class BokehPlot(metaclass=ABCMeta): """Base class for bokeh plots""" def __init__( self, use_notebook=None, autoscale=True, cmap="inferno", norm="lin", **figure_kwargs, ): # only use autoshow / use_notebook by default if we are in a notebook self._use_notebook = use_notebook if use_notebook is not None else is_notebook( ) self._patches = None self._handle = None self._color_bar = None self._color_mapper = None self._palette = None self._annotations = [] self._labels = [] self.cmap = cmap self.norm = norm self.autoscale = autoscale self.datasource = ColumnDataSource(data={}) self.figure = figure(**figure_kwargs) self.figure.add_tools( HoverTool(tooltips=[("id", "@id"), ("value", "@values")])) if figure_kwargs.get("match_aspect"): # Make sure the box zoom tool does not distort the camera display for tool in self.figure.toolbar.tools: if isinstance(tool, BoxZoomTool): tool.match_aspect = True def show(self): """Display the figure""" if self._use_notebook: output_notebook() else: # this only sets the default name, created only when show is called output_file( tempfile.mktemp(prefix="ctapipe_bokeh_", suffix=".html")) self._handle = show(self.figure, notebook_handle=self._use_notebook) def update(self): """Update the figure""" if self._use_notebook and self._handle: push_notebook(handle=self._handle) def add_colorbar(self): self._color_bar = ColorBar( color_mapper=self._color_mapper, label_standoff=12, border_line_color=None, location=(0, 0), ) self.figure.add_layout(self._color_bar, "right") self.update() def set_limits_minmax(self, zmin, zmax): """Set the limits of the color range to ``zmin`` / ``zmax``""" self._color_mapper.update(low=zmin, high=zmax) self.update() def set_limits_percent(self, percent=95): """Set the limits to min / fraction of max value""" low = np.nanmin(self.datasource.data["values"]) high = np.nanmax(self.datasource.data["values"]) frac = percent / 100.0 self.set_limits_minmax(low, high - (1.0 - frac) * (high - low)) @property def cmap(self): """Get the current colormap""" return self._palette @cmap.setter def cmap(self, cmap): """Set colormap""" if isinstance(cmap, str): cmap = palette_from_mpl_name(cmap) self._palette = cmap # might be called in __init__ before color mapper is setup if self._color_mapper is not None: self._color_mapper.palette = cmap self._trigger_cm_update() self.update() def _trigger_cm_update(self): # it seems changing palette does not trigger a color change, # so we reassign a property if isinstance(self._color_mapper, CategoricalColorMapper): self._color_mapper.update(factors=self._color_mapper.factors) else: self._color_mapper.update(low=self._color_mapper.low) def clear_overlays(self): """Remove any added overlays from the figure""" while self._annotations: self.figure.renderers.remove(self._annotations.pop()) while self._labels: self.figure.center.remove(self._labels.pop()) def rescale(self): """Scale pixel colors to min/max range""" low = self.datasource.data["values"].min() high = self.datasource.data["values"].max() # force color to be at lower end of the colormap if # data is all equal if low == high: high += 1 self.set_limits_minmax(low, high) @property def norm(self): """ The norm instance of the Display Possible values: - "lin": linear scale - "log": log scale (cannot have negative values) - "symlog": symmetric log scale (negative values are ok) """ return self._color_mapper @norm.setter def norm(self, norm): """Set the norm""" if not isinstance(norm, ContinuousColorMapper): if norm == "lin": norm = LinearColorMapper elif norm == "log": norm = LogColorMapper else: raise ValueError(f"Unsupported norm {norm}") self._color_mapper = norm(self.cmap) if self._patches is not None: color = dict(transform=self._color_mapper) self._patches.glyph.update(fill_color=color, line_color=color) if self._color_bar is not None: self._color_bar.update(color_mapper=self._color_mapper) self.update()
p = figure(width=800, height=300, title="US unemployment 1948—2016", x_range=list(data.index), y_range=list(reversed(data.columns)), toolbar_location=None, tools="", x_axis_location="above") p.rect(x="Year", y="Month", width=1, height=1, source=source, line_color=None, fill_color=transform('rate', mapper)) color_bar = ColorBar(color_mapper=mapper, ticker=BasicTicker(desired_num_ticks=len(colors)), formatter=PrintfTickFormatter(format="%d%%")) p.add_layout(color_bar, 'right') p.axis.axis_line_color = None p.axis.major_tick_line_color = None p.axis.major_label_text_font_size = "7px" p.axis.major_label_standoff = 0 p.xaxis.major_label_orientation = 1.0 show(p)
def get_figure(year: int): ''' @Author: Haoyang Ding create bokeh figure object :param year: year :return: figure ''' df_year = df[df['year'] == year] # Merge dataframes gdf and df_2016. merged = gdf.merge(df_year, left_on='country_code', right_on='code') # Read data to json. merged_json = json.loads(merged.to_json()) # Convert to String like object. json_data = json.dumps(merged_json) # Input GeoJSON source that contains features for plotting. geosource = GeoJSONDataSource(geojson=json_data) # Define a sequential multi-hue color palette. palette = brewer['RdBu'][11] # Reverse color order so that dark blue is highest obesity. # Instantiate LinearColorMapper that linearly maps numbers in a range, into a sequence of colors. color_mapper = LinearColorMapper(palette=palette, low=-2, high=2) # Define custom tick labels for color bar. tick_labels = { '0': '0°C', '-0.5': '-0.5°C', '-1': '-1°C', '-1.5': '-1.5°C', '-2': '-2°C', '0.5': '0.5°C', '1': '1°C', '1.5': '1.5°C', '2': '2°C' } # Create color bar. color_bar = ColorBar(color_mapper=color_mapper, label_standoff=8, width=500, height=20, border_line_color=None, location=(0, 0), orientation='horizontal', major_label_overrides=tick_labels) # Create figure object. p = figure(title='Surface temperature anomaly (degrees celcius), ' + str(year), plot_height=600, plot_width=950, toolbar_location=None) p.xgrid.grid_line_color = None p.ygrid.grid_line_color = None # Add patch renderer to figure. p.patches('xs', 'ys', source=geosource, fill_color={ 'field': 'temperature', 'transform': color_mapper }, line_color='black', line_width=0.25, fill_alpha=1) # Specify figure layout. p.add_layout(color_bar, 'below') return p
source = ColumnDataSource(dict(x=x, y=y, z=z)) p = figure(plot_width=600, plot_height=600, title="Sum of bill values / week day 0=Monday, 6=Sunday") p.circle(x='x', y='y', line_color=mapper, color=mapper, fill_alpha=1, size=10, source=source) color_bar = ColorBar(color_mapper=mapper['transform'], width=8, location=(0, 0)) p.add_layout(color_bar, 'right') show(p) output_file("bills per hour.html", title="Sum of bill values per hour") x = grouped_filtered_value_and_time.loc[:, 'T'] y = grouped_filtered_value_and_time.loc[:, 'RFV'] z = grouped_filtered_value_and_time.loc[:, 'S'] #Use the field name of the column source mapper = linear_cmap(field_name='z', palette=Spectral6,
def heatmap_viz( df: pd.DataFrame, x: str, y: str, grp_cnt_stats: Dict[str, int], plot_width: int, plot_height: int, max_lbl_len: int = 15, ) -> Panel: """ Render a heatmap """ # pylint: disable=too-many-arguments title = _make_title(grp_cnt_stats, x, y) source = ColumnDataSource(data=df) palette = BIPALETTE[(len(BIPALETTE) // 2 - 1):] mapper = LinearColorMapper(palette=palette, low=df["cnt"].min() - 0.01, high=df["cnt"].max()) if grp_cnt_stats["x_show"] > 60: plot_width = 16 * grp_cnt_stats["x_show"] if grp_cnt_stats["y_show"] > 10: plot_height = 70 + 18 * grp_cnt_stats["y_show"] fig = figure( x_range=list(set(df["x"])), y_range=list(set(df["y"])), toolbar_location=None, tools=[], x_axis_location="below", title=title, plot_width=plot_width, plot_height=plot_height, ) renderer = fig.rect( x="x", y="y", width=1, height=1, source=source, line_color=None, fill_color=transform("cnt", mapper), ) color_bar = ColorBar( color_mapper=mapper, location=(0, 0), ticker=BasicTicker(desired_num_ticks=7), formatter=PrintfTickFormatter(format="%d"), ) fig.add_tools( HoverTool( tooltips=[ (x, "@x"), (y, "@y"), ("Count", "@cnt"), ], mode="mouse", renderers=[renderer], )) fig.add_layout(color_bar, "right") tweak_figure(fig, "heatmap") fig.yaxis.formatter = FuncTickFormatter(code=""" if (tick.length > %d) return tick.substring(0, %d-2) + '...'; else return tick; """ % (max_lbl_len, max_lbl_len)) return Panel(child=fig, title="heat map")
p.axis.major_label_text_font_size = "5pt" p.axis.major_label_standoff = 0 p.xaxis.major_label_orientation = pi / 3 p.rect(x='B1', y='B2', width=1, height=1, source=source, fill_color={ 'field': 'corr', 'transform': mapper }, line_color=None) color_bar = ColorBar(color_mapper=mapper, major_label_text_font_size="5pt", ticker=BasicTicker(desired_num_ticks=len(colors)), formatter=PrintfTickFormatter(format="%f"), label_standoff=6, border_line_color=None, location=(0, 0)) p.add_layout(color_bar, 'right') p.select_one(HoverTool).tooltips = [ ('B1', '@B1'), ('B2', '@B2'), ('corr', '@corr'), ] show(p)
p.axis.major_label_text_font_size = "5pt" p.axis.major_label_standoff = 0 p.xaxis.major_label_orientation = np.pi / 3 p.rect('xname', 'yname', 0.9, 0.9, source=data, line_color=None, hover_line_color='black', alpha='alphas') mapper = LinearColorMapper(palette=Magma6, low=0, high=1) color_bar = ColorBar(color_mapper=mapper, border_line_color=None, location=(0, 0)) data1 = dict( xname=xname, yname=yname, count=counts, ) plot = figure(title="Matrix Author Similarity", x_axis_location="above", x_range=list(reversed(names1)), y_range=names1, toolbar_location='below') hover = HoverTool(tooltips=[('Names', '@yname, @xname'), ('Value', '@count')]) plot.add_tools(hover)
def cluster_usage(): from bokeh.io import show, output_notebook, push_notebook from bokeh.resources import CDN from bokeh.plotting import figure from bokeh.models import ( ColumnDataSource, HoverTool, LinearColorMapper, BasicTicker, ColorBar, ) output_notebook(resources=CDN) # Initial values source = ColumnDataSource( data={ "node_ip_address": ['127.0.0.1'], "time": ['0.5'], "num_tasks": ['1'], "length": [1] }) # Define the color schema colors = [ "#75968f", "#a5bab7", "#c9d9d3", "#e2e2e2", "#dfccce", "#ddb7b1", "#cc7878", "#933b41", "#550b1d" ] mapper = LinearColorMapper(palette=colors, low=0, high=2) TOOLS = "hover, save, xpan, box_zoom, reset, xwheel_zoom" # Create the plot p = figure(title="Cluster Usage", y_range=list(set(source.data['node_ip_address'])), x_axis_location="above", plot_width=900, plot_height=500, tools=TOOLS, toolbar_location='below') # Format the plot axes p.grid.grid_line_color = None p.axis.axis_line_color = None p.axis.major_tick_line_color = None p.axis.major_label_text_font_size = "10pt" p.axis.major_label_standoff = 0 p.xaxis.major_label_orientation = np.pi / 3 # Plot rectangles p.rect(x="time", y="node_ip_address", width="length", height=1, source=source, fill_color={ "field": "num_tasks", "transform": mapper }, line_color=None) # Add legend to the side of the plot color_bar = ColorBar(color_mapper=mapper, major_label_text_font_size="8pt", ticker=BasicTicker(desired_num_ticks=len(colors)), label_standoff=6, border_line_color=None, location=(0, 0)) p.add_layout(color_bar, "right") # Define hover tool p.select_one(HoverTool).tooltips = [ ("Node IP Address", "@node_ip_address"), ("Number of tasks running", "@num_tasks"), ("Time", "@time") ] # Define the axis labels p.xaxis.axis_label = "Time in seconds" p.yaxis.axis_label = "Node IP Address" handle = show(p, notebook_handle=True) workers = ray.global_state.workers() # Function to update the heat map def heat_map_update(abs_earliest, abs_latest, abs_num_tasks, tasks): if len(tasks) == 0: return earliest = time.time() latest = 0 node_to_tasks = dict() # Determine which task has the earlest start time out of the ones # passed into the update function for task_id, data in tasks.items(): if data["score"] > latest: latest = data["score"] if data["score"] < earliest: earliest = data["score"] worker_id = data["worker_id"] node_ip = workers[worker_id]["node_ip_address"] if node_ip not in node_to_tasks: node_to_tasks[node_ip] = {} node_to_tasks[node_ip][task_id] = data nodes = [] times = [] lengths = [] num_tasks = [] for node_ip, task_dict in node_to_tasks.items(): left, right, top = compute_utilizations(earliest, latest, abs_num_tasks, task_dict, 100, True) for (l, r, t) in zip(left, right, top): nodes.append(node_ip) times.append((l + r) / 2) lengths.append(r - l) num_tasks.append(t) # Set the y range of the plot to be the node IP addresses p.y_range.factors = list(set(nodes)) mapper.low = min(min(num_tasks), 0) mapper.high = max(max(num_tasks), 1) # Update plot with new data based on slider and text box values source.data = { "node_ip_address": nodes, "time": times, "num_tasks": num_tasks, "length": lengths } push_notebook(handle=handle) get_sliders(heat_map_update)
def normal2d(X, Y, sigx=1.0, sigy=1.0, mux=0.0, muy=0.0): z = (X - mux)**2 / sigx**2 + (Y - muy)**2 / sigy**2 return np.exp(-z / 2) / (2 * np.pi * sigx * sigy) X, Y = np.mgrid[-3:3:100j, -2:2:100j] Z = normal2d(X, Y, 0.1, 0.2, 1.0, 1.0) + 0.1 * normal2d(X, Y, 1.0, 1.0) image = Z * 1e6 color_mapper = LogColorMapper(palette="Viridis256", low=1, high=1e7) plot = figure(x_range=(0, 1), y_range=(0, 1), toolbar_location=None) plot.image(image=[image], color_mapper=color_mapper, dh=[1.0], dw=[1.0], x=[0], y=[0]) color_bar = ColorBar(color_mapper=color_mapper, ticker=LogTicker(), label_standoff=12, border_line_color=None, location=(0, 0)) plot.add_layout(color_bar, 'right') show(plot)
path = Label(x=-76.3, y=31.4, angle=-36.5, angle_units="deg", text="Solar eclipse path of totality", text_baseline="middle", text_font_size="8pt", text_color="silver") p.add_layout(path) color_bar = ColorBar(color_mapper=mapper, location="bottom_left", orientation="horizontal", title="Popularity of \"solar eclipse\" search term", title_text_font_size="12pt", title_text_font_style="bold", title_text_color="lightgrey", major_label_text_color="lightgrey", background_fill_alpha=0.0) p.add_layout(color_bar) notes = Label( x=0, y=0, x_units="screen", y_units="screen", x_offset=40, y_offset=20, text="Source: Google Trends, NASA Scientific Visualization Studio", level="overlay",
def NLD_processing(df): # get original column names from df list_columns_names = df.columns # change the column labels from strings to integers list_columns_int = [] for number in range(0, len(df.index.values)): list_columns_int.append(number) df.columns = list_columns_int # change the rows labels/ indexes from strings to integers df['index'] = list_columns_int df.set_index("index", inplace=True) # Making a function to map color to edges color_palette = list(reversed(Viridis11[:8])) w_max = df.values.max() w_min = df.values.min() step = (w_max - w_min) / (len(color_palette) - 1) colors = [] # Create a graph with 1-way edges for faster painting g = nx.DiGraph() for row in df.index.values: g.add_node(row) for column in df.index.values: if row < column: if (df[row][column] > 0): color_index = int((df[row][column] - w_min) / step) g.add_edge(row, column, weight=df[row][column], color=color_palette[color_index]) colors.append(color_palette[color_index]) weights = [] # Create a separate graph with 2-way edges only to calculate weights g_w = nx.DiGraph() for row in df.index.values: g_w.add_node(row) for column in df.index.values: if row != column: if (df[row][column] > 0): g_w.add_edge(row, column, weight=df[row][column], color=color_palette[color_index]) weights.append(df[row][column]) # do not draw edges with different widths if the max weight is too big if max(weights) > 30: for index, w in enumerate(weights): weights[index] = 1 # loop over all nodes to find neighbors and set min, max, sum for egdes weights connected to a node node_w_dict = {} for n in list_columns_int: node_weight_list = [] for nb in nx.neighbors(g_w, n): node_weight_list.append( nx.get_edge_attributes(g_w, 'weight')[n, nb]) len_list = len(node_weight_list) if len_list != 0: node_min_weight = min(node_weight_list) node_max_weight = max(node_weight_list) node_sum_weight = sum(node_weight_list) node_avr_weight = node_sum_weight / len_list else: node_min_weight = 0 node_max_weight = 0 node_sum_weight = 0 node_avr_weight = 0 node_w_dict.update({ n: { 'minweight': node_min_weight, 'maxweight': node_max_weight, 'avrweight': node_avr_weight, 'sumweight': node_sum_weight } }) nx.set_node_attributes(g, node_w_dict) # Making a function to map node size deg_node_size_list = [ 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30 ] deg_max = max(list(list(zip(*g.degree))[1])) deg_min = min(list(list(zip(*g.degree))[1])) deg_step = (deg_max - deg_min) / (len(deg_node_size_list) - 1) i = 0 node_s_dict = {} for node in list(list(zip(*g.degree))[0]): deg_index = int( (list(list(zip(*g.degree))[1])[i] - deg_min) / deg_step) node_s_dict.update({node: {'nodesize': deg_node_size_list[deg_index]}}) i += 1 nx.set_node_attributes(g, node_s_dict) # create a dictoinary with double for loop mapping = { old_label: new_label for old_label, new_label in itertools.zip_longest( sorted(g.nodes()), list_columns_names, fillvalue=1) } # relabel the names of the nodes from integers back to strings nx.relabel_nodes(g, mapping, copy=False) # Organize common layouts' size for NLD NLD_width = 780 NLD_height = 690 color_mapper = LinearColorMapper(palette=color_palette, low=w_min, high=w_max) color_bar = ColorBar(color_mapper=color_mapper, border_line_color=None, location=(0, 0)) # circular layout plot_circle = Plot(plot_width=NLD_width, plot_height=NLD_height, x_range=Range1d(-1.1, 1.1), y_range=Range1d(-1.1, 1.1)) graph_circle = NLD_pocessing_graph(g, weights, colors, nx.circular_layout) NLD_add_tools(plot_circle) plot_circle.add_layout(color_bar, 'right') plot_circle.renderers.append(graph_circle) # spring layout plot_spring = Plot(plot_width=NLD_width, plot_height=NLD_height, x_range=Range1d(-1.1, 1.1), y_range=Range1d(-1.1, 1.1)) graph_spring = NLD_pocessing_graph(g, weights, colors, nx.spring_layout) NLD_add_tools(plot_spring) plot_spring.add_layout(color_bar, 'right') plot_spring.renderers.append(graph_spring) # force-directed layout plot_fd = Plot(plot_width=NLD_width, plot_height=NLD_height, x_range=Range1d(-1.1, 1.1), y_range=Range1d(-1.1, 1.1)) graph_fd = NLD_FD_pocessing_graph(g, weights, colors) NLD_add_tools(plot_fd) plot_fd.add_layout(color_bar, 'right') plot_fd.renderers.append(graph_fd) # random layout plot_random = Plot(plot_width=NLD_width, plot_height=NLD_height, x_range=Range1d(-0.1, 1.1), y_range=Range1d(-0.1, 1.1)) graph_random = NLD_random_processing_graph(g, weights, colors, nx.random_layout) NLD_add_tools(plot_random) plot_random.add_layout(color_bar, 'right') plot_random.renderers.append(graph_random) # Create panels for each layout circle_panel = Panel(child=plot_circle, title='Circle layout') spring_panel = Panel(child=plot_spring, title='Spring layout') random_panel = Panel(child=plot_random, title='Random layout') fd_panel = Panel(child=plot_fd, title='Force-Directed layout') # Assign NLD panels to Tabs tabsNLD_int = Tabs( tabs=[circle_panel, spring_panel, fd_panel, random_panel]) return tabsNLD_int
# Make colormap #palette = tuple([p_county_map for p_county_map in palette]+['#ffffee']) # palette = Reverse(Inferno256[128:-1:5]) palette = Turbo256[128:-1:5] CmapAndTicks = make_color_mapper_and_ticks(palette=palette, low=0, high=20 * len(palette), label_format='{:1.0f}') color_mapper = CmapAndTicks['color_mapper'] color_bar = ColorBar( color_mapper=CmapAndTicks['color_mapper'], ticker=CmapAndTicks['ticker'], formatter=CmapAndTicks['formatter'], label_standoff=2, border_line_color=None, location=(0, 0), bar_line_alpha=0.5, major_label_text_align='left', ) # %% Make Buttons for state graph """ # %% Make Buttons for state graph ________________________________________________________________________________ """ buttons = {} buttons['state_covid_data'] = Toggle(label="State Time History Graph", visible=False, button_type='primary') # buttons['state_covid_data'].js_on_change( 'active',
def map_create(prot_pop_geo, prot_pop): geosource = GeoJSONDataSource( geojson=simplejson.dumps(simplejson.loads(prot_pop_geo.to_json()))) # ----- Raw count map ----- # initialize figure palette = cividis(256) hover_a = HoverTool(tooltips=[('Country', '@name'), ('Protests', '@protest')]) color_mapper_a = LogColorMapper(palette=palette, low=1, high=prot_pop['protest'].max() + 5, nan_color='#ffffff') color_bar_a = ColorBar( color_mapper=color_mapper_a, ticker=LogTicker(), orientation='horizontal', border_line_color=None, location=(0, 0), label_standoff=8, major_label_text_font='Raleway', major_label_text_font_size='12pt', title='Number of registered Fridays for Future protests', title_text_font_style='normal', title_text_font='Raleway', title_text_font_size='15pt') p_a = figure( title= 'The Fridays for Future movement grew to global scale within only 10 months', tools=[hover_a, ZoomInTool(), ZoomOutTool(), ResetTool(), PanTool()], plot_height=600, plot_width=980) # add patch renderer p_a.patches('xs', 'ys', source=geosource, fill_color={ 'field': 'protest', 'transform': color_mapper_a }, line_color='black', line_width=0.25, fill_alpha=1) # prettify p_a.xgrid.grid_line_color = None p_a.ygrid.grid_line_color = None p_a.outline_line_color = None p_a.axis.visible = False p_a.add_layout(color_bar_a, 'below') p_a.toolbar.logo = None p_a.title.text_font = "Raleway" p_a.title.text_font_style = "normal" p_a.title.align = 'center' p_a.title.text_color = 'black' p_a.title.text_font_size = '20pt' tab_a = Panel(child=p_a, title="Absolute number") # ----- Population adjusted count map ----- # initialize figure hover_b = HoverTool(tooltips=[( 'Country', '@name'), ('Protests per 10 million', '@prot_ptm'), ('Protests', '@protest'), ('Population', '@population')]) color_mapper_b = LogColorMapper( palette=palette, low=prot_pop['prot_ptm'].min(), high=float(prot_pop.loc[prot_pop['code'] == 'GRL']['prot_ptm']) + 10, nan_color='#ffffff') color_bar_b = ColorBar( color_mapper=color_mapper_b, ticker=LogTicker(), orientation='horizontal', border_line_color=None, location=(0, 0), label_standoff=8, major_label_text_font='Raleway', major_label_text_font_size='12pt', title='Number of registered Fridays for Future protests per 10 million', title_text_font_style='normal', title_text_font='Raleway', title_text_font_size='15pt') p_b = figure( title= 'The Fridays for Future movement grew to global scale within only 10 months', tools=[hover_b, ZoomInTool(), ZoomOutTool(), ResetTool(), PanTool()], plot_height=600, plot_width=980) # add patch renderer p_b.patches('xs', 'ys', source=geosource, fill_color={ 'field': 'prot_ptm', 'transform': color_mapper_b }, line_color='black', line_width=0.25, fill_alpha=1) # prettify p_b.xgrid.grid_line_color = None p_b.ygrid.grid_line_color = None p_b.outline_line_color = None p_b.axis.visible = False p_b.add_layout(color_bar_b, 'below') p_b.toolbar.logo = None p_b.title.text_font = "Raleway" p_b.title.text_font_style = "normal" p_b.title.align = 'center' p_b.title.text_color = 'black' p_b.title.text_font_size = '20pt' tab_b = Panel(child=p_b, title="Population normalized") tabs = Tabs(tabs=[tab_a, tab_b]) return tabs
def GDP_PCA_plot(filename=None, threshold=0.015, lowerbound=2.0, upperbound=1.0e4, factor=0.08): data = np.load('uploads/' + filename) image1 = data.f.image #-np.median(data.f.image) image2 = np.array(image1 * 255 / image1.max(), dtype='uint8') image_avg = np.mean(np.partition(image2, int(len(image2) * 0.2))) image2[image2 < image_avg] = int(image_avg) #H1=cv2.GaussianBlur(image2,(3,3),1.0*np.std(image2)) H1 = gaussian_filter(image2, factor * np.std(image2), mode='nearest') image2 = H1 blobs_log = blob_log(image2, max_sigma=0.3 * np.std(image2), min_sigma=0.02 * np.mean(image2), num_sigma=20, threshold=threshold, overlap=0.6) blobs_log[:, 2] = blobs_log[:, 2] * np.sqrt(2) blobs = blobs_log[(blobs_log[:, 2] > lowerbound) & (blobs_log[:, 2] < upperbound)] xx = (data.f.X.min(), np.round(data.f.X.max(), -1)) yy = (data.f.Y.min(), np.round(data.f.Y.max(), -1)) x_step = (xx[1] - xx[0]) / np.shape(H1)[0] y_step = (yy[1] - yy[0]) / np.shape(H1)[1] #Number of NV height = yy[1] - yy[0] width = xx[1] - xx[0] total = len(blobs) per_nv = round(len(blobs) / float(height * width) * (20 * 20), 2) ######################################################## t = [ 'Original Density Plot,' ' Filename=' + filename, 'Gaussian Filtered Density Plot', 'Total NVs =' + str(total) + ' , NVs per 20x20 pixel area = ' + str(per_nv) ] data_list = [image1, H1, H1] color_list = [ Viridis256, cc.b_linear_bgy_10_95_c74, cc.b_linear_bgy_10_95_c74 ] return_list = [] return_list.append(head) #hover tool hack to work for image function in bokeh. ##http://stackoverflow.com/questions/28176949/convert-list-of-tuples-to-structured-numpy-array px = np.linspace(xx[0], xx[1], np.shape(H1)[0] / 2) py = np.linspace(yy[0], yy[1], np.shape(H1)[1] / 2) px = np.array(px, dtype='uint32') py = np.array(py, dtype='uint32') a = [] for i in px: a.extend(zip(itertools.repeat(i), py)) dt = np.dtype('int,float') X = np.array(a, dtype=dt) x1 = X['f0'] y1 = X['f1'] ################################################################## for i in range(3): color_mapper = LogColorMapper(palette=color_list[i], \ low=np.mean(data_list[i]), \ high=1.0*np.mean(data_list[i])+\ 2.0*np.std(data_list[i])) color_bar = ColorBar(color_mapper=color_mapper,\ label_standoff=12, \ border_line_color=None, \ location=(0,0)) p1 = figure(plot_width=600, plot_height=600,title=t[i],title_text_font_size='12pt',\ x_range=xx,y_range=xx,tools=TOOLS,toolbar_location="below",toolbar_sticky=False,responsive=True) p1.square(x1, y1, alpha=1.0) p1.image(image=[data_list[i]], color_mapper=color_mapper, dh=yy[1] - yy[0], dw=xx[1] - xx[0], x=xx[0], y=xx[0]) p1.add_layout(color_bar, 'right') if i == 2: p1.circle(blobs[:, 1] * x_step + xx[0], blobs[:, 0] * y_step + yy[0], radius=blobs[:, 2] * 1.6, radius_dimension='y', line_color='red', alpha=1.0, line_width=3, fill_color=None) p1.title.text_font_size = "11pt" p1.xaxis.axis_label_text_font_size = "13pt" p1.yaxis.axis_label_text_font_size = "13pt" #plots = {'Navy': p1, 'Blue': p2}; tuple_plot = components(p1) #script2, div2 = components(p2); return_list.append(list(tuple_plot)) p=Histogram(blobs[:,2],\ plot_width=600, plot_height=600,tools=TOOLS,\ toolbar_location="below",toolbar_sticky=False,\ responsive=True,\ title="Distribution of Radii of NV Centers") return_list.append(list(components(p))) return return_list
def bokehSec(data, subject, fname, lat, lon, depth, variabels): TOOLS = "hover,crosshair,pan,wheel_zoom,zoom_in,zoom_out,box_zoom,undo,redo,reset,tap,save,box_select,poly_select,lasso_select," w = 1000 h = 500 p = [] data_org = list(data) for ind in range(len(data_org)): data = data_org[ind] bounds = getBounds(variabels[ind]) paletteName = getPalette(variabels[ind]) if bounds[0] == None: color_mapper = LinearColorMapper(palette=paletteName) else: color_mapper = LinearColorMapper(palette=paletteName, low=bounds[0], high=bounds[1]) if len(lon) > len(lat): p1 = figure(tools=TOOLS, toolbar_location="above", title=subject[ind], plot_width=w, plot_height=h, x_range=(np.min(lon), np.max(lon)), y_range=(np.min(depth), np.max(depth))) data = np.nanmean(data, axis=0) data = np.transpose(data) data = np.squeeze(data) p1.xaxis.axis_label = 'Longitude' p1.image(image=[data], color_mapper=color_mapper, x=np.min(lon), y=np.max(depth), dw=np.max(lon) - np.min(lon), dh=np.max(depth) - np.min(depth)) else: p1 = figure(tools=TOOLS, toolbar_location="above", title=subject[ind], plot_width=w, plot_height=h, x_range=(np.min(lat), np.max(lat)), y_range=(np.min(depth), np.max(depth))) data = np.nanmean(data, axis=1) data = np.transpose(data) data = np.squeeze(data) p1.xaxis.axis_label = 'Latitude' ''' if ind==0: data1 = data if ind==1: data = data / data1 ''' p1.image(image=[data], color_mapper=color_mapper, x=np.min(lat), y=np.min(depth), dw=np.max(lat) - np.min(lat), dh=np.max(depth) - np.min(depth)) p1.yaxis.axis_label = 'depth [m]' color_bar = ColorBar(color_mapper=color_mapper, ticker=BasicTicker(), label_standoff=12, border_line_color=None, location=(0, 0)) p1.add_layout(color_bar, 'right') p.append(p1) dirPath = 'embed/' if not os.path.exists(dirPath): os.makedirs(dirPath) output_file(dirPath + fname + ".html", title="Regional Map") show(column(p)) return
mapper = LinearColorMapper(palette=colors, low=0, high=40) TOOLS_vitesse = "hover,save,pan,box_zoom,reset,wheel_zoom" Vitesses = figure(plot_width=597, plot_height=370, x_axis_type='datetime', y_range=DAYS, tools=TOOLS_vitesse) Vitesses.grid.grid_line_color = None Vitesses.axis.major_tick_line_color = None Vitesses.xaxis[0].formatter.days = ['%Hh'] Vitesses.x_range.range_padding = 0 # barre de légende bar = ColorBar(color_mapper=mapper, location=(0, -10), major_label_text_font_size="5pt", width=5, height=335) Vitesses.add_layout(bar, 'right') tab_vitesses = Panel(child=Vitesses, title="Vitesses Moyennes") Vitesses.select_one(HoverTool).tooltips = [ ('vitesse moyenne', '@rate'), ] # données du graphe de vitesses VitessesChart = Vitesses.rect(x='heure', y='Jour', width=1800000, height=1, source=VitesseSource, fill_color={
def draw_blocks_incidents(new, traffic): ''' By taking in the incidents' area information, we create a plot with the areas boundaries. The colors filled is based on the number of incidents happened in the area. If there are more incidents, the color will be darker. :param new: the dataframe contains cleaned incidents information by area :param traffic: the dataframe will full traffic incidents information :param fname: the output filename :return: a html file contains the blocks of Los Angeles areas ''' assert isinstance(new, pd.DataFrame) assert isinstance(traffic, pd.DataFrame) new_area = list(dict(new.groupby('Area_Name')['Area_Name'].count())) incidents_counter = [0] * len(new_area) for i in range(traffic.shape[0]): for j in range(len(new_area)): if (traffic['lon'][i] >= new['min_lon'][j]) & (traffic['lon'][i] <= new['max_lon'][j]) & ( traffic['lat'][i] >= new['min_lat'][j]) & (traffic['lat'][i] <= new['max_lat'][j]): incidents_counter[j] += 1 area_dict = dict(zip(new_area, incidents_counter)) area_dict['Southeast'] += 3187 area_dict['West LA'] += 1361 sorted_by_value = sorted(area_dict.items(), key=lambda kv: kv[1], reverse=True) checklist = [] for i in sorted_by_value: checklist.append(i[0]) max_lons = [] min_lons = [] max_lats = [] min_lats = [] for i in checklist: max_lons.append(float(new[new['Area_Name'] == i]['max_lon'])) min_lons.append(float(new[new['Area_Name'] == i]['min_lon'])) max_lats.append(float(new[new['Area_Name'] == i]['max_lat'])) min_lats.append(float(new[new['Area_Name'] == i]['min_lat'])) io.output_notebook() palettes = inferno(120) final_palettes = [] count = 0 for i in palettes: count += 1 if count % 10 == 0: final_palettes.append(i) #all_palettes['Reds'][9] p = figure(plot_width=450, plot_height=400) p.quad(top=max_lons, bottom=min_lons, left=min_lats, right=max_lats, color=final_palettes, fill_alpha=0.8) color_mapper = LogColorMapper(palette=final_palettes) color_bar = ColorBar(color_mapper=color_mapper, location=(0, 0)) p.add_layout(color_bar, 'left') return show(p)
p1.legend.location = "bottom_right" p1.legend.title = 'AOI' p1.y_range.flipped = True # In[10]: # fixation heatmap source_heat = ColumnDataSource( data=dict(x=[], y=[], color=[], user=[], gradient=[])) mapper = LinearColorMapper(palette="Turbo256", low=33, high=1200, low_color="blue", high_color="red") color_bar = ColorBar(color_mapper=mapper, width=8, location=(0, 0)) p2 = figure(title="Fixation heat map", plot_width=p1.plot_width, plot_height=p1.plot_width, tools=TOOLS, tooltips=TOOLTIPS, x_range=p1.x_range, y_range=p1.y_range, sizing_mode="scale_both", x_axis_label='x-axis', y_axis_label='y-axis') p2.circle(x="x", y="y", source=source, size=10,
def _contour_data(self): """ Create a contour plot. Parameters ---------- None Returns ------- Bokeh Image Plot """ resolution = self.resolution # Output data array initialization y_data = np.zeros((resolution, resolution, self.num_outputs)) self.input_point_list = [ point.value for point in self.slider_dict.values() ] # Pass the dict to make predictions and then reshape the output to # (resolution, resolution, number of outputs) y_data[:, :, :] = self._make_predictions( self._contour_data_calcs()).reshape( (resolution, resolution, self.num_outputs)) # Use the output variable to pull the correct column of data from the predicted # data (y_data) self.Z = y_data[:, :, self.output_variable] # Reshape it to be 2D self.Z = self.Z.reshape(resolution, resolution) # Update the data source with new data self.contour_plot_source.data = dict(z=[self.Z]) # Min to max of training data self.contour_x_range = xlins = self.xlins_mesh self.contour_y_range = ylins = self.ylins_mesh # Color bar formatting color_mapper = LinearColorMapper(palette="Viridis11", low=np.amin(self.Z), high=np.amax(self.Z)) color_bar = ColorBar(color_mapper=color_mapper, ticker=BasicTicker(), label_standoff=12, location=(0, 0)) # Contour Plot self.contour_plot = contour_plot = figure( match_aspect=False, tooltips=[(self.x_input_select.value, "$x"), (self.y_input_select.value, "$y"), (self.output_select.value, "@z")], tools='') contour_plot.x_range.range_padding = 0 contour_plot.y_range.range_padding = 0 contour_plot.plot_width = 600 contour_plot.plot_height = 500 contour_plot.xaxis.axis_label = self.x_input_select.value contour_plot.yaxis.axis_label = self.y_input_select.value contour_plot.min_border_left = 0 contour_plot.add_layout(color_bar, 'right') contour_plot.x_range = Range1d(min(xlins), max(xlins)) contour_plot.y_range = Range1d(min(ylins), max(ylins)) contour_plot.image(image='z', source=self.contour_plot_source, x=min(xlins), y=min(ylins), dh=(max(ylins) - min(ylins)), dw=(max(xlins) - min(xlins)), palette="Viridis11") # Adding training data points overlay to contour plot if self.is_structured_meta_model: data = self._structured_training_points() else: data = self._unstructured_training_points() if len(data): # Add training data points overlay to contour plot data = np.array(data) if self.is_structured_meta_model: self.contour_training_data_source.data = dict( x=data[:, 0], y=data[:, 1], z=self.meta_model.training_outputs[ self.output_select.value].flatten()) else: self.contour_training_data_source.data = dict( x=data[:, 0], y=data[:, 1], z=self.meta_model._training_output[ self.output_select.value]) training_data_renderer = self.contour_plot.circle( x='x', y='y', source=self.contour_training_data_source, size=5, color='white', alpha=0.50) self.contour_plot.add_tools( HoverTool(renderers=[training_data_renderer], tooltips=[ (self.x_input_select.value + " (train)", '@x'), (self.y_input_select.value + " (train)", '@y'), (self.output_select.value + " (train)", '@z'), ])) return self.contour_plot
nan_color='white') plot = figure(title='Temperature @ 1km, hour 1', x_axis_label='Longitude', y_axis_label='Latitude', x_range=(0, 500), y_range=(0, 500), toolbar_location=None) plot.image(image=[np.flipud(image)], color_mapper=color_mapper, dh=[500], dw=[500], x=[0], y=[0]) color_bar = ColorBar(title='T [ºC]', color_mapper=color_mapper, ticker=BasicTicker(), label_standoff=12, border_line_color=None, location=(0, 0)) plot.add_layout(color_bar, 'left') output_file('task4.html') show(plot) ##task 5 U = get_xy(data['Uf01'], 5) V = get_xy(data['Vf01'], 5) W = get_xy(data['Wf01'], 5) #U=get_xy(data['Uf37'], 50) # reproduce plot in assignment #V=get_xy(data['Vf37'], 50) #W=get_xy(data['Wf37'], 50) x_start = np.zeros(100, dtype='float')
def contour_plot_bokeh( model, xlabel=None, ylabel=None, main=None, xlim=(-3.2, 3.2), ylim=(-3.2, 3.2), colour_function="terrain", show=True, show_expt_data=True, figsize=(10, 10), dpi=50, other_factors=None, ): # TODO: show labels of contour plot # https://stackoverflow.com/questions/33533047/how-to-make-a-contour-plot-in-python-using-bokeh-or-other-libs dpi_max = dpi**3.5 N = min(dpi, np.power(dpi_max, 0.5)) h_grid = np.linspace(xlim[0], xlim[1], num=N) v_grid = np.linspace(ylim[0], ylim[1], num=N) H, V = np.meshgrid(h_grid, v_grid) h_grid, v_grid = H.ravel(), V.ravel() pure_factors = model.get_factor_names(level=1) if xlabel is None: xlabel = pure_factors[0] else: xlabel = str(xlabel) if ylabel is None: ylabel = pure_factors[1] else: ylabel = str(ylabel) kwargs = {xlabel: h_grid, ylabel: v_grid} if other_factors is not None and isinstance(other_factors, dict): kwargs = kwargs.update(other_factors) # Look at which factors are included, and pop them out. The remaining # factors are specified at their zero level unspecified_factors = [i for i in pure_factors if i not in kwargs.keys()] for factor in unspecified_factors: kwargs[factor] = np.zeros_like(h_grid) assert sorted(kwargs.keys()) == sorted(pure_factors), ("Not all factors " "were specified.") Z = predict(model, **kwargs) Z = Z.values.reshape(N, N) z_min, z_max = Z.min(), Z.max() levels = np.linspace(z_min, z_max, N) import matplotlib import matplotlib.pyplot as plt from matplotlib.pyplot import clabel, contour matplotlib.use("Agg") # Turn interactive plotting off plt.ioff() CS = contour(H, V, Z, levels=levels, linestyles="dotted") clabel(CS, inline=True, fontsize=10, fmt="%1.0f") # contour_labels = [(float(q._x), float(q._y), float(q._text))\ # for q in CS.labelTexts] # Convert the Matplotlib colour mapper to Bokeh # https://stackoverflow.com/questions/49931311/using-matplotlibs-colormap-for-bokehs-color-bar mapper = getattr(cm, colour_function) colours = (255 * mapper(range(256))).astype("int") colour_palette = [RGB(*tuple(rgb)).to_hex() for rgb in colours] color_mapper = LinearColorMapper(palette=colour_palette, low=z_min, high=z_max) # Another alternative: # https://stackoverflow.com/questions/35315259/using-colormap-with-bokeh-scatter # colors = ["#%02x%02x%02x" % (int(r), int(g), int(b)) for \ # r, g, b, _ in 255*mpl.cm.viridis(mpl.colors.Normalize()(radii))] p = figure( x_range=xlim, y_range=ylim, # https://github.com/bokeh/bokeh/issues/2351 tools="pan,wheel_zoom,box_zoom,box_select,lasso_select,reset,save", ) # Create the image layer source = {"Xax": [h_grid], "Yax": [v_grid], "predictions": [Z]} h_image = p.image( source=source, image="predictions", x=xlim[0], y=ylim[0], dw=xlim[1] - xlim[0], dh=ylim[1] - ylim[0], color_mapper=color_mapper, global_alpha=0.5, # with some transparency name="contour_image", ) h1 = HoverTool( tooltips=[ (xlabel, "@{Xax}{0.4g}"), (ylabel, "@{Yax}{0.4f}"), ("Predicted", "@{predictions}{0.4g}"), ], renderers=[h_image], formatters={ "Predicted": "printf", xlabel: "printf", ylabel: "printf" }, ) color_bar = ColorBar( color_mapper=color_mapper, major_label_text_font_size="8pt", ticker=BasicTicker(max_interval=(z_max - z_min) / N * 2), formatter=PrintfTickFormatter(format="%.2f"), label_standoff=6, border_line_color=None, location=(0, 0), ) p.add_layout(color_bar, "right") # Contour lines using Scipy: # scaler_y = (ylim[1] - ylim[0]) / (N - 1) # scaler_x = (xlim[1] - xlim[0]) / (N - 1) # for level in levels: # contours = measure.find_contours(Z, level) # for contour in contours: # x = contour[:, 1] * scaler_y + ylim[0] # y = contour[:, 0] * scaler_x + xlim[0] for _, cccontour in enumerate(CS.allsegs): if cccontour: x = cccontour[0][:, 0] y = cccontour[0][:, 1] p.line(x, y, line_dash="dashed", color="darkgrey", line_width=1) # TODO: bigger experimental markers # TODO: hover for the data point shows the factor settings for the data point if show_expt_data: source = ColumnDataSource(data=dict( x=model.data[xlabel], y=model.data[ylabel], output=model.data[model.get_response_name()].to_list(), )) h_expts = p.circle( x="x", y="y", color="black", source=source, # linestyle='', # marker='o', size=10, line_width=2, name="experimental_points", ) # custom tooltip for the experimental points h2 = HoverTool( tooltips=[ (xlabel, "$x{0.4g}"), (ylabel, "$y{0.4g}"), ("Actual value", "@{output}{0.4g}"), # why not working??? ], renderers=[h_expts], formatters={ "Actual value": "printf", xlabel: "printf", ylabel: "printf" }, ) h2.point_policy = "snap_to_data" h2.line_policy = "none" # Axis labels: p.xaxis.axis_label_text_font_size = "14pt" p.xaxis.axis_label = xlabel p.xaxis.major_label_text_font_size = "14pt" p.xaxis.axis_label_text_font_style = "bold" p.xaxis.bounds = (xlim[0], xlim[1]) p.yaxis.major_label_text_font_size = "14pt" p.yaxis.axis_label = ylabel p.yaxis.axis_label_text_font_size = "14pt" p.yaxis.axis_label_text_font_style = "bold" p.yaxis.bounds = (ylim[0], ylim[1]) # Add the hover tooltips: p.add_tools(h1) p.add_tools(h2) if show: show_plot(p) return p
def scatter2D( x, y, z, vmin=None, vmax=None, cmax='red', cmin='blue', cundef='grey', cpalete_size=250, ctransform='log', radii=1., lcolor='black', title='Scatterplot', TOOLS='resize,crosshair,pan,wheel_zoom,box_zoom,reset,tap,previewsave,box_select,poly_select,lasso_select', xlabel='X', ylabel='Y', alpha=0.8, outvar='__inds'): """Plot a 2D scaterplot, e.g. data location with bokeh, and allows manual selection of data. Parameters ---------- x, y : array of floats. Coordinates z : array of floats. Variable for color vmin, vmax : floats (Optional, default None, that is data max and min). Value minimum and maximum for colour scale. cmax : string with valid bokeh colour (Optional, default 'red'). Color corresponding to vmax or above cmin : string with valid bokeh colour (Optional, default 'blue'). Color corresponding to vmin cundef : string with valid bokeh colour (Optional, default 'grey'). Color corresponding to values < vmin and undefined cpalete_size : integer (Optional default 250). Size of the colour palete/scale ctransform : string ( Optional, default 'log'). If == 'log' will use log scale to asign colors, otherwise will use linear scale radii : float (Optional, default 1.). Size of the circles plotted lcolor: string (ptional, default 'black'). Color of the circle outline. title: string (Optional, default 'Scatterplot'). Title of the plot TOOLS: string (Optional, default 'resize,crosshair,pan,wheel_zoom,box_zoom,reset,tap,previewsave,box_select,poly_select,lasso_select'). Tools shown in the plot. xlabel: string (Optional, default 'X'). X axis label ylabel: string (Optional, default 'Y'). Y axis label alpha: float (Optional, default 0.8). Transparency of circles background outvar: string (Optional, default '__inds'). Name of the callback variable. Each time you select points in the scatterplot this variable will be updated. Note ------- This function will create a new variable defined by outvar, e.g. '__inds', the firts time you select points. This variable will be overwritten if it already exist. This variable may be overwritten by selecting points in a different plot with same value in the parameter outvar. The selection variable is updated in your python kernel from a javascript (web brouser) using a calling back function. Example ------- >>> pygslib.plothtml.scatter2D( # data x= mydata['Xlocation'], y= mydata['Ylocation'], z= mydata['Primary'], # vmin and max for formating vmin=0.1, vmax=30, # parameters for color cmax = 'red', cmin = 'blue', cundef='grey', cpalete_size=300, ctransform = 'linear', #parameter for circle size radii=0.5, # line color lcolor= 'black', # parameters for plot title='Scatterplot', TOOLS='resize,crosshair,pan,wheel_zoom,box_zoom,reset,tap,previewsave,box_select,poly_select,lasso_select', xlabel='X', ylabel='Y', alpha=0.9, # call back variable outvar='__inds') >>> print " Select some datapoints, e.g. using the tool lasso " >>> print mydata.iloc[__inds,:] """ #prepare data df = pd.DataFrame({'x': x, 'y': y, 'z': z}) df['radii'] = radii df['alpha'] = alpha df['lcolor'] = lcolor if vmin is None: vmin = z.min() if vmax is None: vmax = z.max() assert vmin < vmax source = ColumnDataSource(df) # create a palete. colourscale = pygslib.charttable.Leyend_num(vmin=vmin, vmax=vmax, cmax=cmax, cmin=cmin, undef=cundef, nval=cpalete_size, convert='HEX') palete = colourscale.c.tolist() # create a mapper if ctransform == 'log': assert vmin > 0 and vmax > 0, "vmin/vmax <=0 and using log transform" mapper = LogColorMapper(palette=palete, low=vmin, high=vmax) else: mapper = LinearColorMapper(palette=palete, low=vmin, high=vmax) mapper.low_color = cundef mapper.high_color = cmax # create figure p = bkplt.figure(title=title, tools=TOOLS, toolbar_location='above') p.xaxis.axis_label = xlabel p.yaxis.axis_label = ylabel # colorbar color_bar = ColorBar(color_mapper=mapper, location=(0, 0)) # plot p.scatter(source=source, x="x", y="y", radius='radii', fill_color={ 'field': 'z', 'transform': mapper }, fill_alpha='alpha', line_color='lcolor') p.add_layout(color_bar, 'right') source.callback = CustomJS(args=dict(p=p), code=""" var inds = cb_obj.get('selected')['1d'].indices; var d1 = cb_obj.get('data'); console.log(d1) var kernel = IPython.notebook.kernel; IPython.notebook.kernel.execute("{} = " + inds); """.format(outvar)) bkplt.show(p)
def hexbin_viz( df: pd.DataFrame, x: str, y: str, plot_width: int, plot_height: int, tile_size: Optional[float] = None, ) -> Panel: """ Render a hexbin plot """ # pylint: disable=too-many-arguments,too-many-locals xmin, xmax = df[x].min(), df[x].max() ymin, ymax = df[y].min(), df[y].max() if tile_size is None: tile_size = (xmax - xmin) / 25 title = f"{y} by {x}" aspect_scale = (ymax - ymin) / (xmax - xmin) bins = hexbin( x=df[x], y=df[y], size=tile_size, orientation="flattop", aspect_scale=aspect_scale, ) fig = figure( title=title, tools=[], match_aspect=False, background_fill_color="#f5f5f5", toolbar_location=None, plot_width=plot_width, plot_height=plot_height, ) palette = list(reversed(viridis(256))) rend = fig.hex_tile( q="q", r="r", size=tile_size, line_color=None, source=bins, orientation="flattop", fill_color=linear_cmap( field_name="counts", palette=palette, low=min(bins.counts), high=max(bins.counts), ), aspect_scale=aspect_scale, ) fig.add_tools( HoverTool( tooltips=[("Count", "@counts")], renderers=[rend], )) mapper = LinearColorMapper(palette=palette, low=min(bins.counts), high=max(bins.counts)) color_bar = ColorBar(color_mapper=mapper, width=8, location=(0, 0)) color_bar.label_standoff = 8 fig.add_layout(color_bar, "right") tweak_figure(fig, "hex") fig.xaxis.ticker = list(np.linspace(xmin, xmax, 10)) fig.yaxis.ticker = list(np.linspace(ymin, ymax, 10)) fig.xaxis.axis_label = x fig.yaxis.axis_label = y return Panel(child=fig, title="hexbin plot")
plot = make_plot() tab_doc = Panel(child=column(row(select_feature), row(plot), row(slider_time)), title="Лікарі") tab_bed = Panel(child=column(row(select_feature), row(plot), row(slider_time)), title="Ліжка") tab_equip = Panel(child=column(row(select_feature), row(plot), row(slider_time)), title="Обладнання") tabs = Tabs(tabs=[tab_doc, tab_bed, tab_equip], name='tabs_custom') # label_figures = LabelSet(x='centr_x', y='centr_y', text=select_feature.value, x_offset=5, y_offset=-10, # source=geosource, render_mode='canvas', text_font_size='12px', text_align='left') # plot.add_layout(label_figures) color_bar = ColorBar(color_mapper=color_mapper, label_standoff=8, width=250, height=10, border_line_color=None, background_fill_color='#f7fbff', location=(0, 0), orientation='horizontal', major_label_overrides= make_tick_labels(n=get_max_feature_value_on_day(select_feature.value, slider_time.value_as_date))) plot.add_layout(color_bar, 'above') labels = LabelSet(x='centr_x', y='centr_y', text='ADM1_UA', x_offset=5, y_offset=5, source=geosource, render_mode='canvas', text_font_size='8px', text_align='left') #plot.add_layout(labels) def update_legend_color_bar(feature, day): new_max_color_value = get_max_feature_value_on_day(feature, day) tick_labels = make_tick_labels(new_max_color_value)
def calendar_plot(data, field='ret'): """ return a calendar plot data dataframe with year and month columns field field to plot values Note ----- Prototype copied from bokeh gallery https://bokeh.pydata.org/en/latest/docs/gallery/unemployment.html """ from math import pi from bokeh.models import LinearColorMapper, BasicTicker, PrintfTickFormatter, ColorBar from bokeh.plotting import figure from bokeh.palettes import Spectral df = data.copy() # Type conversion df['year'] = df.year.astype('str') df['month'] = df.month.astype('str') years = list(df.year.unique()) months = [str(x) for x in range(12, 0, -1)] colors = list(reversed(Spectral[6])) mapper = LinearColorMapper(palette=colors, low=df[field].min(), high=df[field].max()) TOOLS = "hover,save,pan,box_zoom,reset,wheel_zoom" p = figure(title="Calendar Plot", x_range=years, y_range=list(reversed(months)), x_axis_location="above", plot_width=1000, plot_height=600, tools=TOOLS, toolbar_location='below', tooltips=[('date', '@year-@month'), ('return', '@{}'.format(field))]) # Axis settings p.grid.grid_line_color = None p.axis.axis_line_color = None p.axis.major_tick_line_color = None p.axis.major_label_text_font_size = "10pt" p.axis.major_label_standoff = 0 p.xaxis.major_label_orientation = pi / 3 p.rect(x="year", y="month", width=1, height=1, source=df, fill_color={ 'field': field, 'transform': mapper }, line_color='black', line_width=0.5, line_alpha=0.3) color_bar = ColorBar(color_mapper=mapper, major_label_text_font_size="8pt", ticker=BasicTicker(desired_num_ticks=len(colors)), formatter=PrintfTickFormatter(format="%d%%"), label_standoff=6, border_line_color=None, location=(0, 0)) p.add_layout(color_bar, 'right') return p
def helper(obs: Observable, plot=None): # Domain-specific rendering if isinstance(obs, GraphObservable): if plot is None: plot = figure(x_range=self.x_rng, y_range=self.y_rng, tooltips=[], width=self.plot_width, height=self.plot_height) plot.axis.visible = False plot.xgrid.grid_line_color = None plot.ygrid.grid_line_color = None renderer = from_networkx(G, layout) plot.renderers.append(renderer) plot.toolbar_location = None if obs.Gd is GraphDomain.nodes: plot.add_tools(HoverTool(tooltips=[('value', '@value'), ('node', '@node')])) plot.renderers[0].node_renderer.data_source.data['node'] = list(map(str, items[0].G.nodes())) plot.renderers[0].node_renderer.data_source.data['value'] = obs.y cmap = LinearColorMapper(palette=self.node_palette, low=self.node_rng[0], high=self.node_rng[1]) self.node_cmaps[obs.plot_id] = cmap if isinstance(obs, gds): plot.renderers[0].node_renderer.data_source.data['thickness'] = [3 if (x in obs.X_dirichlet or x in obs.X_neumann) else 1 for x in obs.X] plot.renderers[0].node_renderer.glyph = Ellipse(height=self.node_size, width=self.node_size, fill_color=field('value', cmap), line_width='thickness') else: plot.renderers[0].node_renderer.glyph = Ellipse(height=self.node_size, width=self.node_size, fill_color=field('value', cmap)) if self.colorbars: cbar = ColorBar(color_mapper=cmap, ticker=BasicTicker(), title='node') cbar.major_label_text_font_size = "15pt" plot.add_layout(cbar, 'right') elif obs.Gd is GraphDomain.edges: plot.add_tools(HoverTool(tooltips=[('value', '@value'), ('edge', '@edge')])) self.prep_layout_data(obs, G, layout) obs.arr_source.data['edge'] = list(map(str, items[0].G.edges())) self.draw_arrows(obs, obs.y) plot.renderers[0].edge_renderer.data_source.data['value'] = obs.arr_source.data['value'] cmap = LinearColorMapper(palette=self.edge_palette, low=self.edge_rng[0], high=self.edge_rng[1]) self.edge_cmaps[obs.plot_id] = cmap arrows = Patches(xs='xs', ys='ys', fill_color=field('value', cmap)) plot.add_glyph(obs.arr_source, arrows) if self.colorbars: cbar = ColorBar(color_mapper=cmap, ticker=BasicTicker(), title='edge') cbar.major_label_text_font_size = "15pt" plot.add_layout(cbar, 'right') if self.edge_colors: plot.renderers[0].edge_renderer.glyph = MultiLine(line_width=5, line_color=field('value', cmap)) elif isinstance(obs, gds): plot.renderers[0].edge_renderer.data_source.data['thickness'] = [3 if (x in obs.X_dirichlet or x in obs.X_neumann) else 1 for x in obs.X] plot.renderers[0].edge_renderer.glyph = MultiLine(line_width='thickness') elif obs.Gd is GraphDomain.faces: plot.add_tools(HoverTool(tooltips=[('value', '@value'), ('face', '@face')])) cmap = LinearColorMapper(palette=self.face_palette, low=self.face_rng[0], high=self.face_rng[1]) self.face_cmaps[obs.plot_id] = cmap obs.face_source = ColumnDataSource() xs = [[orig_layout[n][0] for n in f] for f in obs.faces] ys = [[orig_layout[n][1] for n in f] for f in obs.faces] if hasattr(obs.G, 'rendered_faces'): # Hacky xs = [xs[i] for i in obs.G.rendered_faces] ys = [ys[i] for i in obs.G.rendered_faces] obs.face_source.data['xs'] = xs obs.face_source.data['ys'] = ys obs.face_source.data['value'] = np.zeros(len(xs)) faces = Patches(xs='xs', ys='ys', fill_color=field('value', cmap), line_color='#FFFFFF', line_width=2) plot.add_glyph(obs.face_source, faces) if self.face_orientations: # TODO: only works for convex faces obs.centroid_x, obs.centroid_y = np.array([np.mean(row) for row in xs]), np.array([np.mean(row) for row in ys]) obs.radius = 0.3 * np.array([min([np.sqrt((xs[i][j] - obs.centroid_x[i])**2 + (ys[i][j] - obs.centroid_y[i])**2) for j in range(len(xs[i]))]) for i in range(len(xs))]) height = 2/5 * obs.radius arrows_ys = np.stack((obs.centroid_y-obs.radius, obs.centroid_y-obs.radius+height/2, obs.centroid_y-obs.radius-height/2), axis=1) obs.face_source.data['centroid_x'] = obs.centroid_x obs.face_source.data['centroid_y'] = obs.centroid_y obs.face_source.data['radius'] = obs.radius obs.face_source.data['arrows_ys'] = (arrows_ys + 0.01).tolist() self.draw_face_orientations(obs, cmap) arcs = Arc(x='centroid_x', y='centroid_y', radius='radius', start_angle=-0.9, end_angle=4.1, line_color=field('arrow_color', cmap)) arrows = Patches(xs='arrows_xs', ys='arrows_ys', fill_color=field('arrow_color', cmap), line_color=field('arrow_color', cmap)) plot.add_glyph(obs.face_source, arcs) plot.add_glyph(obs.face_source, arrows) if self.colorbars: cbar = ColorBar(color_mapper=cmap, ticker=BasicTicker(), title='face') cbar.major_label_text_font_size = "15pt" plot.add_layout(cbar, 'right') else: raise Exception('unknown graph domain.') elif isinstance(obs, PointObservable): plot = figure(width=self.plot_width, height=self.plot_height) plot.add_tools(HoverTool(tooltips=[('time', '@t'), ('value', '@value')])) plot.toolbar_location = None plot.x_range.follow = 'end' plot.x_range.follow_interval = 10.0 plot.x_range.range_padding = 0 plot.xaxis.major_label_text_font_size = "15pt" plot.xaxis.axis_label = 'Time' plot.yaxis.major_label_text_font_size = "15pt" plot.y_range.range_padding_units = 'absolute' plot.y_range.range_padding = obs.render_params['min_res'] / 2 obs.src = ColumnDataSource({'t': [], 'value': []}) glyph = Line(x='t', y='value') plot.add_glyph(obs.src, glyph) # plot.line('t', 'value', line_color='black', source=obs.src) elif isinstance(obs, VectorObservable): plot = figure(width=self.plot_width, height=self.plot_height, y_range=obs.domain) plot.add_tools(HoverTool(tooltips=[('time', '@t'), ('value', '@val'), ('y', '@y')])) plot.toolbar_location = None plot.x_range.follow = 'end' plot.x_range.follow_interval = 10.0 plot.x_range.range_padding = 0 # plot.xaxis.major_label_text_font_size = "15pt" # plot.xaxis.axis_label = 'Time' # plot.yaxis.major_label_text_font_size = "15pt" obs.src = ColumnDataSource({'t': [], 'y': [], 'w': [], 'val': []}) obs.cmap = LinearColorMapper(palette=self.vec_palette, low=0, high=1) obs.last_t = obs.t plot.rect(x='t', y='y', width='w', height=1, source=obs.src, line_color=None, fill_color=field('val', obs.cmap)) if self.colorbars: cbar = ColorBar(color_mapper=obs.cmap, ticker=BasicTicker(), title='value') cbar.major_label_text_font_size = "15pt" plot.add_layout(cbar, 'right') else: raise Exception('unknown observable type: ', obs) return plot
def geoplot( gdf_in, geometry_column="geometry", figure=None, figsize=None, title="", xlabel="Longitude", ylabel="Latitude", xlim=None, ylim=None, color="blue", colormap=None, colormap_uselog=False, colormap_range=None, category=None, dropdown=None, slider=None, slider_range=None, slider_name="", show_colorbar=True, colorbar_tick_format=None, xrange=None, yrange=None, hovertool=True, hovertool_columns=[], hovertool_string=None, simplify_shapes=None, tile_provider="CARTODBPOSITRON_RETINA", tile_provider_url=None, tile_attribution="", tile_alpha=1, panning=True, zooming=True, toolbar_location="right", show_figure=True, return_figure=True, return_html=False, legend=True, webgl=True, **kwargs, ): """Doc-String: TODO""" # Imports: import bokeh.plotting from bokeh.plotting import show from bokeh.models import ( HoverTool, LogColorMapper, LinearColorMapper, GeoJSONDataSource, WheelZoomTool, ColorBar, BasicTicker, LogTicker, Select, Slider, ColumnDataSource, ) from bokeh.models.callbacks import CustomJS from bokeh.models.widgets import Dropdown from bokeh.palettes import all_palettes from bokeh.layouts import row, column # Make a copy of the input geodataframe: gdf = gdf_in.copy() # Check layertypes: if type(gdf) != pd.DataFrame: layertypes = [] if "Point" in str(gdf.geom_type.unique()): layertypes.append("Point") if "Line" in str(gdf.geom_type.unique()): layertypes.append("Line") if "Polygon" in str(gdf.geom_type.unique()): layertypes.append("Polygon") if len(layertypes) > 1: raise Exception( f"Can only plot GeoDataFrames/Series with single type of geometry (either Point, Line or Polygon). Provided is a GeoDataFrame/Series with types: {layertypes}" ) else: layertypes = ["Point"] # Get and check provided parameters for geoplot: figure_options = { "title": title, "x_axis_label": xlabel, "y_axis_label": ylabel, "plot_width": 600, "plot_height": 400, "toolbar_location": toolbar_location, "active_scroll": "wheel_zoom", "x_axis_type": "mercator", "y_axis_type": "mercator", } if not figsize is None: width, height = figsize figure_options["plot_width"] = width figure_options["plot_height"] = height if webgl: figure_options["output_backend"] = "webgl" if type(gdf) != pd.DataFrame: # Convert GeoDataFrame to Web Mercator Projection: gdf.to_crs(epsg=3857, inplace=True) # Simplify shapes if wanted: if isinstance(simplify_shapes, numbers.Number): if layertypes[0] in ["Line", "Polygon"]: gdf[geometry_column] = gdf[geometry_column].simplify( simplify_shapes) elif not simplify_shapes is None: raise ValueError( "<simplify_shapes> parameter only accepts numbers or None.") # Check for category, dropdown or slider (choropleth map column): category_options = 0 if not category is None: category_options += 1 category_columns = [category] if not dropdown is None: category_options += 1 category_columns = dropdown if not slider is None: category_options += 1 category_columns = slider if category_options > 1: raise ValueError( "Only one of <category>, <dropdown> or <slider> parameters is allowed to be used at once." ) # Check for category (single choropleth plot): if category is None: pass elif isinstance(category, (list, tuple)): raise ValueError( "For <category>, please provide an existing single column of the GeoDataFrame." ) elif category in gdf.columns: pass else: raise ValueError( f"Could not find column '{category}' in GeoDataFrame. For <category>, please provide an existing single column of the GeoDataFrame." ) # Check for dropdown (multiple choropleth plots via dropdown selection): if dropdown is None: pass elif not isinstance(dropdown, (list, tuple)): raise ValueError( "For <dropdown>, please provide a list/tuple of existing columns of the GeoDataFrame." ) else: for col in dropdown: if col not in gdf.columns: raise ValueError( f"Could not find column '{col}' for <dropdown> in GeoDataFrame. " ) # Check for slider (multiple choropleth plots via slider selection): if slider is None: pass elif not isinstance(slider, (list, tuple)): raise ValueError( "For <slider>, please provide a list/tuple of existing columns of the GeoDataFrame." ) else: for col in slider: if col not in gdf.columns: raise ValueError( f"Could not find column '{col}' for <slider> in GeoDataFrame. " ) if not slider_range is None: if not isinstance(slider_range, Iterable): raise ValueError( "<slider_range> has to be a type that is iterable like list, tuple, range, ..." ) else: slider_range = list(slider_range) if len(slider_range) != len(slider): raise ValueError( "The number of elements in <slider_range> has to be the same as in <slider>." ) steps = [] for i in range(len(slider_range) - 1): steps.append(slider_range[i + 1] - slider_range[i]) if len(set(steps)) > 1: raise ValueError( "<slider_range> has to have equal step size between each elements (like a range-object)." ) else: slider_step = steps[0] slider_start = slider_range[0] slider_end = slider_range[-1] # Check colormap if either <category>, <dropdown> or <slider> is choosen: if category_options == 1: if colormap is None: colormap = blue_colormap elif isinstance(colormap, (tuple, list)): if len(colormap) > 1: pass else: raise ValueError( f"<colormap> only accepts a list/tuple of at least two colors or the name of one of the following predefined colormaps (see also https://bokeh.pydata.org/en/latest/docs/reference/palettes.html ): {list(all_palettes.keys())}" ) elif isinstance(colormap, str): if colormap in all_palettes: colormap = all_palettes[colormap] colormap = colormap[max(colormap.keys())] else: raise ValueError( f"Could not find <colormap> with name {colormap}. The following predefined colormaps are supported (see also https://bokeh.pydata.org/en/latest/docs/reference/palettes.html ): {list(all_palettes.keys())}" ) else: raise ValueError( f"<colormap> only accepts a list/tuple of at least two colors or the name of one of the following predefined colormaps (see also https://bokeh.pydata.org/en/latest/docs/reference/palettes.html ): {list(all_palettes.keys())}" ) else: if isinstance(color, str): colormap = [color] elif color is None: colormap = ["blue"] else: raise ValueError( "<color> has to be a string specifying the fill_color of the map glyph." ) # Check xlim & ylim: if xlim is not None: if isinstance(xlim, (tuple, list)): if len(xlim) == 2: xmin, xmax = xlim for _ in [xmin, xmax]: if not -180 < _ <= 180: raise ValueError( "Limits for x-axis (=Longitude) have to be between -180 and 180." ) if not xmin < xmax: raise ValueError("xmin has to be smaller than xmax.") from pyproj import Transformer transformer = Transformer.from_crs("epsg:4326", "epsg:3857") xmin = transformer.transform(0, xmin)[0] xmax = transformer.transform(0, xmax)[0] figure_options["x_range"] = (xmin, xmax) else: raise ValueError( "Limits for x-axis (=Longitude) have to be of form [xmin, xmax] with values between -180 and 180." ) else: raise ValueError( "Limits for x-axis (=Longitude) have to be of form [xmin, xmax] with values between -180 and 180." ) if ylim is not None: if isinstance(ylim, (tuple, list)): if len(ylim) == 2: ymin, ymax = ylim for _ in [ymin, ymax]: if not -90 < _ <= 90: raise ValueError( "Limits for y-axis (=Latitude) have to be between -90 and 90." ) if not ymin < ymax: raise ValueError("ymin has to be smaller than ymax.") from pyproj import Transformer transformer = Transformer.from_crs("epsg:4326", "epsg:3857") ymin = transformer.transform(ymin, 0)[1] ymax = transformer.transform(ymax, 0)[1] figure_options["y_range"] = (ymin, ymax) else: raise ValueError( "Limits for y-axis (=Latitude) have to be of form [ymin, ymax] with values between -90 and 90." ) else: raise ValueError( "Limits for y-axis (=Latitude) have to be of form [ymin, ymax] with values between -90 and 90." ) # Create Figure to draw: old_layout = None if figure is None: p = bokeh.plotting.figure(**figure_options) # Add Tile Source as Background: p = _add_backgroundtile(p, tile_provider, tile_provider_url, tile_attribution, tile_alpha) elif isinstance(figure, type(bokeh.plotting.figure())): p = figure elif isinstance(figure, type(column())): old_layout = figure p = _get_figure(old_layout) else: raise ValueError( "Parameter <figure> has to be of type bokeh.plotting.figure or bokeh.layouts.column." ) # Get ridd of zoom on axes: for t in p.tools: if type(t) == WheelZoomTool: t.zoom_on_axis = False # Hide legend if wanted: legend_input = legend if isinstance(legend, str): pass else: legend = "GeoLayer" # Define colormapper: if len(colormap) == 1: kwargs["fill_color"] = colormap[0] elif not category is None: # Check if category column is numerical: if not issubclass(gdf[category].dtype.type, np.number): raise NotImplementedError( f"<category> plot only yet implemented for numerical columns. Column '{category}' is not numerical." ) field = category colormapper_options = {"palette": colormap} if not colormap_range is None: if not isinstance(colormap_range, (tuple, list)): raise ValueError( "<colormap_range> can only be 'None' or a tuple/list of form (min, max)." ) elif len(colormap_range) == 2: colormapper_options["low"] = colormap_range[0] colormapper_options["high"] = colormap_range[1] else: colormapper_options["low"] = gdf[field].min() colormapper_options["high"] = gdf[field].max() if colormap_uselog: colormapper = LogColorMapper(**colormapper_options) else: colormapper = LinearColorMapper(**colormapper_options) kwargs["fill_color"] = {"field": "Colormap", "transform": colormapper} if not isinstance(legend, str): legend = str(field) elif not dropdown is None: # Check if all columns in dropdown selection are numerical: for col in dropdown: if not issubclass(gdf[col].dtype.type, np.number): raise NotImplementedError( f"<dropdown> plot only yet implemented for numerical columns. Column '{col}' is not numerical." ) field = dropdown[0] colormapper_options = {"palette": colormap} if not colormap_range is None: if not isinstance(colormap_range, (tuple, list)): raise ValueError( "<colormap_range> can only be 'None' or a tuple/list of form (min, max)." ) elif len(colormap_range) == 2: colormapper_options["low"] = colormap_range[0] colormapper_options["high"] = colormap_range[1] else: colormapper_options["low"] = gdf[dropdown].min().min() colormapper_options["high"] = gdf[dropdown].max().max() if colormap_uselog: colormapper = LogColorMapper(**colormapper_options) else: colormapper = LinearColorMapper(**colormapper_options) kwargs["fill_color"] = {"field": "Colormap", "transform": colormapper} legend = " " + field elif not slider is None: # Check if all columns in dropdown selection are numerical: for col in slider: if not issubclass(gdf[col].dtype.type, np.number): raise NotImplementedError( f"<slider> plot only yet implemented for numerical columns. Column '{col}' is not numerical." ) field = slider[0] colormapper_options = {"palette": colormap} if not colormap_range is None: if not isinstance(colormap_range, (tuple, list)): raise ValueError( "<colormap_range> can only be 'None' or a tuple/list of form (min, max)." ) elif len(colormap_range) == 2: colormapper_options["low"] = colormap_range[0] colormapper_options["high"] = colormap_range[1] else: colormapper_options["low"] = gdf[slider].min().min() colormapper_options["high"] = gdf[slider].max().max() if colormap_uselog: colormapper = LogColorMapper(**colormapper_options) else: colormapper = LinearColorMapper(**colormapper_options) kwargs["fill_color"] = {"field": "Colormap", "transform": colormapper} if not isinstance(legend, str): legend = "Geolayer" # Check that only hovertool_columns or hovertool_string is used: if isinstance(hovertool_columns, (list, tuple, str)): if len(hovertool_columns) > 0 and hovertool_string is not None: raise ValueError( "Either <hovertool_columns> or <hovertool_string> can be used, but not both at the same time." ) else: raise ValueError( "<hovertool_columns> has to be a list of columns of the GeoDataFrame or the string 'all'." ) if hovertool_string is not None: hovertool_columns = "all" # Check for Hovertool columns: if hovertool: if not isinstance(hovertool_columns, (list, tuple)): if hovertool_columns == "all": hovertool_columns = list( filter(lambda col: col != geometry_column, gdf.columns)) else: raise ValueError( "<hovertool_columns> has to be a list of columns of the GeoDataFrame or the string 'all'." ) elif len(hovertool_columns) == 0: if not category is None: hovertool_columns = [category] elif not dropdown is None: hovertool_columns = dropdown elif not slider is None: hovertool_columns = slider else: hovertool_columns = [] else: for col in hovertool_columns: if col not in gdf.columns: raise ValueError( f"Could not find columns '{col}' in GeoDataFrame. <hovertool_columns> has to be a list of columns of the GeoDataFrame or the string 'all'." ) else: if category is None: hovertool_columns = [] else: hovertool_columns = [category] # Reduce DataFrame to needed columns: if type(gdf) == pd.DataFrame: gdf["Geometry"] = 0 additional_columns = ["x", "y"] else: additional_columns = [geometry_column] for kwarg, value in kwargs.items(): if isinstance(value, Hashable): if value in gdf.columns: additional_columns.append(value) if category_options == 0: gdf = gdf[list(set(hovertool_columns) | set(additional_columns))] else: gdf = gdf[list( set(hovertool_columns) | set(category_columns) | set(additional_columns))] gdf["Colormap"] = gdf[field] field = "Colormap" # Create GeoJSON DataSource for Plot: if type(gdf) != pd.DataFrame: geo_source = GeoJSONDataSource(geojson=gdf.to_json()) else: geo_source = gdf # Draw Glyph on Figure: layout = None if "Point" in layertypes: if "line_color" not in kwargs: kwargs["line_color"] = kwargs["fill_color"] glyph = p.scatter(x="x", y="y", source=geo_source, legend_label=legend, **kwargs) if "Line" in layertypes: if "line_color" not in kwargs: kwargs["line_color"] = kwargs["fill_color"] del kwargs["fill_color"] glyph = p.multi_line(xs="xs", ys="ys", source=geo_source, legend_label=legend, **kwargs) if "Polygon" in layertypes: if "line_color" not in kwargs: kwargs["line_color"] = "black" # Creates from a geoDataFrame with Polygons and Multipolygons a Pandas DataFrame # with x any y columns specifying the geometry of the Polygons: geo_source = ColumnDataSource( convert_geoDataFrame_to_patches(gdf, geometry_column)) # Plot polygons: glyph = p.multi_polygons(xs="__x__", ys="__y__", source=geo_source, legend_label=legend, **kwargs) # Add hovertool: if hovertool and (category_options == 1 or len(hovertool_columns) > 0): my_hover = HoverTool(renderers=[glyph]) if hovertool_string is None: my_hover.tooltips = [(str(col), "@{%s}" % col) for col in hovertool_columns] else: my_hover.tooltips = hovertool_string p.add_tools(my_hover) # Add colorbar: if show_colorbar and category_options == 1: colorbar_options = { "color_mapper": colormapper, "label_standoff": 12, "border_line_color": None, "location": (0, 0), } if colormap_uselog: colorbar_options["ticker"] = LogTicker() if colorbar_tick_format: colorbar_options["formatter"] = get_tick_formatter( colorbar_tick_format) colorbar = ColorBar(**colorbar_options) p.add_layout(colorbar, "right") # Add Dropdown Widget: if not dropdown is None: # Define Dropdown widget: dropdown_widget = Select(title="Select Choropleth Layer", options=list(zip(dropdown, dropdown))) # Define Callback for Dropdown widget: callback = CustomJS( args=dict( dropdown_widget=dropdown_widget, geo_source=geo_source, legend=p.legend[0].items[0], ), code=""" //Change selection of field for Colormapper for choropleth plot: geo_source.data["Colormap"] = geo_source.data[dropdown_widget.value]; geo_source.change.emit(); //Change label of Legend: legend.label["value"] = " " + dropdown_widget.value; """, ) dropdown_widget.js_on_change("value", callback) # Add Dropdown widget above the plot: if old_layout is None: layout = column(dropdown_widget, p) else: layout = column(dropdown_widget, old_layout) # Add Slider Widget: if not slider is None: if slider_range is None: slider_start = 0 slider_end = len(slider) - 1 slider_step = 1 value2name = ColumnDataSource({ "Values": np.arange(slider_start, slider_end + slider_step, slider_step), "Names": slider, }) # Define Slider widget: slider_widget = Slider( start=slider_start, end=slider_end, value=slider_start, step=slider_step, title=slider_name, ) # Define Callback for Slider widget: callback = CustomJS( args=dict( slider_widget=slider_widget, geo_source=geo_source, value2name=value2name, ), code=""" //Change selection of field for Colormapper for choropleth plot: var slider_value = slider_widget.value; var i; for(i=0; i<value2name.data["Names"].length; i++) { if (value2name.data["Values"][i] == slider_value) { var name = value2name.data["Names"][i]; } } geo_source.data["Colormap"] = geo_source.data[name]; geo_source.change.emit(); """, ) slider_widget.js_on_change("value", callback) # Add Slider widget above the plot: if old_layout is None: layout = column(slider_widget, p) else: layout = column(slider_widget, old_layout) # Hide legend if user wants: if legend_input is False: p.legend.visible = False # Set click policy for legend: p.legend.click_policy = "hide" # Set panning option: if panning is False: p.toolbar.active_drag = None # Set zooming option: if zooming is False: p.toolbar.active_scroll = None # Display plot and if wanted return plot: if layout is None: if old_layout is None: layout = p else: layout = old_layout # Display plot if wanted if show_figure: show(layout) # Return as (embeddable) HTML if wanted: if return_html: return embedded_html(layout) # Return plot: if return_figure: return layout
def create_satellite_panel(radar_pass, cloudsat_vbl, sat_img_src, sat_src, traj_df, radar_full_names): """Creates bottom panel for the data visualization tool plot.""" # Create color mapper. if cloudsat_vbl == 'radar_refl': color_mapper = LinearColorMapper(palette='Plasma256',low=-2300,high=1500) elif cloudsat_vbl == 'cloud_type': color_mapper = LinearColorMapper(palette='Paired9',low=-0.5,high=8.5) elif cloudsat_vbl == 'cpr_cloud_mask': color_mapper = LinearColorMapper(palette='Paired11',low=-2,high=42) elif cloudsat_vbl == 'iwc': cmp = get_hex_matplotlib_cmap('Blues',100,reverse=False) cmp.insert(0,'#FFFFFF') color_mapper = LinearColorMapper(palette=cmp,low=0,high=0.25) elif cloudsat_vbl == 'lwc': cmp = get_hex_matplotlib_cmap('Greens',100,reverse=False) cmp.insert(0,'#FFFFFF') color_mapper = LinearColorMapper(palette=cmp,low=0,high=1) elif cloudsat_vbl == 'iwc_unc': color_mapper = LinearColorMapper(palette='Viridis256',low=0,high=200) elif cloudsat_vbl == 'lwc_unc': color_mapper = LinearColorMapper(palette='Viridis256',low=0,high=200) # Put the plot together. p2 = figure(title="CloudSat: "+radar_full_names[cloudsat_vbl], toolbar_location="right", plot_width=800, plot_height=250, active_scroll = "wheel_zoom", x_range=(min(traj_df['t']), max(traj_df['t'])),y_range=(0, 15000)) sat_im = p2.image('image', source=sat_img_src, x=min(traj_df['t']), y=radar_pass.cloudsat['height'][0], dw=max(traj_df['t'])-min(traj_df['t']), dh=(radar_pass.cloudsat['height'][-1]-radar_pass.cloudsat['height'][0]), color_mapper=color_mapper) sat_im.glyph.color_mapper.nan_color = (0, 0, 0, 1) lr_sat = p2.line('t','y',source=sat_src,line_color='gray',line_width=3) # Add colorbar. #if cloudsat_vbl == 'radar_refl': # ticker = FixedTicker(ticks=np.linspace(-2300,1500,11)) #elif cloudsat_vbl == 'cloud_type': # ticker = FixedTicker(ticks=[i for i in range(9)]) #elif cloudsat_vbl == 'cpr_cloud_mask': # ticker = FixedTicker(ticks=[4*i for i in range(11)]) color_bar = ColorBar(color_mapper=color_mapper, bar_line_color='black', major_tick_line_color='black',label_standoff=8, border_line_color=None, location=(0,0)) p2.add_layout(color_bar, 'right') # Adjust some formatting. p2.xaxis.axis_label = 'Time (UTC)' p2.xaxis.axis_label_text_font_size='11pt' p2.xaxis.axis_label_text_font_style='normal' p2.xaxis.major_label_text_font_size='9pt' p2.yaxis.axis_label = 'Height (m)' p2.yaxis.axis_label_text_font_size='11pt' p2.yaxis.axis_label_text_font_style='normal' p2.yaxis.major_label_text_font_size='9pt' # Create datetime x axis p2.xaxis.formatter = DatetimeTickFormatter( hours=["%H:%M:%S"], minutes=["%H:%M:%S"], seconds=["%H:%M:%S"], ) return p2, sat_src
def modify_doc(doc): conn = connect_to_db() # ------------------------------------------- # QUERY: TIME SERIES OF H500, ERC AT ONE LOCATION # Reading data into a list object 'results' directly from postgres fire_weather_db: # cur = conn.cursor() # sql = 'select id, lat, lon, date, h500, h500_grad_x, erc from narr_erc \ # where lat = 39.2549 and lon = 236.314 \ # order by id' # df = pd.read_sql(sql, conn) # cur.close() # conn.close() # df.set_index('date', inplace=True) # # var = 'h500' # # var_title = 'H500' # # df_var = df[[var]] # # var_list = df_var[var].values.tolist() # # var_min = 0.99*(min(var_list)) # # var_max = 1.01*(max(var_list)) # dict_from_df = {'date': df.index.values, 'y': df['h500'].values} # source = ColumnDataSource(dict_from_df) # p.y_range = DataRange1d(start=var_min, end=var_max) # p.yaxis.axis_label = 'Geopotential gradient, gpm/deg' # ------------------------------------------- # # PLOTTING H500 TIME SERIES # p = figure( # x_axis_type = 'datetime', # plot_width = 800, # plot_height = 600, # # y_range = [], # x_axis_label = 'Date', # y_axis_label = 'Geopotential height, gpm', # tools = 'pan,zoom_in,zoom_out,save,reset', # title = 'Time Series' # ) # p.line( # source = source, # x = 'date', # y = 'y', # line_color = 'green', # line_width = 2 # ) # # THIS SLIDER CAUSES THE DATA TO JUMP BACK TO H500 DATA # # EVEN WHEN THE SELECT DROPDOWN SHOWS h500_grad_x. THIS # # ISSUE IS NOT RESOLVED. IT'S POSSIBLE THAT BOKEH ISN'T # # DESIGNED TO HANDLE CHANGING THE COLUMNS TO BE DISPLAYED # # IN ONE PLOT. # def slider_callback(attr, old, new): # if new == 0: # data = dict_from_df # else: # # df = pd.DataFrame(data=source.data) # df = pd.DataFrame(dict_from_df) # df.set_index('date', inplace=True) # data = df.rolling(new).mean() #'{0}D'.format(new)).mean() # source.data = ColumnDataSource(data=data).data # def select_callback(attr, old, new): # if new == 'h500': # # data = df[[new]] # source.data = {'date': df.index.values, 'y': df['h500'].values} # # Rebuilding dict_from_df to pass to slider_callback(): # dict_from_df = {'date': df.index.values, 'y': df['h500'].values} # elif new == 'h500_grad_x': # # data = df[[new]] # source.data = {'date': df.index.values, 'y': df['h500_grad_x'].values} # # Rebuilding dict_from_df to pass to slider_callback(): # dict_from_df = {'date': df.index.values, 'y': df['h500_grad_x'].values} # # Figure p data: # var_list = df['h500_grad_x'].values.tolist() # var_min = 0.99*(min(var_list)) # var_max = 1.01*(max(var_list)) # p.y_range = DataRange1d(start=var_min, end=var_max) # p.yaxis.axis_label = 'Geopotential gradient, gpm/deg' # dict_from_df = source.data # # Widgets # slider = Slider(start=0, end=30, value=0, step=1, title="Smoothing by N Days") # slider.on_change('value', slider_callback) # select = Select(title="Weather Variable:", value="h500", options=["h500","h500_grad_x"])#["H500", "H500 X Gradient", "H500 Y Gradient", "PMSL", "PMSL X Gradient", "PMSL Y Gradient", "Energy Release Component"]) # select.on_change('value', select_callback) # # Layout # # widget_layout = widgetbox(slider, select) # # layout = row(slider, p) # # Add root: # doc.add_root(row(column(slider,select), p)) # # doc.add_root(row(slider, p)) # # doc.add_root(row(select, p)) # # doc.add_root(widget_layout, p) # # curdoc().add_root(widget_layout) # doc.theme = Theme(filename="fwp_theme.yaml") # ------------------------------------------- # # PLOTTING ERC TIME SERIES # p = figure( # x_axis_type = 'datetime', # plot_width = 800, # plot_height = 600, # # y_range = h500_list, # title = 'ERC Time Series', # x_axis_label = 'Date', # y_axis_label = 'ERC, AU', # tools = 'pan,zoom_in,zoom_out,save,reset', # ) # p.line( # source = source, # x = 'date', # y = 'erc', # line_color = 'red', # legend = 'ERC', # line_width=2 # ) # ------------------------------------------- # SQL QUERY: H500 CONTOUR SINGLE DATE # Reading data into a list object 'results' directly from postgres database fire_weather_db: cur = conn.cursor() # Selecting a specific day: # sql = "select id, lat, lon, date, h500, h500_grad_x, pmsl, pmsl_grad_x, pmsl_grad_y, erc from narr_erc \ # where cast(date as date) = '1979-05-15' \ # order by id" # Selecting all days: sql = "select id, lat, lon, date, h500, h500_grad_x, erc from narr_erc \ where cast(date as date) >= '1979-01-02' \ order by id" df = pd.read_sql(sql, conn) cur.close() conn.close() # ------------------------------------------- # # PLOTTING NARR GRID # x = df['lon'] # y = df['lat'] # p = figure( # plot_width = 800, # plot_height = 600, # title = 'NARR Grid', # x_axis_label = 'Lon', # y_axis_label = 'Lat', # tools = 'pan,zoom_in,zoom_out,save,reset', # ) # p.circle(x, y, size=2, color="black", alpha=0.5) # ------------------------------------------- # PLOTTING H500 CONTOUR var = 'h500' # e.g. 'h500', 'h500_grad_x', 'erc' var_title = 'H500' # e.g. 'H500', 'H500 - X Gradient', 'ERC' # Creating mesh of lon and lat then using it to create a mesh of # the plotting data (the z data needs to be in meshgrid format, # the lat lon data does not): lon = df['lon'].drop_duplicates('first').to_numpy() lat = df['lat'].drop_duplicates('first').to_numpy() lonlon, latlat = np.meshgrid(lon, lat) mesh_shape = np.shape(lonlon) # If var = 'erc', change -32767 to 0: if var == 'erc': criteria = df[df['erc'] == -32767].index df['erc'].loc[criteria] = 0 # Getting selected day df.set_index('date', inplace=True) date_list = df.index.unique().tolist() # df['date'].unique().tolist() date_select = date_list[0] df = df[[var]] df_one_day = df.loc[date_select] #[var] d = df_one_day.to_numpy().reshape(mesh_shape) # source = ColumnDataSource(df) print('Unique date list:\n', date_list) print('Selected date:\n', date_select) print('df_one_day:\n', df_one_day) print('d on a selected day:\n', d) # Min and max synoptic variable values: # GETS VALUES ONLY FOR ONE DAY OF YEAR: var_list = df_one_day[var].values.tolist() # GETS VALUES FOR ENTIRE YEAR: # var_list = df[var].values.tolist() # print('var_list:\n', var_list) var_min = min(var_list) var_max = max(var_list) print('var_min:\n', var_min) # Min and max lingitude and latitude for x_range and y_range: lon_min = np.min(lon) lon_max = np.max(lon) dw = lon_max - lon_min lat_min = np.min(lat) lat_max = np.max(lat) dh = lat_max - lat_min print('lat_min:\n', lat_min) p = figure( #toolbar_location="left", title=var_title, plot_width=580, plot_height=600, tooltips=[("lon", "$lon"), ("lat", "$lat"), ("value", "@image")], x_range=(lon_min, lon_max), y_range=(lat_min, lat_max), x_axis_label='Longitude, deg', y_axis_label='Latitude, deg') # Set palette depending on variable to be plotted if var == 'h500_grad_x' or 'h500_grad_y' or 'pmsl_grad_x' or 'pmsl_grad_y': # Color maps that make 0 values clear: # color_mapper = LinearColorMapper(palette=cividis(256), low=var_min, high=var_max) color_mapper = LinearColorMapper(palette="Inferno256", low=var_min, high=var_max) else: color_mapper = LinearColorMapper(palette="Inferno256", low=var_min, high=var_max) # Decent color map: "Spectra11", "Viridis256" # Giving a vector of image data for image parameter (contour plot) # p.image(image=[d], x=lon_min, y=lat_min, dw=dw, dh=dh, color_mapper=color_mapper) source = ColumnDataSource({'image': [d]}) p.image(image='image', x=lon_min, y=lat_min, dw=dw, dh=dh, color_mapper=color_mapper, source=source) # p.x_range.range_padding = p.y_range.range_padding = 0 color_bar = ColorBar(color_mapper=color_mapper, ticker=BasicTicker(), label_standoff=12, border_line_color=None, location=(0, 0)) p.add_layout(color_bar, 'right') # Get state boundaries from state map data imported from Bokeh state_lats = [states[code]["lats"] for code in states] state_lons = [states[code]["lons"] for code in states] # add 360 to adjust lons to NARR grid state_lons = np.array([np.array(sublist) for sublist in state_lons]) state_lons += 360 # Patch the state and coastal boundaries p.patches(state_lons, state_lats, fill_alpha=0.0, line_color="black", line_width=2, line_alpha=0.3) # select = Select(title="Weather Variable:", value="H500", options=["H500", "H500 X Gradient", "H500 Y Gradient", "PMSL", "PMSL X Gradient", "PMSL Y Gradient", "Energy Release Component"]) # slider = Slider(start=DateTime(1979,1,2), end=DateTime(1979,12,31), value=DateTime(1979,1,2), step=1, title="Date") # slider = Slider(start=1, end=365, step=10, title="Date") # def callback(attr, old, new): # points = slider.value # data_points.data = {'x': random(points), 'y': random(points)} # To run on bokeh server: # bokeh serve --show fwp_app.py # # Limit the view to the min and max of the building data # p.x_range = DataRange1d(lon_min, lon_max) # p.y_range = DataRange1d(lat_min, lat_max) # p.xaxis.visible = False # p.yaxis.visible = False p.xgrid.grid_line_color = None p.ygrid.grid_line_color = None # show(p) # output_file("image.html", title="image.py example") # show(p) # open a browser # script, div = components(p) # The data below is passed to add_user_fwp.html to run when localhost:5000/ is opened. # return render_template('add_user_fwp.html', narr_erc_all=narr_erc_all, narr_erc_lat=narr_erc_lat, narr_erc_date=narr_erc_date, script=script, div=div) # return render_template('fwp_bokeh_render.html', script=script, div=div, widget_layout=widget_layout) # return render_template('bokeh_practice.html', results=results) def slider_callback(attr, old, new): # if new == 0: # date_select = date_list[0] # print('date_select in callback:\n', date_select) # df_one_day = df.loc[date_select] #[var] # print('df_one_day in callback:\n', df_one_day) # d = df_one_day.to_numpy().reshape(mesh_shape) # print('d in callback:\n', d) # else: # date_select = date_list[new] # print('date_select in callback:\n', date_select) # df_one_day = df.loc[date_select] #[var] # print('df_one_day in callback:\n', df_one_day) # d = df_one_day.to_numpy().reshape(mesh_shape) # print('d in callback:\n', d) # df = pd.DataFrame(data=source.data) # df = pd.DataFrame(dict_from_df) # df.set_index('date', inplace=True) # data = df.rolling(new).mean() #'{0}D'.format(new)).mean() date_select = date_list[slider.value] print('date_select in callback:\n', date_select) df_one_day = df.loc[date_select] #[var] print('df_one_day in callback:\n', df_one_day) d = df_one_day.to_numpy().reshape(mesh_shape) print('d in callback:\n', d) # source.data = ColumnDataSource(data=data).data source.data = {'image': [d]} # --------------------------------- # THIS WORKS. UNCOMMENT TO USE: # Adjusting color mapper one each slider change: var_list = df_one_day[var].values.tolist() var_min = min(var_list) var_max = max(var_list) # color_mapper = LinearColorMapper(palette=cividis(256), low=var_min, high=var_max) cm = p.select_one(LinearColorMapper) cm.update(low=var_min, high=var_max) # --------------------------------- slider = Slider(start=0, end=364, value=0, step=1, title="Day of Year") # slider = Slider(start=0, end=30, value=0, step=1, title="Smoothing by N Days") slider.on_change('value', slider_callback) # def select_callback(attr, old, new): # if new == 'h500': # # data = df[[new]] # source.data = {'date': df.index.values, 'y': df['h500'].values} # # Rebuilding dict_from_df to pass to slider_callback(): # dict_from_df = {'date': df.index.values, 'y': df['h500'].values} # elif new == 'h500_grad_x': # # data = df[[new]] # source.data = {'date': df.index.values, 'y': df['h500_grad_x'].values} # # Rebuilding dict_from_df to pass to slider_callback(): # dict_from_df = {'date': df.index.values, 'y': df['h500_grad_x'].values} # # Figure p data: # var_list = df['h500_grad_x'].values.tolist() # var_min = 0.99*(min(var_list)) # var_max = 1.01*(max(var_list)) # p.y_range = DataRange1d(start=var_min, end=var_max) # p.yaxis.axis_label = 'Geopotential gradient, gpm/deg' # dict_from_df = source.data # # Widgets # slider = Slider(start=0, end=30, value=0, step=1, title="Smoothing by N Days") # slider.on_change('value', slider_callback) # select = Select(title="Weather Variable:", value="h500", options=["h500","h500_grad_x"])#["H500", "H500 X Gradient", "H500 Y Gradient", "PMSL", "PMSL X Gradient", "PMSL Y Gradient", "Energy Release Component"]) # select.on_change('value', select_callback) # # Layout # widget_layout = widgetbox(slider, select) # layout = row(slider, p) # # Add root: # doc.add_root(row(column(slider,select), p)) doc.add_root(row(slider, p)) # doc.add_root(row(select, p)) # doc.add_root(widget_layout, p) # curdoc().add_root(widget_layout) doc.theme = Theme(filename="fwp_theme.yaml")
#Input GeoJSON source that contains features for plotting. geosource = GeoJSONDataSource(geojson = json_data(2016)) #Define a sequential multi-hue color palette. # palette = brewer['YlOrRd'][9] palette = all_palettes['PuOr'][10] #Reverse color order so that dark blue is highest obesity. palette = palette[::-1] #Instantiate LinearColorMapper that linearly maps numbers in a range, into a sequence of colors. Input nan_color. color_mapper = LinearColorMapper(palette = palette, low = 0, high = 100, nan_color = '#A9A9A9') #Define custom tick labels for color bar. tick_labels = {'0': '0%', '10': '10%', '20':'20%', '30' : '30%', '40':'40%', '50':'50%', '60':'60%', '70':'70%','80':'80%', '90': '90%', '100': '100%'} #Add hover tool hover = HoverTool(tooltips = [ ('Country/region','@country'),('% internet usage', '@percent_usage_of_internet')]) #Create color bar. color_bar = ColorBar(color_mapper=color_mapper, label_standoff=8,width = 500, height = 20, border_line_color=None,location = (0,0), orientation = 'horizontal', major_label_overrides = tick_labels) #Create figure object. p = figure(title = 'Share of individuals with Internet access, 2016', plot_height = 600 , plot_width = 950, toolbar_location = None, tools = [hover]) p.xgrid.grid_line_color = None p.ygrid.grid_line_color = None #Add patch renderer to figure. p.patches('xs','ys', source = geosource,fill_color = {'field' :'percent_usage_of_internet', 'transform' : color_mapper}, line_color = 'black', line_width = 0.25, fill_alpha = 1) #Specify layout p.add_layout(color_bar, 'below') # Make a slider object: slider slider = Slider(title = 'Year',start = 1990, end = 2016, step = 1, value = 2016) slider.on_change('value', update_plot) # Make a column layout of widgetbox(slider) and plot, and add it to the current document