def makeOutput(game): gameFile = 'games/%s.txt' % game seqFile = 'json/%s_sequences.json' % game dataFile = 'json/%s_datapoints.json' % game p1, p2 = parsing.processInfosets(gameFile) parsing.processSeqIDs(p1, p2, seqFile) parsing.getData(p1, p2, dataFile) ''' hm1 = hv.HoloMap({(i.player,name): genCurves(i) for p in (p1,p2) for name,i in p.items()}, kdims=['player','infoset']) ''' p1 = hv.HoloMap({name: genCurves(i) for name,i in p1.items()}, kdims=['infoset']) p2 = hv.HoloMap({name: genCurves(i) for name,i in p2.items()}, kdims=['infoset']) grid1 = hv.GridSpace(p1) grid2 = hv.GridSpace(p2) layout1 = hv.NdLayout(grid1).cols(2) layout2 = hv.NdLayout(grid2).cols(2) hv.output(layout1 + layout2, size=150, filename=game)
def visualize(self, deltas, phis, to_save, outname=None): hv.extension('matplotlib') tsteps= list(phis.keys()) # hmap*contours hmap = hv.HoloMap({t: hv.Image((self.xs, self.ys, phis[t])) for t in tsteps}) contour_hmap =hv.operation.contours(hmap, levels=5) phi_hmap = hmap * contour_hmap.opts(framewise=True, fig_inches=10) hmap_point = hv.HoloMap({t: hv.Points([(t,deltas[t])]) for t in tsteps}).opts(color='r', s=15) # delta curve try: deltas.pop(0.) except KeyError: print("deltas don't contain time=0 value") pass curve_hmap = (hv.Curve(deltas) *hmap_point).redim.label(x='time', y='delta') overlay_hmap = phi_hmap + curve_hmap # save hmap overlay as gif animation if to_save: outname = outname or utils.get_temp_fname(prefix='ls_propagate', suffix='.gif') hv.save((overlay_hmap.opts(framewise=True, fig_inches=10)), outname, fps=1) print("Saved simulation as gif: ", outname) return overlay_hmap
def plot_stimulus(obj, **args): spatial = args.get('spatial', False) bin = args.get('bin', float('Inf')) if np.isinf(bin): bins = np.array([0, obj.duration]) num = 1 else: bins = np.r_[0:obj.duration + bin / 1000.:bin / 1000.] num = bins.size - 1 if not spatial: grid = args.get('grid', False) hm = dict() tmin = np.min(obj.trace) tmax = np.max(obj.trace) for t in range(num): if num == 1: d = {i:hv.Curve((obj.time,obj.trace[i]))\ for i in range(obj.trace.shape[0])} else: d = {i:hv.Curve((obj.time,obj.trace[i]))*\ hv.Curve([(bins[t+1],tmin),(bins[t+1],tmax)]) for i in range(obj.trace.shape[0])} if grid: hvobj = hv.NdLayout(d) else: hvobj = hv.NdOverlay(d) hm[t] = hvobj hvobj = hv.HoloMap(hm, kdims='Time bin [' + str(bin) + ' ms]').collate() else: sur = args.get('surface', hand_surface) mid = (bins[1:] + bins[:-1]) / 2. d = np.array([np.interp(mid,obj.time,obj.trace[i])\ for i in range(obj.trace.shape[0])]) d = (d - np.min(d)) d = 1 - d / np.max(d) hm = dict() locs = sur.hand2pixel(obj.location) rad = obj.pin_radius * sur.pxl_per_mm for t in range(num): p = hv.Polygons( [{ ('x', 'y'): hv.Ellipse(locs[l, 0], locs[l, 1], 2 * rad).array(), 'z': d[l, t] } for l in range(obj.location.shape[0])], vdims='z').opts( plot=dict(color_index='z', aspect='equal'), style=dict(linewidth=0., line_width=0.01)).options(cmap='fire') hm[t] = p hvobj = hv.HoloMap(hm, kdims='Time bin [' + str(bin) + ' ms]') return hvobj
def moisture_budget_plots(h20b): import holoviews as hv def make_overlay(x): return hv.Dataset(x.to_array(name='water'))\ .to.curve()\ .overlay() hmap = hv.HoloMap({ 'Domain Mean': make_overlay(h20b.sel(time=slice(100, 140)).mean(['x', 'y'])), 'Location': make_overlay(h20b.isel(x=0, y=32)), 'Zonal Mean': make_overlay(h20b.isel(time=slice(1, 10)).mean(['x', 'time'])) }) opts = { 'Curve': dict( norm=dict(framewise=True, axiswise=True), plot=dict(width=400), ), 'NdOverlay.II': { 'plot': dict(show_legend=False) }, 'NdOverlay.I': { 'plot': dict(show_legend=False) }, } return hmap.layout().cols(2).opts(opts)
def plot_1d_min_max_with_region_bar( run_diags: RunDiagnostics, varfilter_min: str, varfilter_max: str, ) -> HVPlot: """Plot all diagnostics whose name includes varfilter. Plot is overlaid across runs. All matching diagnostics must be 1D.""" p = hv.Cycle("Colorblind") hmap = hv.HoloMap(kdims=["variable", "region", "run"]) variables_to_plot = run_diags.matching_variables(varfilter_min) for run in run_diags.runs: for min_var in variables_to_plot: max_var = min_var.replace(varfilter_min, varfilter_max) vmin = run_diags.get_variable(run, min_var).rename("min") vmax = run_diags.get_variable(run, max_var).rename("max") style = "solid" if run_diags.is_baseline(run) else "dashed" long_name = vmin.long_name region = min_var.split("_")[-1] # Area plot doesn't automatically add correct y label ylabel = f'{vmin.attrs["long_name"]} {vmin.attrs["units"]}' hmap[(long_name, region, run)] = hv.Area( (vmin.time, vmin, vmax), label="Min/max", vdims=["y", "y2"]).options(line_dash=style, color=p, alpha=0.6, ylabel=ylabel) return HVPlot(_set_opts_and_overlay(hmap))
def __init__(self, data): """ Arguments: - `data`: an object with attribute "embedding" e.g. TsneMapper() """ self._data = data if len(self._data.data_dims) == 0: self._points = hv.Points( self._data.embedding.reset_index(), #tsne.embedding.reset_index(), kdims=self._data.coord_dims, vdims=["Sequence"] + self._data.data_dims, label="Sequences", ) else: overlay_dict = {} for d in self._data.data_dims: p = hv.Points(self._data.embedding[self._data.coord_dims + [d]].rename(columns={ d: "Value" }).reset_index(), kdims=self._data.coord_dims, vdims=["Sequence", "Value"], label="Sequences") overlay_dict[d] = p #.opts(plot={"color_index"=d}) #self._points = hv.NdOverlay(overlay_dict, kdims=["Counts"]) self._points = hv.HoloMap(overlay_dict, kdims=["Counts"])
def get_html_header() -> str: """Return the javascript includes needed to render holoviews plots """ hv.extension("bokeh") hmap = hv.HoloMap() # need at least two plots in the holoviews for it to work hmap["a"] = hv.Curve([(0, 1), (0, 1)]) hmap["b"] = hv.Curve([(0, 1), (0, 1)]) fp = io.BytesIO() hv.save(hmap, fp, fmt="html") html = fp.getvalue().decode("UTF-8") # need to add root tag to parse with lxml doc = pq(html) header = "" for script in doc("script"): try: script.attrib["src"] except KeyError: pass else: # need to prevent self-closing script tags <src ... /> does not work in # Firefox (and maybe other browsers) header += (ET.tostring( script, short_empty_elements=False).decode("UTF-8").strip()) return header
def main(data_sequence_folder: str, limit: int, start: int, out: str): root = Path(data_sequence_folder) img_folder_path = root.joinpath("imgs/") npz_filepath = root.joinpath("rendered.npz") data = np.load(npz_filepath) datasource = {key: data[key] for key in data.files} images_filepaths = list(img_folder_path.glob("*.png")) images_filepaths.sort() limit = min(start + limit, len(images_filepaths) - 1) with_slides = {} for idx, filepath in enumerate(tqdm(images_filepaths[start:limit])): dataframe = dict([(key, str(value[start + idx])) for key, value in datasource.items()]) image = hv.RGB.load_image(str(filepath)) image.opts(title=f"Frame #{idx+1}") table = hv.Div(pformat(dataframe).replace("\n", "</br>")) fig = image + table with_slides[idx + 1] = fig data.close() hmap = hv.HoloMap(with_slides, "frame") hmap = hmap.collate() path_info = hv.Div(f"Sequence from {str(img_folder_path.parent)}") layout = hv.Layout([path_info] + [hmap]) hv.save(layout, "holomap.html")
def investigateOptimalAlgorithms(kmerId, kmerCount): plot.setLibrary('bokeh') plots = {} params = {'n_components':N_PCA_COMPONENTS, 'random_state':42} algos = ( ('PCA', decomposition.PCA(**params)), ('LLE', manifold.LocallyLinearEmbedding(method='standard', **params)), ('LTSA', manifold.LocallyLinearEmbedding(method='ltsa', **params)), ('Hessian LLE', manifold.LocallyLinearEmbedding(method='hessian', n_neighbors=10, **params)), ('Modified LLE', manifold.LocallyLinearEmbedding(method='modified', **params)), ('tSNE', manifold.TSNE(**params)), ('Isomap', manifold.Isomap(n_components=N_PCA_COMPONENTS)), ('MDS', manifold.MDS(**params)), ('SE', manifold.SpectralEmbedding(**params))) ## Visualise data and manually determine which algorithm will be good for i, (name, algo) in enumerate(algos, 1): com = _getComponents(algo, kmerCount) com = pd.DataFrame(com, columns=PCA_DATA_COL_NAMES) kmerDf = pd.concat([kmerId, com], axis=1) dataset = hv.Dataset(kmerDf, PCA_DATA_COL_NAMES) scatter = dataset.to(hv.Scatter, PCA_DATA_COL_NAMES) scatter.opts(opts.Scatter(size=10, show_legend=True)) plots[name] = scatter plots = hv.HoloMap(plots, kdims='algo') plots = plots.collate() return plots
def test_holoviews_widgets_invalid_widget_type_override(): hmap = hv.HoloMap({(i, chr(65 + i)): hv.Curve([i]) for i in range(3)}, kdims=['X', 'Y']) with pytest.raises(ValueError): HoloViews.widgets_from_dimensions(hmap, widget_types={'X': 1})
def plot_data(self, feature_name): """ Plots the FeatureType.DATA of eopatch. :param feature_name: name of the eopatch feature :type feature_name: str :return: visualization :rtype: holoview/geoviews/bokeh """ crs = self.eopatch.bbox.crs crs = CRS.POP_WEB if crs is CRS.WGS84 else crs data_da = array_to_dataframe(self.eopatch, (FeatureType.DATA, feature_name), crs=crs) if self.mask: data_da = self.mask_data(data_da) timestamps = self.eopatch.timestamp crs = self.eopatch.bbox.crs if not self.rgb: return data_da.hvplot(x='x', y='y', crs=ccrs.epsg(crs.epsg)) data_rgb = self.eopatch_da_to_rgb(data_da, feature_name, crs) rgb_dict = { timestamp_: self.plot_rgb_one(data_rgb, timestamp_) for timestamp_ in timestamps } return hv.HoloMap(rgb_dict, kdims=['time'])
def test_holoviews_widgets_explicit_widget_instance_override(): hmap = hv.HoloMap({(i, chr(65+i)): hv.Curve([i]) for i in range(3)}, kdims=['X', 'Y']) widget = Select(options=[1, 2, 3], value=3) widgets, _ = HoloViews.widgets_from_dimensions(hmap, widget_types={'X': widget}) assert widgets[0] is widget
def investigateOptimalAlgorithms(kmerId, kmerPca): plot.setLibrary('bokeh') pca = kmerPca.loc[:, PCA_DATA_COL_NAMES] plots = {} algos = ( ('Elliptic', EllipticEnvelope()), ('SVM', OneClassSVM()), ('Forest', IsolationForest()), ('Local', LocalOutlierFactor())) ## Visualise data and manually determine which algorithm will be good for i, (name, algo) in enumerate(algos, 1): labels = _getLabels(algo, pca) labels = pd.DataFrame(labels, columns=[OLABEL_COL_NAME]) kmerDf = pd.concat([kmerId, pca, labels], axis=1) dataset = hv.Dataset(kmerDf, PCA_DATA_COL_NAMES) scatter = dataset.to(hv.Scatter, PCA_DATA_COL_NAMES, groupby=OLABEL_COL_NAME).overlay() scatter.opts(opts.Scatter(size=10, show_legend=True)) plots[name] = scatter plots = hv.HoloMap(plots, kdims='algo') plots = plots.collate() return plots
def _holoviews_get_metrics(self, color_map: dict = {}, label_map: dict = {}): """ Creates holoviews plot for every not node specific metric over time Returns: holoviews.HoloMap: holoviews object representing plot """ metric_names = [ name for name in next(iter( self._calculated_networks.values())).graph.keys() ] curve_dict = {} for metric_name in metric_names: name = label_map.get(metric_name, metric_name) curve_dict[name] = hv.Curve( (list(self._calculated_networks.keys()), list( map(lambda x: x.graph[metric_name], self._calculated_networks.values()))), kdims='Time', vdims='Value') if metric_name in color_map: curve_dict[name].opts(color=color_map[metric_name]) ndoverlay = hv.NdOverlay(curve_dict) distribution = hv.HoloMap({i: (ndoverlay * hv.VLine(i)).relabel(group='Metrics') for i in self._calculated_networks.keys()}, kdims='Time')\ .opts(width=400, height=400, padding=0.1) return distribution
def draw_holoviews_graphs(graph_dict): # use first key to determine default settings first_key = list(graph_dict.keys())[0] molecule, ksize, log2sketchsize = first_key hv.extension('bokeh') defaults = dict(width=400, height=400, padding=0.1) hv.opts.defaults(opts.EdgePaths(**defaults), opts.Graph(**defaults), opts.Nodes(**defaults)) kdims = [ hv.Dimension(('molecule', "molecule"), default=molecule), hv.Dimension(('ksize', "k-mer size"), default=ksize), hv.Dimension(('log2_num_hashes', "$\log_2$ num hashes"), default=log2sketchsize), ] kwargs = dict(width=800, height=800, xaxis=None, yaxis=None) opts.defaults(opts.Nodes(**kwargs), opts.Graph(**kwargs)) kwargs = dict(node_size=10, edge_line_width=1, cmap='Set2', node_color=dim("species"), node_line_color='gray', width=600, height=600, xaxis=None, yaxis=None) holomap = hv.HoloMap(graph_dict, kdims=kdims) holomap.opts(opts.Graph(**kwargs)) return holomap
def __post_init__(self): """ :return: """ data = self.spectral_cube.data self.ds = hv.Dataset((np.arange(data.shape[2]), np.arange( data.shape[1]), np.arange(data.shape[0]), data), [self.spectral_axis_name, 'x', 'y'], 'Cube') # maybe PolyEdit as well # polys = hv.Polygons([hv.Box(int(self.image_width / 2), int(self.image_height / 2), int(self.image_height / 2))]) # self.box_stream = streams.PolyEdit(source=polys) polys = hv.Polygons([]) self.box_stream = streams.BoxEdit(source=polys) hlines = hv.HoloMap({i: hv.VLine(i) for i in range(data.shape[2])}, 'wavelengths') dmap = hv.DynamicMap(self.roi_curves, streams=[self.box_stream]) im = self.ds.to(hv.Image, ['x', 'y'], dynamic=True) self.layout = (im * polys + dmap * hlines).opts( opts.Image(cmap=self.color_map, width=self.image_width, height=self.image_height), opts.Curve(width=650, height=450, framewise=True), opts.Polygons(fill_alpha=0.2, line_color='white'), opts.VLine(color='black'))
def plot( metrics, x="step", y="mean_episode_return", palette="Set1", kdims=["lr"], kdims_facet=["lstm"], subsample=1000, cols=3, ): hmap = {} model2color = {} colors = hv.Palette(palette).values colors = list(set(colors)) for _facet, models in metrics.items(): for model, _ in models.items(): if model not in model2color: model2color[model] = colors[len(model2color) - 1] for facet, models in metrics.items(): p = plot_facet( models, x, y, palette, model2color, kdims=kdims_facet, subsample=subsample ) if facet not in hmap: hmap[facet] = {} hmap[facet] = p p = hv.HoloMap(hmap, kdims=kdims) p = hv.NdLayout(p).cols(cols) return p
def investigateOptimalAlgorithms(kmerId, kmerPca): plot.setLibrary('bokeh') pca = kmerPca.loc[:, PCA_DATA_COL_NAMES] plots = {} algos = (('KMeans', cluster.KMeans()), ('Affinity', cluster.AffinityPropagation()), ('MeanShift', cluster.MeanShift()), ('Spectral', cluster.SpectralClustering()), ('Agglomerative', cluster.AgglomerativeClustering(linkage='average')), ('Agglomerative', cluster.AgglomerativeClustering(linkage='ward')), ('DBSCAN', cluster.DBSCAN()), ('Gaussian', GaussianMixture())) ## Visualise data and manually determine which algorithm will be good for i, (name, algo) in enumerate(algos, 1): labels = _getLabels(algo, pca) labels = pd.DataFrame(labels, columns=[CLABEL_COL_NAME]) kmerDf = pd.concat([kmerId, pca, labels], axis=1) dataset = hv.Dataset(kmerDf, PCA_DATA_COL_NAMES) scatter = dataset.to(hv.Scatter, PCA_DATA_COL_NAMES, groupby=CLABEL_COL_NAME).overlay() scatter.opts(opts.Scatter(size=10, show_legend=True)) plots[name] = scatter plots = hv.HoloMap(plots, kdims='algo') plots = plots.collate() return plots
def test_holoviews_with_widgets(document, comm): hmap = hv.HoloMap({(i, chr(65+i)): hv.Curve([i]) for i in range(3)}, kdims=['X', 'Y']) hv_pane = HoloViews(hmap) layout = hv_pane.get_root(document, comm) model = layout.children[0] assert len(hv_pane.widget_box.objects) == 2 assert hv_pane.widget_box.objects[0].name == 'X' assert hv_pane.widget_box.objects[1].name == 'Y' assert hv_pane._models[layout.ref['id']][0] is model hmap = hv.HoloMap({(i, chr(65+i)): hv.Curve([i]) for i in range(3)}, kdims=['A', 'B']) hv_pane.object = hmap assert len(hv_pane.widget_box.objects) == 2 assert hv_pane.widget_box.objects[0].name == 'A' assert hv_pane.widget_box.objects[1].name == 'B'
def hv_plot_stack(img_list, timepoints=None): if not timepoints: timepoints = range(len(img_list)) dictionary = {int(t): hv.Image(arr, bounds=None, kdims=['x', 'y']) for t, arr in zip(timepoints, img_list)} return hv.HoloMap(dictionary, kdims=['Time'])
def plot_wfs_in_cross_section(lead, params, k, num_bands=40): xy, energies, densities = get_densities(lead, k, params) wfs = [ kwant.plotter.mask_interpolate(xy, density, oversampling=1)[0] for density in densities[:num_bands] ] ims = {E: hv.Image(wf) for E, wf in zip(energies, wfs)} return hv.HoloMap(ims, kdims=[hv.Dimension("E", unit="meV")])
def get_holomap(df): """ Produce a dictionary linking tuples of the form (timestamp, N, hour, is_baseline) to their corresponding data """ holomap = hv.HoloMap( {mi_tuple: points(df, *mi_tuple) for mi_tuple in df.columns}, kdims=['timestamp', 'N', 'hour', 'is_baseline']) return holomap
def test_holoviews_widgets_explicit_widget_type_override(): hmap = hv.HoloMap({(i, chr(65+i)): hv.Curve([i]) for i in range(3)}, kdims=['X', 'Y']) widgets, _ = HoloViews.widgets_from_dimensions(hmap, widget_types={'X': Select}) assert isinstance(widgets[0], Select) assert widgets[0].name == 'X' assert widgets[0].options == OrderedDict([(str(i), i) for i in range(3)]) assert widgets[0].value == 0
def plot_model( runs, x="step", y="mean_episode_return", model="model", color="#ff0000", subsample=1000, ): hmap = {} # Interpolate the data on an even grid. With min(np.amin(...)) # this starts where the first data starts and ends where the last # data ends. Interpolation of missing data will create artefacts. # An alternative would be to throw away data and the end and do # max(np.amin(...)) etc. xmin = min(np.amin(config["df"][x].values) for _, config in runs.items()) xmax = max(np.amax(config["df"][x].values) for _, config in runs.items()) xnum = max(len(config["df"][x]) for _, config in runs.items()) grid = np.linspace(xmin, xmax, xnum) for run, config in runs.items(): df = config["df"] yvalues = np.interp(grid, df[x].values, df[y].values) df = pd.DataFrame({x: grid, y: yvalues}) p = plot_run(df, x, y, model, color, subsample) p.opts(opts.Curve(f"Curve", color=color, alpha=0.2)) hmap[run] = p hmap = hv.HoloMap(hmap) p_runs = hmap.overlay().relabel("Runs") hmap_mean = hv.HoloMap(hmap) p_mean = hmap_mean.collapse(function=np.mean) p_mean = hv.Curve(p_mean).relabel(model) p_mean.opts(opts.Curve("Curve", color=color)) p = p_runs * p_mean # p = p_runs * p_mean * p_std # Plot options p.opts(opts.NdOverlay("NdOverlay.Runs", show_legend=False)) return p
def test_holoviews_widgets_update_plot(document, comm): hmap = hv.HoloMap({(i, chr(65+i)): hv.Curve([i]) for i in range(3)}, kdims=['X', 'Y']) hv_pane = HoloViews(hmap, backend='bokeh') layout = hv_pane.get_root(document, comm) cds = layout.children[0].select_one(ColumnDataSource) assert cds.data['y'] == np.array([0]) hv_pane.widget_box[0].value = 1 hv_pane.widget_box[1].value = chr(65+1) assert cds.data['y'] == np.array([1])
def test_holoviews_with_widgets_not_shown(document, comm): hmap = hv.HoloMap({(i, chr(65+i)): hv.Curve([i]) for i in range(3)}, kdims=['X', 'Y']) hv_pane = HoloViews(hmap, show_widgets=False) layout_obj = Column(hv_pane, hv_pane.widget_box) layout = layout_obj._get_root(document, comm) model = layout.children[0] assert len(hv_pane.widget_box.objects) == 2 assert hv_pane.widget_box.objects[0].name == 'X' assert hv_pane.widget_box.objects[1].name == 'Y' assert layout.ref['id'] in hv_pane._callbacks assert hv_pane._models[layout.ref['id']] is model hmap = hv.HoloMap({(i, chr(65+i)): hv.Curve([i]) for i in range(3)}, kdims=['A', 'B']) hv_pane.object = hmap assert model.ref['id'] not in hv_pane._callbacks assert len(hv_pane.widget_box.objects) == 2 assert hv_pane.widget_box.objects[0].name == 'A' assert hv_pane.widget_box.objects[1].name == 'B'
def generate_holo_map(rgb_images, height, width): frame_map = {} for i, image in enumerate(rgb_images): # print('image type: ' + str(type(image))) hv_rgb = hv.RGB(np.array(image)) shape = image.shape frame_map[i] = hv_rgb holomap = hv.HoloMap(frame_map) holomap = holomap.options(width=int(width), height=int(height)) return holomap
def test_holoviews_date_slider_widgets_from_holomap(): hmap = hv.HoloMap({dt.datetime(2016, 1, i+1): hv.Curve([i]) for i in range(3)}, kdims=['X']) widgets, _ = HoloViews.widgets_from_dimensions(hmap) assert isinstance(widgets[0], DiscreteSlider) assert widgets[0].name == 'X' assert widgets[0].options == OrderedDict([ ('2016-01-01 00:00:00', dt.datetime(2016, 1, 1)), ('2016-01-02 00:00:00', dt.datetime(2016, 1, 2)), ('2016-01-03 00:00:00', dt.datetime(2016, 1, 3))]) assert widgets[0].value == dt.datetime(2016, 1, 1)
def _plot_vector(self, eopatch: EOPatch): """A visualization for vector feature""" crs = eopatch.bbox.crs timestamps = eopatch.timestamp data_gpd = self._fill_vector(eopatch) if crs is CRS.WGS84: crs = CRS.POP_WEB data_gpd = data_gpd.to_crs(crs.pyproj_crs()) shapes_dict = { timestamp_: self._plot_shapes_one(data_gpd, timestamp_, crs) for timestamp_ in timestamps } return hv.HoloMap(shapes_dict, kdims=["time"])
def get_plot_curve(x, y): mdist, mdata = extract_timeseries(x, y, data.sx, data.sy, dataset) if mdist > data.mdist: mdata = mdata * np.nan hdynamic = hv.Curve((data.time, mdata)).opts(color='k', line_width=2, line_dash='dotted') hcurve = hv.HoloMap({ 'dynamic': hdynamic, **{(i + 1): k for i, k in enumerate(data.curve)} }).overlay() return hcurve