def visualize(self): daily_plot_cols_labels = {"INFECTED": "Infected", "RECOVERED": "Recovered", "DEAD": "dead"} change_plot_cols_labels = { "num_recovered_cases": "# newly recovered", "num_deceased_cases": "# of new deaths", "num_new_cases": "# of new cases" } mobility_plot_cols_labels = { "num_state_changed": "# of residents moved" # NOTE: Only people moving is considered a state change as of today } gspec = pn.GridSpec(width=975, margin=0, sizing_mode="stretch_both") mobility_plot = self.curve.visualize_time_series(mobility_plot_cols_labels.keys(), rename_cols=mobility_plot_cols_labels, options=opts(title="∆ in number of residents moved", ylabel="Periodic change", height=300, show_legend=False)) daily_plot = self.curve.visualize_time_series(daily_plot_cols_labels.keys(), rename_cols=daily_plot_cols_labels, options=opts(ylabel="Total as of date")) change_plot = self.curve.visualize_time_series(change_plot_cols_labels.keys(), rename_cols=change_plot_cols_labels, options=opts(ylabel="Periodic change in metric")) gspec[0, 0:2] = self.city.visualize() gspec[0, 2:5] = mobility_plot gspec[0, 5] = self.curve.visualize_recent_residents_moved(opts(width=100, title="")) gspec[1, :3] = daily_plot gspec[1, 3:] = change_plot return gspec
def plot_phase_diagrams(filenames,fileout): for i in range(len(filenames)): print 'i: ',i ds = yt.load(filenames[i]) center_guess = initial_center_guess(ds,track_name) halo_center = get_halo_center(ds,center_guess) rb = sym_refine_box(ds,halo_center) args = filenames[i].split('/') sim_label = args[-3] dens = np.log10(rb['H_nuclei_density']) temp = np.log10(rb['Temperature']) df = pd.DataFrame({'temp':temp, 'dens':dens}) phase_scatter = hv.Scatter(df,kdims=['dens'],vdims=['temp'],label=sim_label) #phase_data = np.zeros((len(rb['H_nuclei_density']),2)) #phase_data[:,0] = np.log10(rb['H_nuclei_density']) #phase_data[:,1] = np.log10(rb['Temperature']) #points = hv.Points(phase_data,kdims=['nH','temp'],label=sim_label) hv.opts({'Histogram': {'style': {'alpha':0.3, 'fill_color':'k'}}}) xhist = (histogram(phase_scatter, bin_range=(-7.5, 1), dimension='dens',normed=True)) #,alpha=0.3, fill_color='k')) yhist = (histogram(phase_scatter, bin_range=(3, 8.5), dimension='temp',normed=True)) #,alpha=0.3, fill_color='k')) if i == 0: phase_plot = (datashade(phase_scatter,cmap=cm.plasma, dynamic=False,x_range=(-7.5,1),y_range=(3,8.5))) << yhist(plot=dict(width=125)) << xhist(plot=dict(height=125)) else: plot2 = (datashade(phase_scatter,cmap=cm.plasma, dynamic=False,x_range=(-7.5,1),y_range=(3,8.5))) << yhist(plot=dict(width=125)) << xhist(plot=dict(height=125)) phase_plot = phase_plot + plot2 renderer = hv.renderer('bokeh').instance(fig='html') renderer.save(phase_plot, fileout) return
def test_options_inherit_invalid_keywords(self): original_kws = dict(kw2='value', kw3='value') opts = Options('test', allowed_keywords=['kw3', 'kw2'], **original_kws) new_kws = dict(kw4='val4', kw5='val5') try: opts(**new_kws) except OptionError as e: self.assertEqual(str(e), "Invalid option 'kw4', valid options are: ['kw2', 'kw3']")
def plot_interactive(self): ds = hv.Dataset(self.results) likelihood_plot = ds.to(hv.Curve, 'position', 'likelihood') posterior_plot = ds.to(hv.Curve, 'position', 'posterior_density') prior_plot = ds.to(hv.Curve, 'position', 'prior') plot_opts = dict(shared_yaxis=True, shared_xaxis=True) norm_opts = dict(framewise=True) hv.opts({'Curve': dict(norm=norm_opts)}, likelihood_plot) return (prior_plot.grid('state').opts(plot=plot_opts) + likelihood_plot.grid('state').opts(plot=plot_opts) + posterior_plot.grid('state').opts(plot=plot_opts)).cols(1)
def _make_heatmap(final_grid, density, fname, target): logger.info('Drawing the heatmap') lat = np.linspace(-90, 90, num=180 * density + 1) lon = np.linspace(-179.75, 180, num=360 * density) d = { 'coords': { 'latitude': { 'dims': ('latitude', ), 'data': lat }, 'longitude': { 'dims': ('longitude', ), 'data': lon } }, 'attrs': { 'title': '%s latency heatmap' % target }, 'dims': ['latitude', 'longitude'], 'data_vars': { 'latency': { 'dims': ('latitude', 'longitude'), 'data': final_grid } } } xr_set = xr.Dataset.from_dict(d) xr_dataset = gv.Dataset(xr_set, kdims=['latitude', 'longitude'], vdims=['latency'], crs=crs.PlateCarree()) hv.output(dpi=200, size=500) hv.opts("Image [colorbar=True clipping_colors={'min': 'lightgrey'}]") main_layer = xr_dataset.redim(latency=dict(range=(30, 90))).to( gv.Image, ['longitude', 'latitude']) img = gf.land * main_layer * gf.ocean * gf.borders if fname.endswith('.png'): fname = fname[:-4] renderer = hv.renderer('matplotlib').instance(fig='png') renderer.save(img, fname, style=dict(Image={'cmap': 'RdYlGn_r'}))
def _create_histogram(df: pandas.DataFrame, histogram_name: HistogramName, bins: int = 20) -> hv.Histogram: """ ヒストグラムを生成する。 Args: df: histogram_name: bins: ヒスグラムの棒の数 Returns: ヒストグラムオブジェクト """ mean = round(df[histogram_name.column].mean(), 3) std = round(df[histogram_name.column].std(), 3) title = f"{histogram_name.title}: μ={mean}, α={std}, N={len(df)}" data = df[histogram_name.column].values frequencies, edges = np.histogram(data, bins) hist = ( hv.Histogram( (edges, frequencies), kdims=histogram_name.x_axis_label, vdims=histogram_name.y_axis_label, label=title ) .options(width=500, title=title, fontsize={"title": 9, "labels": 9}) .opts(hv.opts(tools=["hover"])) ) return hist
def test_options_inherit(self): original_kws = dict(kw2='value', kw3='value') opts = Options('test', **original_kws) new_kws = dict(kw4='val4', kw5='val5') new_opts = opts(**new_kws) self.assertEqual(new_opts.options, dict(original_kws, **new_kws))
def chart_for_metric(state:Dict, metric:str, viz_opts=opts()): bar_charts = [] for g in state[M1][metric].keys(): chart_data = [(state[model]["label"], state[model][metric][g]) for model in state.keys()] bar_chart = hv.Bars(chart_data, hv.Dimension(f'Models for {g}'), " ").opts(common_opts).opts(viz_opts) bar_charts.append(bar_chart) return hv.Layout(bar_charts).opts(shared_axes=False, title=metric).cols(1) # TODO: Title disturbs the layout
def fetch_all_models_metrics_for_feature_on_dataset(feature:str, ad_category:str): state = { M1: { "label": "Base" }, M2: { "label": "M2" }, M3: { "label": "M3" } } for model_id in state.keys(): state[model_id].update(fetch_model_metrics_for_feature_on_dataset( model_id, feature, ad_category )) return state common_opts = opts(show_grid=True, height=200, width=300) #, tools=["hover"] gfm_opts = opts(ylabel="Closer to zero, the better", ylim=(-1, 1)) fpr_opts = opts(ylim=(0, 1)) def chart_for_metric(state:Dict, metric:str, viz_opts=opts()): bar_charts = [] for g in state[M1][metric].keys(): chart_data = [(state[model]["label"], state[model][metric][g]) for model in state.keys()] bar_chart = hv.Bars(chart_data, hv.Dimension(f'Models for {g}'), " ").opts(common_opts).opts(viz_opts) bar_charts.append(bar_chart) return hv.Layout(bar_charts).opts(shared_axes=False, title=metric).cols(1) # TODO: Title disturbs the layout class AdsFairnessExplorer(param.Parameterized):
import numpy as np import holoviews as hv import math hv.extension('matplotlib') hv.opts("Scatter [xaxis=None yaxis=None] (color='k' marker='.' s=1)") renderer = hv.renderer('matplotlib').instance(fig='pdf', holomap='gif') sf = False if sf: tree_file = './san_francisco_street_trees.csv' else: tree_file = './new_york_tree_census_2015.csv' trees = np.genfromtxt(tree_file, delimiter=',', comments='!') trees = trees[~np.isnan(trees).any(axis=1)] # Filter SF trees to just get the inner city if sf: trees = trees[(trees[:, 0] > 37.6) & (trees[:, 0] < 40)] # Want to print scatter plot of (longitude, latitude) for tree in trees: tmp = tree[0] tree[0] = tree[1] tree[1] = tmp image = hv.Scatter(trees) filename = '' if sf:
def plot_frames(data, backend='matplotlib', mode='mosaic', rows=1, vmax=None, vmin=None, circle=None, circle_alpha=0.8, circle_color='white', circle_radius=6, circle_label=False, arrow=None, arrow_alpha=0.8, arrow_length=10, arrow_shiftx=5, label=None, label_pad=5, label_size=12, grid=False, grid_alpha=0.4, grid_color='#f7f7f7', grid_spacing=None, cross=None, cross_alpha=0.4, ang_scale=False, ang_ticksep=50, pxscale=0.01, ang_legend=False, axis=True, show_center=False, cmap=None, log=False, colorbar=True, colorbar_ticks=None, dpi=100, size_factor=6, horsp=0.4, versp=0.2, width=400, height=400, title=None, sampling=1, save=None, transparent=False): """ Plot a 2d array or a tuple of 2d arrays. Supports the ``matplotlib`` and ``bokeh`` backends. When having a tuple of 2d arrays, the plot turns into a mosaic. For ``matplotlib``, instead of a mosaic of images, we can create a mosaic of surface plots. Also, when using the ``matplotlib`` backend, this function allows to annotate and customize the plot and produce publication quality figures. Parameters ---------- data : numpy.ndarray or tuple A single 2d array or a tuple of 2d arrays. backend : {'matplotlib', 'bokeh'}, str optional Selects the backend used to display the plots. ``Matplotlib`` plots are static and allow customization (leading to publication quality figures). ``Bokeh`` plots are interactive, allowing the used to zoom, pan, inspect pixel values, etc. mode : {'mosaic', 'surface'}, str optional [backend='matplotlib'] Controls whether to turn the images into surface plots. rows : int, optional How many rows (subplots in a grid) in the case ``data`` is a tuple of 2d arrays. vmax : None, float/int or tuple of float/int, optional For defining the data range that the colormap covers. When set to None, the colormap covers the complete value range of the supplied data. vmin : None, float/int or tuple of float/int, optional For stretching the displayed pixels values. When set to None, the colormap covers the complete value range of the supplied data. circle : None, tuple or tuple of tuples, optional [backend='matplotlib'] To show a circle at the given px coordinates. The circles are shown on all subplots. circle_alpha : float or tuple of floats, optional [backend='matplotlib'] Alpha transparency for each circle. circle_color : str, optional [backend='matplotlib'] Color of the circles. White by default. circle_radius : int, optional [backend='matplotlib'] Radius of the circles, 6 px by default. circle_label : bool, optional [backend='matplotlib'] Whether to show the coordinates next to each circle. arrow : None or tuple of floats, optional [backend='matplotlib'] To show an arrow pointing to the given pixel coordinates. arrow_alpha : float, optional [backend='matplotlib'] Alpha transparency for the arrow. arrow_length : int, optional [backend='matplotlib'] Length of the arrow, 10 px by default. arrow_shiftx : int, optional [backend='matplotlib'] Shift in x of the arrow pointing position, 5 px by default. label : None, str or list of str/None, optional [backend='matplotlib'] Text for labeling each subplot. The label is shown at the bottom-left corner if each subplot. label_pad : int, optional [backend='matplotlib'] Padding of the label from the left bottom corner. 5 by default. label_size : int, optional [backend='matplotlib'] Size of the labels font. grid : bool or tuple of bools, optional [backend='matplotlib'] If True, a grid is displayed over the image, off by default. grid_alpha : None, float/int or tuple of None/float/int, optional [backend='matplotlib'] Alpha transparency of the grid. grid_color : str, optional [backend='matplotlib'] Color of the grid lines. grid_spacing : None, float/int or tuple of None/float/int, optional [backend='matplotlib'] Separation of the grid lines in pixels. cross : None or tuple of floats, optional [backend='matplotlib'] If provided, a crosshair is displayed at given pixel coordinates. cross_alpha : float, optional [backend='matplotlib'] Alpha transparency of the crosshair. ang_scale : bool or tuple of bools, optional [backend='matplotlib'] If True, the axes are displayed in angular scale (arcsecs). ang_ticksep : int, optional [backend='matplotlib'] Separation for the ticks when using axis in angular scale. pxscale : float, optional [backend='matplotlib'] Pixel scale in arcseconds/px. Default 0.01 (Keck/NIRC2, SPHERE-IRDIS). ang_legend : bool or tuple of bools, optional [backend='matplotlib'] If True a scaling bar (1 arcsec or 500 mas) will be added on the bottom-right corner of the subplots. axis : bool, optional [backend='matplotlib'] Show the axis, on by default. show_center : bool or tuple of bools, optional [backend='matplotlib'] To show a crosshair at the center of the frame. cmap : None, str or tuple of str, optional Colormap to be used. When None, the value of the global variable ``default_cmap`` will be used. Any string corresponding to a valid ``matplotlib`` colormap can be used. Additionally, 'ds9cool', 'ds9heat' and 'binary' (for binary maps) are valid colormaps for this function. log : bool or tuple of bool, optional [backend='matplotlib'] Log color scale. colorbar : bool or tuple of bool, optional To attach a colorbar, on by default. colorbar_ticks : None, tuple or tuple of tuples, optional [backend='matplotlib'] Custom ticks for the colorbar of each plot. dpi : int, optional [backend='matplotlib'] Dots per inch, determines how many pixels the figure comprises (which affects the plot quality). size_factor : int, optional [backend='matplotlib'] Determines the size of the plot by setting the figsize parameter (width x height [inches]) as size_factor * ncols, size_factor * nrows. horsp : float, optional [backend='matplotlib'] Horizontal gap between subplots. versp : float, optional [backend='matplotlib'] Vertical gap between subplots. width : int, optional [backend='bokeh'] Controls the width of each subplot. height : int, optional [backend='bokeh'] Controls the height of each subplot. title : None or str, optional [backend='matplotlib'] Title of the whole figure, None by default. sampling : int, optional [mode='surface'] Sets the stride used to sample the input data to generate the surface graph. save : None or str, optional If a string is provided the plot is saved using ``save`` as the path/filename. transparent : bool, optional [save=True] Whether to have a transparent background between subplots. If False, then a white background is shown. """ def check_bool_param(param, name): msg_type = '`' + name + '` must be a bool or tuple of bools' if isinstance(param, bool): param = [param] * num_plots elif isinstance(param, tuple): if not num_plots == len(param): msg = 'The len of `' + name + '` ({}) does not match the ' + \ 'number of plots ({})' raise ValueError(msg.format(len(param), num_plots)) else: for elem in param: if not isinstance(elem, bool): raise TypeError(msg_type) else: raise TypeError(msg_type) return param def check_numeric_param(param, name): msg_type = '`' + name + '` must be a None, float/int or tuple of ' + \ 'None/float/ints' if param is None: param = [None] * num_plots elif isinstance(param, (int, float)): param = [param] * num_plots elif isinstance(param, tuple): if not num_plots == len(param): msg = 'The len of `' + name + '` ({}) does not match the ' + \ 'number of plots ({})' raise ValueError(msg.format(len(param), num_plots)) else: for elem in param: if elem and not isinstance(elem, (float, int)): raise TypeError(msg_type) else: raise TypeError(msg_type) return param def check_str_param(param, name, default_value=None): msg_type = '`' + name + '` must be a None, str or tuple of ' + \ 'None/str' if param is None: param = [default_value] * num_plots elif isinstance(param, str): param = [param] * num_plots elif isinstance(param, tuple): if not num_plots == len(param): msg = 'The len of `' + name + '` ({}) does not match the ' + \ 'number of plots ({})' raise ValueError(msg.format(len(param), num_plots)) else: for elem in param: if elem and not isinstance(elem, str): raise TypeError(msg_type) else: raise TypeError(msg_type) return param # -------------------------------------------------------------------------- # Checking inputs: a frame (1 or 3 channels) or tuple of them msg_data_type = "`data` must be a frame (2d array) or tuple of frames" if isinstance(data, np.ndarray): if data.ndim == 2: data = [data] elif data.ndim == 3: raise TypeError(msg_data_type) elif isinstance(data, tuple): for i in range(len(data)): # checking the elements are 2d (excepting the case of 3 channels) if not data[i].ndim == 2 and data[i].shape[2] != 3: raise ValueError(msg_data_type) else: raise ValueError(msg_data_type) if not isinstance(backend, str): raise TypeError('`backend` must be a string. ' + msg_data_type) if backend == 'bokeh': if mode == 'surface': raise ValueError('Surface plotting only supported with matplotlib ' 'backend') if save is not None: raise ValueError('Saving is only supported with matplotlib backend') num_plots = len(data) if rows == 0: raise ValueError('Rows must be a positive integer') if num_plots % rows == 0: cols = int(num_plots / rows) else: cols = int((num_plots / rows) + 1) # CIRCLE ------------------------------------------------------------------- if circle is not None: if isinstance(circle, tuple): show_circle = True if isinstance(circle[0], tuple): n_circ = len(circle) coor_circle = circle elif isinstance(circle[0], (float, int)): n_circ = 1 coor_circle = [circle] * n_circ else: print("`circle` must be a tuple (X,Y) or tuple of tuples (X,Y)") show_circle = False else: show_circle = False if show_circle: if isinstance(circle_radius, (float, int)): # single value is provided, used for all circles circle_radius = [circle_radius] * n_circ elif isinstance(circle_radius, tuple): # a different value for each circle if not n_circ == len(circle_radius): msg = '`circle_radius` must have the same len as `circle`' raise ValueError(msg) else: raise TypeError("`circle_rad` must be a float or tuple of floats") if show_circle: if isinstance(circle_alpha, (float, int)): circle_alpha = [circle_alpha] * n_circ elif isinstance(circle_alpha, tuple): # a different value for each circle if not n_circ == len(circle_alpha): msg = '`circle_alpha` must have the same len as `circle`' raise ValueError(msg) # ARROW -------------------------------------------------------------------- if arrow is not None: if isinstance(arrow, tuple): show_arrow = True else: raise ValueError("`arrow` must be a tuple (X,Y)") else: show_arrow = False # VMAX-VMIN ---------------------------------------------------------------- vmin = check_numeric_param(vmin, 'vmin') vmax = check_numeric_param(vmax, 'vmax') # CROSS -------------------------------------------------------------------- if cross is not None: if not isinstance(cross, tuple): raise ValueError("`crosshair` must be a tuple (X,Y)") else: coor_cross = cross show_cross = True else: show_cross = False # AXIS, GRID, ANG_SCALE ---------------------------------------------------- axis = check_bool_param(axis, 'axis') grid = check_bool_param(grid, 'grid') grid_alpha = check_numeric_param(grid_alpha, 'grid_alpha') grid_spacing = check_numeric_param(grid_spacing, 'grid_spacing') show_center = check_bool_param(show_center, 'show_center') ang_scale = check_bool_param(ang_scale, 'ang_scale') ang_legend = check_bool_param(ang_legend, 'ang_legend') if isinstance(grid_color, str): grid_color = [grid_color] * num_plots if any(ang_scale) and save is not None: print("`Pixel scale set to {}`".format(pxscale)) # LABEL -------------------------------------------------------------------- label = check_str_param(label, 'label') # CMAP --------------------------------------------------------------------- custom_cmap = check_str_param(cmap, 'cmap', default_cmap) # COLORBAR ----------------------------------------------------------------- colorbar = check_bool_param(colorbar, 'colorbar') if colorbar_ticks is not None: cbar_ticks = colorbar_ticks # must be a tuple if isinstance(cbar_ticks, tuple): # tuple of tuples if isinstance(cbar_ticks[0], tuple): if not num_plots == len(cbar_ticks): raise ValueError('`colorbar_ticks` does not contain enough ' 'items') # single tuple elif isinstance(cbar_ticks[0], (float, int)): cbar_ticks = [colorbar_ticks] * num_plots else: raise TypeError('`colorbar_ticks` must be a tuple or tuple of ' 'tuples') else: cbar_ticks = [None] * num_plots # LOG ---------------------------------------------------------------------- logscale = check_bool_param(log, 'log') if any(logscale): # Showing bad/nan pixels with the darkest color in current colormap current_cmap = mplcm.get_cmap() current_cmap.set_bad(current_cmap.colors[0]) # -------------------------------------------------------------------------- if backend == 'matplotlib': # Creating the figure -------------------------------------------------- fig = figure(figsize=(cols * size_factor, rows * size_factor), dpi=dpi) if title is not None: fig.suptitle(title, fontsize=28, va='center', x=0.5, y=0.92) if mode == 'surface': plot_mosaic = False elif mode == 'mosaic': plot_mosaic = True else: raise ValueError("`mode` value was not recognized") for i, v in enumerate(range(num_plots)): image = data[i].copy() frame_size = image.shape[0] # assuming square frames cy = image.shape[0] / 2 - 0.5 cx = image.shape[1] / 2 - 0.5 v += 1 if plot_mosaic: ax = subplot(rows, cols, v) ax.set_aspect('equal') if logscale[i]: image += np.abs(image.min()) if vmin[i] is None: linthresh = 1e-2 else: linthresh = vmin[i] norm = colors.SymLogNorm(linthresh) else: norm = None if image.dtype == bool: image = image.astype(int) if custom_cmap[i] == 'binary' and image.max() == 1 and \ image.min() == 0: cucmap = cmap_binary cbticks = (0, 0.5, 1) else: cucmap = custom_cmap[i] cbticks = cbar_ticks[i] im = ax.imshow(image, cmap=cucmap, origin='lower', norm=norm, interpolation='nearest', vmin=vmin[i], vmax=vmax[i]) if colorbar[i]: divider = make_axes_locatable(ax) # the width of cax is 5% of ax and the padding between cax # and ax wis fixed at 0.05 inch cax = divider.append_axes("right", size="5%", pad=0.05) cb = plt_colorbar(im, ax=ax, cax=cax, drawedges=False, ticks=cbticks) cb.outline.set_linewidth(0.1) cb.ax.tick_params(labelsize=8) else: # Leave the import to make porjection='3d' work from mpl_toolkits.mplot3d import Axes3D x = np.outer(np.arange(0, frame_size, 1), np.ones(frame_size)) y = x.copy().T ax = subplot(rows, cols, v, projection='3d') ax.set_aspect('equal') surf = ax.plot_surface(x, y, image, rstride=sampling, cstride=sampling, linewidth=2, cmap=custom_cmap[i], antialiased=True, vmin=vmin[i], vmax=vmax[i]) ax.set_xlabel('x') ax.set_ylabel('y') ax.dist = 10 if title is not None: ax.set_title(title) if colorbar[i]: fig.colorbar(surf, aspect=10, pad=0.05, fraction=0.04) if ang_legend[i] and plot_mosaic: scaleng = 1. / pxscale scalab = '1 arcsec' scalabloc = scaleng / 2. - 8 if scaleng > frame_size / 2.: scaleng /= 2. scalab = '500 mas' scalabloc = scaleng / 2. - 8 scapad = 4 xma = frame_size - scapad xmi = xma - scaleng hlines(y=scapad, xmin=xmi, xmax=xma, colors='white', lw=1., linestyles='solid') annotate(scalab, (xmi + scalabloc, scapad + 2), color='white') if show_circle and plot_mosaic: for j in range(n_circ): circ = Circle(coor_circle[j], radius=circle_radius[j], fill=False, color=circle_color, alpha=circle_alpha[j]) ax.add_artist(circ) if circle_label: x = coor_circle[j][0] y = coor_circle[j][1] cirlabel = str(int(x))+','+str(int(y)) ax.text(x, y + 1.8 * circle_radius[j], cirlabel, fontsize=8, color='white', family='monospace', ha='center', va='top', weight='bold', alpha=circle_alpha[j]) if show_cross and plot_mosaic: ax.scatter([coor_cross[0]], [coor_cross[1]], marker='+', color='white', alpha=cross_alpha) if show_center[i] and plot_mosaic: ax.axhline(cx, xmin=0, xmax=frame_size, alpha=0.3, lw=0.6, linestyle='dashed', color='white') ax.axvline(cy, ymin=0, ymax=frame_size, alpha=0.3, lw=0.6, linestyle='dashed', color='white') if show_arrow and plot_mosaic: ax.arrow(arrow[0] + arrow_length + arrow_shiftx, arrow[1], -arrow_length, 0, color='white', head_width=6, head_length=4, width=2, length_includes_head=True, alpha=arrow_alpha) if label[i] is not None and plot_mosaic: ax.annotate(label[i], xy=(label_pad, label_pad), color='white', xycoords='axes pixels', weight='bold', size=label_size) if grid[i] and plot_mosaic: if grid_spacing[i] is None: if cy < 10: gridspa = 1 elif cy >= 10: if cy % 2 == 0: gridspa = 4 else: gridspa = 5 else: gridspa = grid_spacing[i] ax.tick_params(axis='both', which='minor') minor_ticks = np.arange(0, data[i].shape[0], gridspa) ax.set_xticks(minor_ticks, minor=True) ax.set_yticks(minor_ticks, minor=True) ax.grid(True, which='minor', color=grid_color[i], linewidth=0.5, alpha=grid_alpha[i], linestyle='dashed') else: ax.grid(False) if ang_scale[i] and plot_mosaic: # Converting axes from pixels to arcseconds half_num_ticks = int(np.round(cy // ang_ticksep)) # Calculate the pixel locations at which to put ticks ticks = [] for t in range(half_num_ticks, -half_num_ticks-1, -1): # Avoid ticks not showing on the last pixel if not cy - t * ang_ticksep == frame_size: ticks.append(cy - t * ang_ticksep) else: ticks.append((cy - t * ang_ticksep) - 1) ax.set_xticks(ticks) ax.set_yticks(ticks) # Corresponding distance in arcseconds, measured from the center labels = [] for t in range(half_num_ticks, -half_num_ticks-1, -1): labels.append(-t * (ang_ticksep * pxscale)) ax.set_xticklabels(labels) ax.set_yticklabels(labels) ax.set_xlabel("arcseconds", fontsize=12) ax.set_ylabel("arcseconds", fontsize=12) ax.tick_params(axis='both', which='major', labelsize=10) else: ax.set_xlabel("x", fontsize=12) ax.set_ylabel("y", fontsize=12) if not axis[i]: ax.set_axis_off() fig.subplots_adjust(wspace=horsp, hspace=versp) if save is not None and isinstance(save, str): savefig(save, dpi=dpi, bbox_inches='tight', pad_inches=0, transparent=transparent) close() else: show() elif backend == 'bokeh': hv.extension(backend) subplots = [] options = "Image (cmap='" + custom_cmap[0] + "')" # taking first item hv.opts(options) for i, v in enumerate(range(num_plots)): image = data[i].copy() if vmin[i] is None: vmin_i = image.min() if vmax[i] is None: vmax_i = image.max() im = hv.Image((range(image.shape[1]), range(image.shape[0]), image)) subplots.append(im.opts(tools=['hover'], colorbar=colorbar[i], colorbar_opts={'width': 15}, width=width, height=height, clim=(vmin_i, vmax_i))) return hv.Layout(subplots).cols(cols) else: raise ValueError('`backend` not supported')
def visualize_recent_residents_moved(self, options:opts=opts()): default_options = opts(title="A sample of residents who moved") df = pd.DataFrame(self.trend[-1].get('state_changed_sample', []), columns=["resident"]) if df.shape[0] == 0: return hv.Table([], ["Names of a few"]).opts(default_options).opts(options) return hv.Table((df.apply(lambda row: row['resident'].name, axis=1),), ["Names of a few"]).opts(default_options).opts(options)
""" An example app demonstrating how to use the HoloViews API to generate a bokeh app with complex interactivity. Uses a Selection1D stream to compute the mean y-value of the current selection. The app can be served using: bokeh serve --show selection_stream.py """ import numpy as np import holoviews as hv from holoviews.streams import Selection1D renderer = hv.renderer('bokeh') hv.opts("Points [tools=['box_select']]") data = np.random.multivariate_normal((0, 0), [[1, 0.1], [0.1, 1]], (1000, )) points = hv.Points(data) sel = Selection1D(source=points) mean_sel = hv.DynamicMap(lambda index: hv.HLine(points.iloc[index]['y'].mean() if index else -10), kdims=[], streams=[sel]) doc = renderer.server_doc(points * mean_sel) doc.title = 'HoloViews Selection Stream'
def interactive( umap_object, labels=None, values=None, hover_data=None, theme=None, cmap="Blues", color_key=None, color_key_cmap="Spectral", background="white", width=800, height=800, point_size=None, subset_points=None, ): """Create an interactive bokeh plot of a UMAP embedding. While static plots are useful, sometimes a plot that supports interactive zooming, and hover tooltips for individual points is much more desireable. This function provides a simple interface for creating such plots. The result is a bokeh plot that will be displayed in a notebook. Note that more complex tooltips etc. will require custom code -- this is merely meant to provide fast and easy access to interactive plotting. Parameters ---------- umap_object: trained UMAP object A trained UMAP object that has a 2D embedding. labels: array, shape (n_samples,) (optional, default None) An array of labels (assumed integer or categorical), one for each data sample. This will be used for coloring the points in the plot according to their label. Note that this option is mutually exclusive to the ``values`` option. values: array, shape (n_samples,) (optional, default None) An array of values (assumed float or continuous), one for each sample. This will be used for coloring the points in the plot according to a colorscale associated to the total range of values. Note that this option is mutually exclusive to the ``labels`` option. hover_data: DataFrame, shape (n_samples, n_tooltip_features) (optional, default None) A dataframe of tooltip data. Each column of the dataframe should be a Series of length ``n_samples`` providing a value for each data point. Column names will be used for identifying information within the tooltip. theme: string (optional, default None) A color theme to use for plotting. A small set of predefined themes are provided which have relatively good aesthetics. Available themes are: * 'blue' * 'red' * 'green' * 'inferno' * 'fire' * 'viridis' * 'darkblue' * 'darkred' * 'darkgreen' cmap: string (optional, default 'Blues') The name of a matplotlib colormap to use for coloring or shading points. If no labels or values are passed this will be used for shading points according to density (largely only of relevance for very large datasets). If values are passed this will be used for shading according the value. Note that if theme is passed then this value will be overridden by the corresponding option of the theme. color_key: dict or array, shape (n_categories) (optional, default None) A way to assign colors to categoricals. This can either be an explicit dict mapping labels to colors (as strings of form '#RRGGBB'), or an array like object providing one color for each distinct category being provided in ``labels``. Either way this mapping will be used to color points according to the label. Note that if theme is passed then this value will be overridden by the corresponding option of the theme. color_key_cmap: string (optional, default 'Spectral') The name of a matplotlib colormap to use for categorical coloring. If an explicit ``color_key`` is not given a color mapping for categories can be generated from the label list and selecting a matching list of colors from the given colormap. Note that if theme is passed then this value will be overridden by the corresponding option of the theme. background: string (optional, default 'white') The color of the background. Usually this will be either 'white' or 'black', but any color name will work. Ideally one wants to match this appropriately to the colors being used for points etc. This is one of the things that themes handle for you. Note that if theme is passed then this value will be overridden by the corresponding option of the theme. width: int (optional, default 800) The desired width of the plot in pixels. height: int (optional, default 800) The desired height of the plot in pixels point_size: int (optional, default None) The size of each point marker subset_points: array, shape (n_samples,) (optional, default None) A way to select a subset of points based on an array of boolean values. Returns ------- """ if theme is not None: cmap = _themes[theme]["cmap"] color_key_cmap = _themes[theme]["color_key_cmap"] background = _themes[theme]["background"] if labels is not None and values is not None: raise ValueError( "Conflicting options; only one of labels or values should be set") points = umap_object.embedding_ if subset_points is not None: if len(subset_points) != points.shape[0]: raise ValueError( "Size of subset points ({}) does not match number of input points ({})" .format(len(subset_points), points.shape[0])) points = points[subset_points] if points.shape[1] != 2: raise ValueError( "Plotting is currently only implemented for 2D embeddings") if point_size is None: point_size = 100.0 / np.sqrt(points.shape[0]) data = pd.DataFrame(umap_object.embedding_, columns=("x", "y")) if labels is not None: data["label"] = labels if color_key is None: unique_labels = np.unique(labels) num_labels = unique_labels.shape[0] color_key = _to_hex( plt.get_cmap(color_key_cmap)(np.linspace(0, 1, num_labels))) if isinstance(color_key, dict): data["color"] = pd.Series(labels).map(color_key) else: unique_labels = np.unique(labels) if len(color_key) < unique_labels.shape[0]: raise ValueError( "Color key must have enough colors for the number of labels" ) new_color_key = { k: color_key[i] for i, k in enumerate(unique_labels) } data["color"] = pd.Series(labels).map(new_color_key) colors = "color" elif values is not None: data["value"] = values palette = _to_hex(plt.get_cmap(cmap)(np.linspace(0, 1, 256))) colors = btr.linear_cmap("value", palette, low=np.min(values), high=np.max(values)) else: colors = matplotlib.colors.rgb2hex(plt.get_cmap(cmap)(0.5)) if subset_points is not None: data = data[subset_points] if hover_data is not None: hover_data = hover_data[subset_points] if points.shape[0] <= width * height // 10: if hover_data is not None: tooltip_dict = {} for col_name in hover_data: data[col_name] = hover_data[col_name] tooltip_dict[col_name] = "@" + col_name tooltips = list(tooltip_dict.items()) else: tooltips = None # bpl.output_notebook(hide_banner=True) # this doesn't work for non-notebook use data_source = bpl.ColumnDataSource(data) plot = bpl.figure( width=width, height=height, tooltips=tooltips, background_fill_color=background, ) plot.circle(x="x", y="y", source=data_source, color=colors, size=point_size) plot.grid.visible = False plot.axis.visible = False # bpl.show(plot) else: if hover_data is not None: warn("Too many points for hover data -- tooltips will not" "be displayed. Sorry; try subssampling your data.") hv.extension("bokeh") hv.output(size=300) hv.opts( 'RGB [bgcolor="{}", xaxis=None, yaxis=None]'.format(background)) if labels is not None: point_plot = hv.Points(data, kdims=["x", "y"]) plot = hd.datashade( point_plot, aggregator=ds.count_cat("color"), color_key=color_key, cmap=plt.get_cmap(cmap), width=width, height=height, ) elif values is not None: min_val = data.values.min() val_range = data.values.max() - min_val data["val_cat"] = pd.Categorical( (data.values - min_val) // (val_range // 256)) point_plot = hv.Points(data, kdims=["x", "y"], vdims=["val_cat"]) plot = hd.datashade( point_plot, aggregator=ds.count_cat("val_cat"), cmap=plt.get_cmap(cmap), width=width, height=height, ) else: point_plot = hv.Points(data, kdims=["x", "y"]) plot = hd.datashade( point_plot, aggregator=ds.count(), cmap=plt.get_cmap(cmap), width=width, height=height, ) return plot
# Shade the data shaded = shade(aggregated) # Define PointerX stream, attach to points and declare DynamicMap for cross-section and VLine pointer = hv.streams.PointerX(x=ddf.dropoff_x.loc[0].compute().iloc[0], source=points) section = hv.util.Dynamic(aggregated, operation=lambda obj, x: obj.sample(dropoff_x=x), streams=[pointer], link_inputs=False) vline = hv.DynamicMap(lambda x: hv.VLine(x), streams=[pointer]) # Define options hv.opts( "RGB [width=800 height=600 xaxis=None yaxis=None] VLine (color='black' line_width=1)" ) hv.opts( "Curve [width=100 yaxis=None show_frame=False] (color='black') {+framewise} Layout [shared_axes=False]" ) # Combine it all into a complex layout hvobj = (wmts * shaded * vline) << section ### Pass the HoloViews object to the renderer plot = renderer.get_plot(hvobj, doc=curdoc()) hist = hv.operation.histogram(aggregated, bin_range=(0, 10)) hist_plot = renderer.get_plot(hist, doc=curdoc()) # Define a slider and button
import holoviews as hv print('from holoviews_defaults') try: hv.extension('bokeh') hv.opts({'Curve': {'plot': {'tools': ['hover'], 'width': 1000}}}) hv.opts({'Points': {'plot': {'tools': ['hover'], 'width': 1000}}}) hv.opts({'Scatter': {'plot': {'tools': ['hover'], 'width': 1000}}}) hv.opts({'Histogram': {'plot': {'tools': ['hover'], 'width': 1000}}}) hv.opts({'HLine': {'color': 'black', 'line_width': 1, 'alpha': 0.5}}) except: pass
def plot_cubes(cube, mode='slider', backend='matplotlib', dpi=100, figtype='png', vmin=None, vmax=None, size=100, width=360, height=360, cmap=None, colorbar=True, dynamic=True, anim_path=None, data_step_range=None, label=None, label_step_range=None, delay=50, anim_format='gif', delete_anim_cache=True, **kwargs): """ Plot multi-dimensional high-contrast imaging datacubes (3d and 4d ``numpy`` arrays). It allows to visualize in-memory ``numpy`` arrays on ``Jupyterlab`` by leveraging the ``HoloViews`` library. It can also generate and save animations from a 3d ``numpy`` array with ``matplotlib``. Parameters ---------- cube : np.ndarray Input 3d or 4d cube. mode : {'slider', 'animation'}, str optional Whether to plot the 3d array as a widget with a slider or to save an animation of the 3d array. The animation is saved to disk using ImageMagick's convert command (it must be installed otherwise a ``FileNotFoundError`` will be raised). backend : {'matplotlib', 'bokeh'}, str optional Selects the backend used to display the plots. ``Bokeh`` plots are interactive, allowing the used to zoom, pan, inspect pixel values, etc. ``Matplotlib`` can lead to some flickering when using the slider and ``dynamic`` is True. dpi : int, optional [backend='matplotlib'] The rendered dpi of the figure. figtype : {'png', 'svg'}, str optional [backend='matplotlib'] Type of output. vmin : None, float or int, optional For defining the data range that the colormap covers. When set to None, the colormap covers the complete value range of the supplied data. vmax : None, float or int, optional For defining the data range that the colormap covers. When set to None, the colormap covers the complete value range of the supplied data. size : int, optional [backend='matplotlib'] Sets the size of the plot. width : int, optional [backend='bokeh'] Sets the width of the plot. height : int, optional [backend='bokeh'] Sets the height of the plot. cmap : None or str, optional Colormap. When None, the value of the global variable ``default_cmap`` will be used. colorbar : bool, optional If True, a colorbar is shown. dynamic : bool, optional [mode='slider'] When False, a ``HoloViews.HoloMap`` is created (slower and will take up a lot of RAM for large datasets). If True, a ``HoloViews.DynamicMap`` is created instead. anim_path : str, optional [mode='animation'] The animation path/filename. If None then the animation will be called ``animation``.``anim_format`` and will be saved in the current directory. data_step_range : tuple, optional [mode='animation'] Tuple of 1, 2 or 3 values that creates a range for slicing the ``data`` cube. label : str, optional [mode='animation'] Label to be overlaid on top of each frame of the animation. If None, then ``frame <#>`` will be used. label_step_range : tuple, optional [mode='animation'] Tuple of 1, 2 or 3 values that creates a range for customizing the label overlaid on top of each frame of the animation. delay : int, optional [mode='animation'] Delay for displaying the frames in the animation sequence. anim_format : str, optional [mode='animation'] Format of the saved animation. By default 'gif' is used. Other formats supported by ImageMagick are valid, such as 'mp4'. delete_anim_cache : str, optional [mode='animation'] If True, the cache folder is deleted once the animation file is saved to disk. **kwargs : dictionary, optional [mode='animation'] Arguments to be passed to ``plot_frames`` to customize each frame of the animation (adding markers, using a log scale, etc). Notes ----- http://holoviews.org/getting_started/Gridded_Datasets.html http://holoviews.org/user_guide/Gridded_Datasets.html http://holoviews.org/user_guide/Applying_Customizations.html """ hv.extension(backend) if not isinstance(cube, np.ndarray): raise TypeError('`cube` must be a numpy.ndarray') if cmap is None: cmap = default_cmap if mode == 'slider': if cube.ndim not in (3, 4): raise ValueError('`cube` must be a 3 or 4 array when `mode` set to ' 'slider') if cube.ndim == 3: # Dataset((X, Y, Z), Data), where # X is a 1D array of shape M , # Y is a 1D array of shape N and # Z is a 1D array of shape O # Data is a ND array of shape NxMxO ds = hv.Dataset((range(cube.shape[2]), range(cube.shape[1]), range(cube.shape[0]), cube), ['x', 'y', 'time'], 'flux') max_frames = cube.shape[0] elif cube.ndim == 4: # adding a lambda dimension ds = hv.Dataset((range(cube.shape[3]), range(cube.shape[2]), range(cube.shape[1]), range(cube.shape[0]), cube), ['x', 'y', 'time', 'lambda'], 'flux') max_frames = cube.shape[0] * cube.shape[1] # Matplotlib takes None but not Bokeh. We take global min & max instead if vmin is None: vmin = cube.min() if vmax is None: vmax = cube.max() print(ds) print(":Cube_shape\t{}".format(list(cube.shape[::-1]))) # not working for bokeh: dpi image_stack = ds.to(hv.Image, kdims=['x', 'y'], dynamic=dynamic) hv.output(backend=backend, size=size, dpi=dpi, fig=figtype, max_frames=max_frames) if backend == 'matplotlib': # keywords in the currently active 'matplotlib' renderer are: # 'alpha', 'clims', 'cmap', 'filterrad', 'interpolation', 'norm', # 'visible' options = "Image (cmap='" + cmap + "', interpolation='nearest'," options += " clims=("+str(vmin)+','+str(vmax)+")"+")" opts(options, image_stack) return image_stack.opts(opts.Image(colorbar=colorbar)) # hv.save(image_stack, 'holomap.gif', fps=5) elif backend == 'bokeh': options = "Image (cmap='" + cmap + "')" opts(options, image_stack) # Compensating the width to accommodate the colorbar if colorbar: cb_wid = 15 cb_pad = 3 tick_len = len(str(int(cube.max()))) if tick_len < 4: cb_tick = 25 elif tick_len == 4: cb_tick = 35 elif tick_len > 4: cb_tick = 45 width_ = width + cb_pad + cb_wid + cb_tick else: width_ = width return image_stack.opts(opts.Image(colorbar=colorbar, colorbar_opts={'width': 15, 'padding': 3}, width=width_, height=height, clim=(vmin, vmax), tools=['hover'])) elif mode == 'animation': if cube.ndim != 3: raise ValueError('`cube` must be a 3 array when `mode` set to ' 'animation') if backend == 'bokeh': print('Creating animations works with the matplotlib backend') dir_path = './animation_temp/' if anim_path is None: anim_path = './animation' if data_step_range is None: data_step_range = range(0, cube.shape[0], 1) else: if not isinstance(data_step_range, tuple): msg = '`data_step_range` must be a tuple with 1, 2 or 3 values' raise ValueError(msg) if len(data_step_range) == 1: data_step_range = range(data_step_range) elif len(data_step_range) == 2: data_step_range = range(data_step_range[0], data_step_range[1]) elif len(data_step_range) == 3: data_step_range = range(data_step_range[0], data_step_range[1], data_step_range[2]) if label_step_range is None: label_step_range = data_step_range else: if not isinstance(label_step_range, tuple): msg = '`label_step_range` must be a tuple with 1, 2 or 3 values' raise ValueError(msg) if len(label_step_range) == 1: label_step_range = range(label_step_range) elif len(label_step_range) == 2: label_step_range = range(label_step_range[0], label_step_range[1]) elif len(label_step_range) == 3: label_step_range = range(label_step_range[0], label_step_range[1], label_step_range[2]) if os.path.exists(dir_path): shutil.rmtree(dir_path) print('Replacing ' + dir_path) os.mkdir(dir_path) print('Producing each animation frame...') for i, labstep in zip(data_step_range, list(label_step_range)): if label is None: label = 'frame ' savelabel = dir_path + label + str(i + 100) plot_frames(cube[i], backend='matplotlib', mode='mosaic', save=savelabel, dpi=dpi, vmin=vmin, vmax=vmax, colorbar=colorbar, cmap=cmap, label=[label + str(labstep + 1)], **kwargs) try: filename = anim_path + '.' + anim_format call(['convert', '-delay', str(delay), dir_path + '*.png', filename]) if os.path.exists(filename): print('Animation successfully saved to disk as ' + filename) if delete_anim_cache: shutil.rmtree(dir_path) print('Temp directory deleted ' + dir_path) except FileNotFoundError: print('ImageMagick `convert` command could not be found') else: raise ValueError("`mode` is not recognized")
# This displays hour/minute marks for the x-ticks instead of milliseconds def clock_ms_tick_formatter() -> TickFormatter: milliseconds_since_epoch = 0 return FuncTickFormatter( code=""" var d = new Date(initial + tick); return "" + d.getHours() + ":" + ("00" + d.getMinutes()).slice(-2) + ":" + ("00" + d.getSeconds()).slice(-2); """, args={"initial": milliseconds_since_epoch}, ) opt = hv.opts(width=1200, height=250, xformatter=clock_ms_tick_formatter(), ylim=(-0.2, 1.2), show_legend=False, gridstyle=grid_style, show_grid=True) df_default = pd.DataFrame({}, columns=[ "mission_id", "annotation_time", "start_clock_ms", "end_clock_ms", "classification" ]) color_dict = { "SR": "blue", "STC": "lightgreen", "IOCA": "gray", "VF": "olive", "CPR": "cyan",
def colorblind_holoviews(): """Use colorblind pallette""" import holoviews as hv hv.opts({'Curve': {'style': dict(color=hv.Cycle('Colorblind'))}})
if front: #we want "seq" to be in the front #so append current column to the end of the list cols.append(x) else: #we want "seq" to be last, so insert this #column in the front of the new column list #"cols" we are building: cols.insert(0, x) return dataframe[cols] pd_nodes = pd.read_pickle('nodes.pkl') pd_edges = pd.read_pickle('edges-bundled.pkl') r_nodes = hv.Points(set_column_sequence(pd_nodes, ['x', 'y']), label='Nodes') r_edges = hv.Curve(pd_edges, label='Bundled') hv_layout=datashade(r_edges, **sz) * \ decimate(hv.Points(r_nodes),max_samples=1000) # Opts hv.opts( 'RGB [xaxis=None yaxis=None show_grid=False bgcolor="black" width={width} height={height}]' .format(**sz)) hv.opts('Points [tools=["hover"]] (color="cyan", size=3)') hv_plot = renderer.get_plot(hv_layout, curdoc()) bk_layout = layout([[hv_plot.state]], sizing_mode='fixed') curdoc().add_root(bk_layout)
import requests import param import parambokeh import holoviews as hv import geoviews as gv import datashader as ds import dask.dataframe as dd from cartopy import crs from bokeh.models import WMTSTileSource from holoviews.operation.datashader import datashade # Get renderer and set global display options hv.extension('bokeh') hv.opts("RGB [width=1200 height=682 xaxis=None yaxis=None show_grid=False]") hv.opts("Polygons (fill_color=None line_width=1.5) [apply_ranges=False tools=['tap']]") hv.opts("Points [apply_ranges=False] WMTS (alpha=0.5)") # Load census data df = dd.io.parquet.read_parquet('data/census.snappy.parq').persist() census_points = gv.Points(df, kdims=['easting', 'northing'], vdims=['race']) # Declare colormapping color_key = {'w': 'white', 'b': 'green', 'a': 'red', 'h': 'orange', 'o': 'saddlebrown'} races = {'w': 'White', 'b': 'Black', 'a': 'Asian', 'h': 'Hispanic', 'o': 'Other'} color_points = hv.NdOverlay({races[k]: gv.Points([0,0], crs=crs.PlateCarree())(style=dict(color=v)) for k, v in color_key.items()})
class ColormapPicker(hv.streams.Stream): # set up the colormap picker colormap = param.ObjectSelector( default=cm["kbc"], objects=[cm[k] for k in cm.keys() if not '_' in k]) cmap_picker = ColormapPicker(rename={'colormap': 'cmap'}, name='') widget = parambokeh.Widgets(cmap_picker, mode='raw') # the color picker shaded = datashade(dmap, streams=[hv.streams.RangeXY, cmap_picker], y_range=(-13, 7), y_sampling=0.10, x_sampling=0.050, height=1000) # "sampling" parameters control "pixel size" hv.opts( "RGB [width=400 height=800 xaxis=bottom yaxis=left fontsize={'title': '14pt'}]" ) hv.opts("Points [tools=['box_select']]") plot = renderer.get_plot( shaded, doc=curdoc()) ### Pass the HoloViews object to the renderer plot.state.quad(top=[-10.5], bottom=[-9.8], left=[2.7], right=[3.9], fill_color='white', fill_alpha=0.8, line_alpha=0.) plot.state.quad(top=[-5.5], bottom=[-4.8],
""" An example app demonstrating how to use the HoloViews API to generate a bokeh app with complex interactivity. Uses a Selection1D stream to compute the mean y-value of the current selection. The app can be served using: bokeh serve --show selection_stream.py """ import numpy as np import holoviews as hv from holoviews.streams import Selection1D renderer = hv.renderer('bokeh') hv.opts("Points [tools=['box_select']]") data = np.random.multivariate_normal((0, 0), [[1, 0.1], [0.1, 1]], (1000,)) points = hv.Points(data) sel = Selection1D(source=points) mean_sel = hv.DynamicMap(lambda index: hv.HLine(points.iloc[index]['y'].mean() if index else -10), kdims=[], streams=[sel]) doc = renderer.server_doc(points * mean_sel) doc.title = 'HoloViews Selection Stream'
def visualize_time_series(self, stats:List[str], rename_cols:Dict[str, str]=dict(), options:opts=opts()): """ Plots the given stats over a period of a time :param stats: names of statistics to plot :param rename_cols: any human readable names for the statistics :param options: plotting options for holoviews """ df = pd.DataFrame(self.trend).fillna(0) stats = list(map(lambda s: rename_cols.get(s, s), df.columns & stats)) df = df.rename(columns=rename_cols) point_curves = [hv.Scatter(df[["date", statistic]], label=statistic) for statistic in stats] line_curves = [hv.Curve(points) for points in point_curves] return (hv.Overlay(line_curves + point_curves)). opts(opts.Scatter(tools=["hover"], size=6)). opts(padding=0.05, height=375, legend_position="bottom", title=""). opts(options)
def get_plot(inp_x, inp_y, inp_clr): """Creates holoviews plot""" data, msg = prepare_data(inp_x, inp_y, inp_clr) source = bmd.ColumnDataSource(data=data) # hovering hover = get_hover(inp_x, inp_y, inp_clr) # tap tap = bmd.TapTool() tap.callback = bmd.OpenURL(url=explore_url + "/details/@uuid") # plot points = hv.Points( source.data, kdims=['x', 'y'], vdims=['color', 'name', 'uuid'], ) filtered = points.apply(filter_points, streams=[hv.streams.RangeXY(source=points)]) p_shaded = datashade( filtered, width=plot_px, height=plot_px, cmap=Plasma256, aggregator=ds.mean('color') # we want color of mean value under pixel ) p_hover = filtered.apply(hover_points) update_fn = functools.partial(update_legends, inp_x=inp_x, inp_y=inp_y, inp_clr=inp_clr) hv_plot = (dynspread(p_shaded) * p_hover).opts( hv.opts.Points( tools=[ tap, 'pan', 'box_zoom', 'save', 'reset', hover, ], active_tools=['wheel_zoom'], #active_scroll='box_zoom', #active_drag='box_zoom', alpha=0.2, hover_alpha=0.5, size=10, width=plot_px, height=plot_px, color='color', cmap=Plasma256, colorbar=True, show_grid=True, ), hv.opts(toolbar='above', finalize_hooks=[update_fn]), ) # output_backend='webgl', p_new = hv_renderer.get_plot(hv_plot).state return p_new, msg
import numpy as np from colorcet import cm from bokeh.models import WMTSTileSource from holoviews.operation.datashader import aggregate, shade from holoviews.operation import histogram from holoviews.streams import RangeXY, PlotSize hv.extension('bokeh') df = dd.read_parquet('./data/osm-1billion.snappy.parq/').persist() url = 'https://server.arcgisonline.com/ArcGIS/rest/services/World_Imagery/MapServer/tile/{Z}/{Y}/{X}.jpg' tiles = gv.WMTS(WMTSTileSource(url=url)) hv.opts( "WMTS [width=800 height=475 xaxis=None yaxis=None bgcolor='black']" "Histogram [logy=True] (fill_color='white') {+framewise} VLine (color='black')" ) class OSMExplorer(hv.streams.Stream): alpha = param.Magnitude(default=0.75, doc="Alpha value for the map opacity") cmap = param.ObjectSelector(default=cm["fire"], objects=cm.values()) min_count = param.Number(default=0, bounds=(0, 100)) output = parambokeh.view.Plot() def filter_count(agg, min_count, **kwargs): if min_count: agg = deepcopy(agg) agg.data.Count.data[agg.data.Count.data < min_count] = 0
import pandas as pd import holoviews as hv import hvplot.pandas import numpy as np from config import PED_ID, FLOW, SPEED, TIME, X, Y, PERS_ID, ENTRANCES_EXITS from holoviews import opts hv.extension('bokeh') default_opts = opts(height=600, width=800, tools=['hover'], active_tools=['wheel_zoom']) class Proband(): ''' Baseclass for person who took part in the experiment (Proband) ''' def __init__(self, pers_id, data, test_field): self.pers_id = pers_id self.data = data self.test_field = test_field self.avg_speed = self.average_speed() def average_speed(self): subdata = self.data[(self.data['X'] > self.test_field.XMIN) & ( self.data['X'] <= self.test_field.XMAX)].reset_index() try: lapse = subdata.iloc[-1][TIME] - subdata.iloc[0][TIME] speed = self.test_field.XDISTANCE / lapse # metros por segundo return speed except:
streams=[stream]) # Apply aggregation aggregated = aggregate(dmap, link_inputs=True) # Shade the data shaded = shade(aggregated) # Define PointerX stream, attach to points and declare DynamicMap for cross-section and VLine pointer = hv.streams.PointerX(x=ddf.dropoff_x.loc[0].compute().iloc[0], source=points) section = hv.util.Dynamic(aggregated, operation=lambda obj, x: obj.sample(dropoff_x=x), streams=[pointer], link_inputs=False) vline = hv.DynamicMap(lambda x: hv.VLine(x), streams=[pointer]) # Define options hv.opts("RGB [width=800 height=600 xaxis=None yaxis=None] VLine (color='black' line_width=1)") hv.opts("Curve [width=100 yaxis=None show_frame=False] (color='black') {+framewise} Layout [shared_axes=False]") # Combine it all into a complex layout hvobj = (wmts * shaded * vline) << section ### Pass the HoloViews object to the renderer plot = renderer.get_plot(hvobj, doc=curdoc()) hist = hv.operation.histogram(aggregated, bin_range=(0, 10)) hist_plot = renderer.get_plot(hist, doc=curdoc()) # Define a slider and button start, end = 0, 23 def slider_update(attrname, old, new):
PLAYER = sys.argv[2] if (len(sys.argv) > 2 and sys.argv[2] in PLAYERS) else 'P1' GAMEFILE = 'games/%s.txt' % GAME GAME_SEQ = 'json/%s_sequences.json' % GAME SORTS = ['diff', 'square'] SORT = sys.argv[3] if ((len(sys.argv) > 3 and sys.argv[3] in SORTS) or sys.argv[3].startswith('reachIterate=')) else 'diff' ALGS = sys.argv[4:] ITERATE = int( SORT[len('reachIterate='):]) if SORT.startswith('reachIterate=') else 500 renderer = hv.renderer('bokeh') dict_spec = {'Curve': {'plot': {'height': 500, 'width': 500}}} hv.opts(dict_spec) def render(obj): plot = renderer.get_plot(obj) size = renderer.get_size(plot) return renderer._figure_data(plot), size playerData = dict() # map of algName -> (p1,p2) genFunctions = dict() # map of algName -> genCurvesAlg tableFunctions = dict() # map of algName -> genTableAlg def makeGenerator(p1, p2, actions, alg): def genCurves(infoset=p1.keys()[0], player=PLAYER, **kwargs):
import dask.dataframe as dd from holoviews.operation.datashader import datashade, aggregate, shade from bokeh.models import WMTSTileSource renderer = hv.renderer('bokeh') # Load data usecols = ['tpep_pickup_datetime', 'dropoff_x', 'dropoff_y'] ddf = dd.read_csv('../data/nyc_taxi.csv', parse_dates=['tpep_pickup_datetime'], usecols=usecols) ddf['hour'] = ddf.tpep_pickup_datetime.dt.hour ddf = ddf.persist() # Declare objects stream = hv.streams.Counter() points = hv.Points(ddf, kdims=['dropoff_x', 'dropoff_y']) dmap = hv.DynamicMap(lambda counter: points.select(hour=counter%24).relabel('Hour: %s' % (counter % 24)), streams=[stream]) shaded = datashade(dmap) hv.opts('RGB [width=800, height=600, xaxis=None, yaxis=None]') url = 'https://server.arcgisonline.com/ArcGIS/rest/services/World_Imagery/MapServer/tile/{Z}/{Y}/{X}.jpg' wmts = gv.WMTS(WMTSTileSource(url=url)) overlay = wmts * shaded # Create server document doc = renderer.server_doc(overlay) dmap.periodic(1)
cmap_picker = ColormapPicker(rename={'colormap': 'cmap'}, name='') shaded = shade(aggregated, link_inputs=True, streams=[cmap_picker]) # Define PointerX stream, attach to points and declare DynamicMap for cross-section and VLine pointer = hv.streams.PointerX(x=ddf.dropoff_x.loc[0].compute().iloc[0], source=points) section = hv.util.Dynamic(aggregated, operation=lambda obj, x: obj.sample(dropoff_x=x), streams=[pointer], link_inputs=False).relabel('') vline = hv.DynamicMap(lambda x: hv.VLine(x), streams=[pointer]) # Define options hv.opts( "RGB [width=1200 height=600 xaxis=None yaxis=None fontsize={'title': '14pt'}] VLine (color='white' line_width=2)" ) hv.opts( "Curve [width=150 yaxis=None show_frame=False] (color='black') {+framewise} Layout [shared_axes=False]" ) # Combine it all into a complex layout hvobj = (tiles * shaded * vline) << section ### Pass the HoloViews object to the renderer plot = renderer.get_plot(hvobj, doc=curdoc()) # Define a slider and button start, end = 0, 23
colormap = param.ObjectSelector( default=cm["bgy"], # sets the default colormap to "blues" objects=[cm[k] for k in cm.keys() if not '_' in k]) cmap_picker = ColormapPicker(rename={'colormap': 'cmap'}, name='') widget = parambokeh.Widgets(cmap_picker, mode='raw') # the color picker shaded = datashade(dmap, streams=[hv.streams.RangeXY, cmap_picker], y_range=(-13, 7), y_sampling=0.1, x_sampling=0.05, height=1000) # "sampling" parameters control "pixel size" hv.opts( "RGB [width=400 height=800 xaxis=bottom yaxis=left fontsize={'title': '14pt'}]" ) hv.opts( "Curve [width=150 yaxis=None show_frame=False] (color='black') {+framewise} Layout [shared_axes=False]" ) plot = renderer.get_plot( shaded, doc=curdoc()) ### Pass the HoloViews object to the renderer def age_slider_update(attrname, old, new): age_stream.event(age=new) def mass_slider_update(attrname, old, new): mass_stream.event(mass=new)