def addVector(start, v): global color_index color = colors[color_index] color_index = (color_index + 1) % len(colors) end = start + v trace = go.Scatter3d(x=[start[0], end[0], None], y=[start[1], end[1], None], z=[start[2], end[2], None], mode='lines', name=str(v), line=dict(color=color, width=4)) norm = np.sqrt(np.sum(v * v)) n = v if norm == 0 else v / norm n = 1.5 * n c_end = end - 0.37 * n cone = go.Cone(x=[c_end[0]], y=[c_end[1]], z=[c_end[2]], u=[n[0]], v=[n[1]], w=[n[2]], name=str(v), colorscale=[[0, color], [1, color]], hoverinfo="none", showscale=False) data.append(trace) data.append(cone)
def get_3D_quiver_trace(points, directions, color='#bd1540', name=''): assert points.shape[ 1] == 3, "3d cone plot input points are not correctely shaped " assert len(points.shape ) == 2, "3d cone plot input points are not correctely shaped " assert directions.shape[ 1] == 3, "3d cone plot input directions are not correctely shaped " assert len( directions.shape ) == 2, "3d cone plot input directions are not correctely shaped " trace = go.Cone(name=name, x=points[:, 0].cpu(), y=points[:, 1].cpu(), z=points[:, 2].cpu(), u=directions[:, 0].cpu(), v=directions[:, 1].cpu(), w=directions[:, 2].cpu(), sizemode='absolute', sizeref=0.125, showscale=False, colorscale=[[0, color], [1, color]], anchor="tail") return trace
def draw_vector_R3(h, t=np.zeros((3, )), color='rgb(0, 0, 0)', name='', arrow_size=0., showlegend=False, textposition=None): q = np.linalg.norm(h - t) f = lambda q: np.exp(np.power(q / 2.5, 2.5 / 9)) if arrow_size == 0.: a = .99 - np.exp(-f(q)) arrow_size = .6 * (a**(1.7)) g = lambda q: 1. - np.exp(-0.85 * q) q = .99 - np.exp(-g(q) * f(q)) x, y, z = h u, v, w = h - t cone = go.Cone(x=[x], y=[y], z=[z], u=[u], v=[v], w=[w], anchor="tip", sizemode="absolute", sizeref=arrow_size, name=name, hoverinfo='x+y+z+name', hoverlabel=dict(bgcolor=color), colorscale=[[0, color], [0.5, color], [1.0, color]], showscale=False) lx = [t[0], t[0] + q * (h[0] - t[0])] ly = [t[1], t[1] + q * (h[1] - t[1])] lz = [t[2], t[2] + q * (h[2] - t[2])] l = go.Scatter3d( x=lx, y=ly, z=lz, showlegend=showlegend, text=['', name], textfont=dict(color=color), hoverinfo='none', line=dict( color=color, # color='rgb(0, 255, 0)', width=9, ), mode='lines, text') mx = np.max(np.abs([h, t])) data = [l, cone] return data, mx
def vector_plot(result, titles, verbose=False, **kwargs): variable = titles['variable'] val0 = list(result.values())[0] if (result[variable].shape == val0.shape) & (val0.shape[1] == 2): if verbose: print('\t 2-d output', result[variable].shape) u = result[variable][:, 0] v = result[variable][:, 1] x = val0[:, 0] y = val0[:, 1] trace = ff.create_quiver( x, y, u, v, # scale=.25, # arrow_scale=.4, name='quiver', line=dict(width=1))['data'][0] # extracts quiver trace layout = go.Layout(title=titles['title'], xaxis=dict(title='x'), yaxis=dict(title='y')) chart_type = '2d-vector' elif (result[variable].shape == val0.shape) & (val0.shape[1] == 3): if verbose: print('\t 3-d output', result[variable].shape) u = result[variable][:, 0].tolist() v = result[variable][:, 1].tolist() w = result[variable][:, 2].tolist() x = val0[:, 0].tolist() y = val0[:, 1].tolist() z = val0[:, 2].tolist() trace = go.Cone(x=x, y=y, z=z, u=u, v=v, w=w) layout = go.Layout(title=titles['title'], scene=dict( xaxis=dict(title='x'), yaxis=dict(title='y'), zaxis=dict(title='z'), )) chart_type = '3d-vector' else: raise NotImplementedError('plot type not supported yet') return [trace], chart_type, layout
def draw(self): from mlreco.visualization import plotly_layout3d from mlreco.visualization.voxels import scatter_voxels, scatter_label import plotly.plotly as py import plotly.graph_objs as go from plotly.offline import init_notebook_mode, iplot init_notebook_mode(connected=False) # Create labels for the voxels # Use a different color for each cluster labels = np.full(len(self.output['energy'][:,-1]), -1) for i, s in enumerate(self.output['showers']): labels[s.voxels] = i # Draw voxels with cluster labels voxels = self.output['energy'][:,:3] graph_voxels = scatter_label(voxels, labels, 2)[0] graph_voxels.name = 'Shower ID' graph_data = [graph_voxels] if len(self.output['showers']): # Add EM primary points points = np.array([s.start for s in self.output['showers']]) graph_start = scatter_voxels(points)[0] graph_start.name = 'Shower starts' graph_data.append(graph_start) # Add EM primary directions dirs = np.array([s.direction for s in self.output['showers']]) arrows = go.Cone(x=points[:,0], y=points[:,1], z=points[:,2], u=dirs[:,0], v=dirs[:,1], w=dirs[:,2], sizemode='absolute', sizeref=0.25, anchor='tail', showscale=False, opacity=0.4) graph_data.append(arrows) # Add a vertex if matches, join vertex to start points for i, m in enumerate(self.output['matches']): v = self.output['vertices'][i] s1, s2 = self.output['showers'][m[0]].start, self.output['showers'][m[1]].start points = [v, s1, v, s2] line = scatter_voxels(np.array(points))[0] line.name = 'Pi0 Decay' line.mode = 'lines,markers' graph_data.append(line) # Draw iplot(go.Figure(data=graph_data,layout=plotly_layout3d()))
def vector_plot(result, titles, verbose = False, **kwargs): variable = titles['variable'] val0 = list(result.values())[0] # check if this is a 2d vector plot: input and output should have shape 2d if (result[variable].shape == val0.shape) & (val0.shape[1] == 2): if verbose: print('\t 2-d output', result[variable].shape) u = result[variable][:, 0] v = result[variable][:, 1] x = val0[:, 0] y = val0[:, 1] # plotly's quiver plot has its own defaults quiver_defaults = get_defaults(ff.create_quiver) for k, v_ in kwargs.items(): if k in quiver_defaults: quiver_defaults[k] = v_ if verbose: print(quiver_defaults) try: trace = ff.create_quiver( x, y, u, v, name='quiver', line=dict(width=1), **quiver_defaults)['data'][0] # extracts quiver trace except: print('problem with quiver, u,v,x,y shapes:') for v_ in [u, v, x, y]: print(v_.shape) raise layout = go.Layout(title=titles['title'], xaxis=dict(title='x'), yaxis=dict(title='y')) chart_type = '2d-vector' # check if this is a 3d vector plot: input and output should have shape 3d elif (result[variable].shape == val0.shape) & (val0.shape[1] == 3): if verbose: print('\t 3-d output', result[variable].shape, val0.shape) print('\t 3d vector plot') if type(result[variable]) == pd.DataFrame: u = result[variable].values[:, 0].tolist() v = result[variable].values[:, 1].tolist() w = result[variable].values[:, 2].tolist() else: u = result[variable][:, 0].tolist() v = result[variable][:, 1].tolist() w = result[variable][:, 2].tolist() if type(val0) == pd.DataFrame: x = val0.values[:, 0].tolist() y = val0.values[:, 1].tolist() z = val0.values[:, 2].tolist() else: x = val0[:, 0].tolist() y = val0[:, 1].tolist() z = val0[:, 2].tolist() # normalize each vector to get the length norms = np.linalg.norm(result[variable], axis=1) trace = go.Cone( x=x, y=y, z=z, u=u, v=v, w=w, hoverinfo='x+y+z+u+v+w+norm', colorscale='Reds', cmin=0, cmax=norms.max(), ) layout = go.Layout( title=titles['title'], scene=dict( xaxis=dict(title='x'), yaxis=dict(title='y'), zaxis=dict(title='z'), )) chart_type = '3d-vector' else: raise NotImplementedError('plot type not supported yet') return [trace], chart_type, layout
def display_scatterplot_3D(model, user_input=None, words=None, label=None, color_map=None, annotation='On', dim_red='PCA', perplexity=0, learning_rate=0, iteration=0, topn=0, sample=10): if words == None: if sample > 0: words = np.random.choice(list(model.wv.vocab.keys()), sample) else: words = np.random.choice(list(model.wv.vocab.keys()), 10) word_vectors = np.array([model.wv.get_vector(w) for w in words]) if dim_red == 'PCA': three_dim = PCA(random_state=0).fit_transform(word_vectors)[:, :3] else: three_dim = TSNE(n_components=3, random_state=0, perplexity=perplexity, learning_rate=learning_rate, n_iter=iteration).fit_transform(word_vectors)[:, :3] color = 'blue' quiver = go.Cone(x=[0, 0, 0], y=[0, 0, 0], z=[0, 0, 0], u=[1.5, 0, 0], v=[0, 1.5, 0], w=[0, 0, 1.5], anchor="tail", colorscale=[[0, color], [1, color]], showscale=False) data = [quiver] count = 0 for i in range(len(user_input)): trace = go.Scatter3d(x=three_dim[count:count + topn, 0], y=three_dim[count:count + topn, 1], z=three_dim[count:count + topn, 2], text=words[count:count + topn] if annotation == 'On' else '', name=user_input[i], textposition="top center", textfont_size=15, mode='markers+text', marker={ 'size': 10, 'opacity': 0.8, 'color': 2 }) data.append(trace) count = count + topn trace_input = go.Scatter3d(x=three_dim[count:, 0], y=three_dim[count:, 1], z=three_dim[count:, 2], text=words[count:], name='input words', textposition="top center", textfont_size=15, mode='markers+text', marker={ 'size': 10, 'opacity': 1, 'color': 'black' }) data.append(trace_input) # Configure the layout. layout = go.Layout(margin={ 'l': 0, 'r': 0, 'b': 0, 't': 0 }, showlegend=True, legend=dict(x=1, y=0.5, font=dict(family="Courier New", size=15, color="black")), font=dict(family=" Courier New ", size=15), autosize=True, width=1000, height=1000) plot_figure = go.Figure(data=data, layout=layout) st.plotly_chart(plot_figure)
def get_graphs(filename, entry, modifiers): info = get_info_for_entry(filename, entry) fig = make_subplots() jet_pt = info["jet_pt"] jet_eta = info["jet_eta"] jet_phi = info["jet_phi"] jet_mass = info["jet_mass"] njet = len(jet_pt) vx, vy, vz = [], [], [] vu, vv, vw = [], [], [] hovertexts = [] for i in range(njet): hovertexts.append(f"<b>Jet</b><br>p<sub>T</sub> = {jet_pt[i]:.1f}<br>η = {jet_eta[i]:.2f}<br>φ = {jet_phi[i]:.2f}<br>mass = {jet_mass[i]:.1f}") vx.append(0) vy.append(0) vz.append(0) x, y, z = ptetaphi_to_xyz(jet_pt[i], jet_eta[i], jet_phi[i], norm=True) vu.append(y) vv.append(z) vw.append(z) fig.add_trace( go.Cone( x=vx, y=vz, z=vy, # note the flip u=vu, v=vw, w=vv, # note the flip sizemode="absolute", anchor="tip", colorscale=[[0, "red"], [1, "red"]], name=f"Jets ({njet})", showlegend=True, showscale=False, opacity=0.3, hoverinfo="text", hovertext=hovertexts, ), ) electron_pt = info["electron_pt"] electron_eta = info["electron_eta"] electron_phi = info["electron_phi"] electron_charge = info["electron_charge"] nelectron = len(electron_pt) vx, vy, vz = [], [], [] vu, vv, vw = [], [], [] hovertexts = [] for i in range(nelectron): hovertexts.append(f"<b>Electron</b><br>p<sub>T</sub> = {electron_pt[i]:.1f}<br>η = {electron_eta[i]:.2f}<br>φ = {electron_phi[i]:.2f}<br>charge = {electron_charge[i]:+}") vx.append(0) vy.append(0) vz.append(0) x, y, z = ptetaphi_to_xyz(electron_pt[i], electron_eta[i], electron_phi[i], norm=True) vu.append(y) vv.append(z) vw.append(z) fig.add_trace( go.Cone( x=vx, y=vz, z=vy, # note the flip u=vu, v=vw, w=vv, # note the flip sizemode="absolute", anchor="tip", colorscale=[[0, "blue"], [1, "blue"]], name=f"Electrons ({nelectron})", showlegend=True, showscale=False, opacity=0.3, hoverinfo="text", hovertext=hovertexts, ), ) muon_pt = info["muon_pt"] muon_eta = info["muon_eta"] muon_phi = info["muon_phi"] muon_charge = info["muon_charge"] nmuon = len(muon_pt) # return to 0 each time vx, vy, vz = [], [], [] hovertexts = [] for i in range(nmuon): hovertexts.append("") vx.append(0) vy.append(0) vz.append(0) hovertexts.append(f"<b>Muon</b><br>p<sub>T</sub> = {muon_pt[i]:.1f}<br>η = {muon_eta[i]:.2f}<br>φ = {muon_phi[i]:.2f}<br>charge = {muon_charge[i]:+}") x, y, z = ptetaphi_to_xyz(muon_pt[i], muon_eta[i], muon_phi[i], norm=True) vx.append(x) vy.append(y) vz.append(z) fig.add_trace( go.Scatter3d( x=vx, y=vz, z=vy, # note the flip marker=dict(size=0.001), line=dict(color="red", width=4), name=f"Muons ({nmuon})", mode="lines+markers", hoverinfo="text", hovertext=hovertexts, ) ) met_pt = info["met_pt"] met_phi = info["met_phi"] x, y, z = ptetaphi_to_xyz(met_pt, 0., met_phi, norm=True) vx = [0, x] vy = [0, y] vz = [0, z] fig.add_trace( go.Scatter3d( x=vx, y=vz, z=vy, # note the flip marker=dict(size=0.001), line=dict(color="black", width=4), name="MET", mode="lines+markers", hoverinfo="name+text", hovertemplate=f"p<sub>T</sub> = {met_pt:.1f} GeV<br>φ = {met_phi:.2f}" ) ) vx, vy, vz = cylinder(1, 4, a=-2, nt=20, nv=2) fig.add_trace( go.Surface( x=vx, y=vz, z=vy, # note the flip colorscale=[[0, "gray"], [1, "gray"]], opacity=0.1, showscale=False, hoverinfo="none", name="Dumb cylinder", showlegend=True, visible="legendonly", ) ) sf = 0.5 fig.update_layout( height=600, width=800, template="plotly", scene=dict( aspectratio=dict(x=sf * 1, y=sf * 2, z=sf * 1), xaxis=dict( tickvals= [-1,+1], title="x", range=[-1, 1], showspikes=False, ), yaxis=dict( tickvals= [-1,+1], title="z", range=[-2, 2], showspikes=False, ), zaxis=dict( tickvals= [-1,+1], title="y", range=[-1, 1], showspikes=False, ), ), margin=dict(r=0, b=0, l=0, t=0), legend=dict(yanchor="top", y=0.99, xanchor="left", x=0.01), ) g_plot = dcc.Graph(figure=fig, id='g_plot') return [g_plot]
def draw(self, **kargs): import plotly from mlreco.visualization.points import scatter_points import plotly.graph_objs as go from plotly.offline import iplot graph_data = [] # Draw voxels with cluster labels energy = self.output['energy'] shower_mask = self.output['shower_mask'] graph_data += scatter_points(energy, markersize=2, color=energy[:, -1], colorscale='Inferno') graph_data[-1].name = 'Energy' colors = plotly.colors.qualitative.Light24 for i, s in enumerate(self.output['showers']): points = energy[shower_mask][s.voxels] color = colors[i % (len(colors))] graph_data += scatter_points(points, markersize=2, color=color) graph_data[-1].name = 'Shower %d (id=%d)' % (i, s.pid) if len(self.output['showers']): # Add EM primary points points = np.array([s.start for s in self.output['showers']]) graph_data += scatter_points(points) graph_data[-1].name = 'Shower Starts' # Add EM primary directions dirs = np.array([s.direction for s in self.output['showers']]) cone_start = points[:, :3] arrows = go.Cone(x=cone_start[:, 0], y=cone_start[:, 1], z=cone_start[:, 2], u=-dirs[:, 0], v=-dirs[:, 1], w=-dirs[:, 2], sizemode='absolute', sizeref=1.0, anchor='tip', showscale=False, opacity=0.4) graph_data.append(arrows) # Add a vertex if matches, join vertex to start points if 'matches' in self.output: for i, match in enumerate(self.output['matches']): v = self.output['vertices'][i] idx1, idx2 = match s1, s2 = self.output['showers'][idx1].start, self.output[ 'showers'][idx2].start points = [v, s1, v, s2] graph_data += scatter_points(np.array(points), color='red') graph_data[ -1].name = 'Pi0 (%.2f MeV)' % self.output['masses'][i] graph_data[-1].mode = 'lines,markers' # Draw #go.Figure(data=graph_data,layout=self.layout(**kargs)) from mlreco.visualization import plotly_layout3d fig = go.Figure(data=graph_data, layout=plotly_layout3d()) camera = dict(up=dict(x=0, y=0, z=0), center=dict(x=0, y=0, z=-0.3), eye=dict(x=0.4, y=0.4, z=0.4)) fig.update_layout(scene_camera=camera, showlegend=False) iplot(fig)
zs.append(z) us.append(tom[x][y][z][0]) vs.append(tom[x][y][z][1]) ws.append(tom[x][y][z][2]) i += 1 print(i) #if i >= 500: # break #if i >= 500: # break #if i >= 500: # break #fig = px.scatter_3d(x=xs, y=ys, z=zs, color=np.array([1 for i in range(len(xs))]), size=[0.5 for item in xs], range_x=[0,144], range_y=[0,144], range_z=[0,144]) fig = go.Figure(data=go.Cone(x=xs, y=ys, z=zs, u=us, v=vs, w=ws)) #fig = px.scatter_3d(x=xs, y=ys, z=zs, color=np.array(["rgb(" + str(abs(us[i])) + "," + str(abs(vs[i])) + "," + str(abs(ws[i])) + ")" for i in range(len(xs))]), size=[0.1 for item in xs], range_x=[0,144], range_y=[0,144], range_z=[0,144]) fig.update_layout( scene_aspectmode='cube', scene=dict(xaxis=dict(range=[0, 144]), yaxis=dict(range=[0, 144]), zaxis=dict(range=[0, 144])), scene_camera=camera, ) fig.show() """ print(len(xs), len(ys), len(zs)) fig = plt.figure() ax = fig.add_subplot(111, projection='3d') ax.set_xlim([0, 144]) ax.set_ylim([0, 144])
def network_topology(voxels, clusters, primaries, edges, mode='sphere'): """ Network 3D topological representation - voxels is a list of voxel coordinates (Nx3-matrix) - clusters is an array of clusters, each defined as an array of voxel ids - primaries is a list of the primary cluster ids - edges is list of pairs of cluster ids arranged in two vectors (2xM-vector) """ # Define the arrays of node positions (barycenter of voxels in the cluster) pos = np.array([voxels[c].cpu().numpy().mean(0) for c in clusters]) # Define the node features (label, color) n = len(clusters) node_labels = [ '%d (%0.1f, %0.1f, %0.1f)' % (i, pos[i, 0], pos[i, 1], pos[i, 2]) for i in range(n) ] node_colors = [ '#ff7f0e' if i in primaries else '#1f77b4' for i in range(n) ] # Assert if there is edges to draw draw_edges = bool(edges.shape[1]) if len(edges) == 2 else False # Define the nodes and their connections graph_data = [] edge_vertices = [] if mode == 'sphere': # Define the node size as a linear function of the amount of voxels in the cluster sizes = np.array([len(c) for c in clusters]) node_sizes = sizes * 50. / sizes.max() # Define the nodes as sphere of radius proportional to the log of the cluster voxel content graph_data.append( go.Scatter3d(x=pos[:, 0], y=pos[:, 1], z=pos[:, 2], name='clusters', mode='markers', marker=dict(symbol='circle', size=node_sizes, color=node_colors, colorscale='Viridis', line=dict(color='rgb(50,50,50)', width=0.5)), text=node_labels, hoverinfo='text')) # Define the edges center to center if draw_edges: edge_vertices = np.concatenate( [[pos[i], pos[j], [None, None, None]] for i, j in zip(edges[0], edges[1])]) elif mode == 'cone': # Evaluate the cone parameters from sklearn.decomposition import PCA import numpy.linalg as LA pca = PCA() axes, spos, epos = np.empty((0, 3)), np.empty((0, 3)), np.empty((0, 3)) curv = lambda vox, pid, norm :\ np.sum([np.abs(np.dot((v-vox[pid])/LA.norm(v-vox[pid]), norm)) for i, v in enumerate(vox) if i != pid]) for c in clusters: # Get the voxels corresponding to the cluster vox = voxels[c].numpy() # Get the mean and the principal axis from the PCA pca.fit(vox) axis = np.array([pca.components_[0][i] for i in range(3)]) # Order the point along the principal axis, get the end points pa_vals = np.dot(vox, axis) pids = np.argmax(pa_vals), np.argmin(pa_vals) # Identify the starting point as the point with the largest curvature curvs = [curv(vox, pid, axis) for pid in pids] start_id, end_id = pids[np.argmax(curvs)], pids[np.argmin(curvs)] spos = np.concatenate((spos, [vox[start_id]])) epos = np.concatenate((epos, [vox[end_id]])) # Get the full length of the principal axis pa_dist = pa_vals[start_id] - pa_vals[end_id] # Append the cone parameters axes = np.concatenate((axes, [2. * pa_dist * axis])) # Compute plotly's internal vector scale to undo it... vector_scale = np.inf for i, p in enumerate(spos): u = axes[i] if i > 0: vector_scale = min( vector_scale, 2 * LA.norm(p2 - p) / (LA.norm(u2) + LA.norm(u))) p2 = p u2 = u # Add a graph with a cone per cluster graph_data.append( go.Cone(x=spos[:, 0], y=spos[:, 1], z=spos[:, 2], u=axes[:, 0], v=axes[:, 1], w=axes[:, 2], name='clusters', opacity=.5, sizeref=.5 / vector_scale, showscale=False, anchor='tip')) # Add a graph with the starting points graph_data.append( go.Scatter3d(x=spos[:, 0], y=spos[:, 1], z=spos[:, 2], name='nodes', mode='markers', marker=dict(symbol='circle', color=node_colors, size=5, colorscale='Viridis'), text=node_labels, hoverinfo='text')) # Join end points of primary cones to starting points of secondary cones for e in edges: edge_vertices = np.concatenate( [[epos[i], spos[j], [None, None, None]] for i, j in zip(edges[0], edges[1])]) elif mode == 'hull': # For each cluster, add the convex hull of all its voxels graph_data += [ go.Mesh3d(alphahull=10.0, name='', x=voxels[c][:, 0], y=voxels[c][:, 1], z=voxels[c][:, 2], color=node_colors[i], opacity=0.3, text=node_labels[i], hoverinfo='text') for i, c in enumerate(clusters) ] # Define the edges closest pixel to closest pixel import scipy as sp edge_vertices = [] for i, j in zip(edges[0], edges[1]): vi, vj = voxels[clusters[i]], voxels[clusters[j]] d12 = sp.spatial.distance.cdist(vi, vj, 'euclidean') i1, i2 = np.unravel_index(np.argmin(d12), d12.shape) edge_vertices.append([ vi[i1].cpu().numpy(), vj[i2].cpu().numpy(), [None, None, None] ]) if draw_edges: edge_vertices = np.concatenate(edge_vertices) elif mode == 'scatter': # Simply draw all the voxels of each cluster, using primary as color cids = np.full(len(voxels), -1) for i, c in enumerate(clusters): cids[c] = i mask = np.where(cids != -1)[0] colors = [node_colors[i] for i in cids[mask]] labels = [node_labels[i] for i in cids[mask]] graph_data = [ go.Scatter3d(x=voxels[mask][:, 0], y=voxels[mask][:, 1], z=voxels[mask][:, 2], mode='markers', marker=dict(symbol='circle', color=colors, size=1), text=labels, hoverinfo='text') ] # Define the edges closest pixel to closest pixel if draw_edges: import scipy as sp edge_vertices = [] for i, j in zip(edges[0], edges[1]): vi, vj = voxels[clusters[i]], voxels[clusters[j]] d12 = sp.spatial.distance.cdist(vi, vj, 'euclidean') i1, i2 = np.unravel_index(np.argmin(d12), d12.shape) edge_vertices.append([ vi[i1].cpu().numpy(), vj[i2].cpu().numpy(), [None, None, None] ]) edge_vertices = np.concatenate(edge_vertices) else: raise ValueError("Network topology mode not supported") # Initialize a graph that contains the edges if draw_edges: graph_data.append( go.Scatter3d(x=edge_vertices[:, 0], y=edge_vertices[:, 1], z=edge_vertices[:, 2], mode='lines', name='edges', line=dict(color='rgba(50, 50, 50, 0.5)', width=5), hoverinfo='none')) # Return return graph_data
y=[ dataset_dict['data'][i, 1], dataset_dict['data'][i, 1] + line_length * t1[1] ], z=[ dataset_dict['data'][i, 2], dataset_dict['data'][i, 2] + line_length * t1[2] ], mode='lines', line=dict(width=line_width, color='red'))) # drawing the arrowhead (is there an easier way?): pd.append( go.Cone(x=[dataset_dict['data'][i, 0] + line_length * t1[0]], y=[dataset_dict['data'][i, 1] + line_length * t1[1]], z=[dataset_dict['data'][i, 2] + line_length * t1[2]], u=[arrow_cone_length * t1[0]], v=[arrow_cone_length * t1[1]], w=[arrow_cone_length * t1[2]], colorscale='Reds')) # plot the tangent space eigenvector #2: pd.append( go.Scatter3d(x=[ dataset_dict['data'][i, 0], dataset_dict['data'][i, 0] + line_length * t2[0] ], y=[ dataset_dict['data'][i, 1], dataset_dict['data'][i, 1] + line_length * t2[1] ], z=[
def cones(self, x=None, y=None, z=None, u=None, v=None, w=None, conesize=40, width=700, height=700, res=50, grid=True, pane_fill=None, prune=None, x_slice=True, x_center=None, x_scale=1, x_lim=None, y_slice=True, y_center=-3.5, y_scale=1, y_lim=None, z_slice=True, z_center=None, z_scale=1, z_lim=None, norm=None, cb_labelpad=10, cb_nticks=10, cb_x=None, cb_y=None, cb_title=None, cb_length=0.75, cb_outlinecolor=None, cb_outlinewidth=1, cb_tickfontsize=10, plot_title='Airstream', title_bold=True, title_size=20, title_pad=5, title_y=0.85, x_label='x', xaxis_bold=False, xaxis_labelpad=5, xlabel_rotation=None, x_tick_number=10, y_label='y', yaxis_bold=False, yaxis_labelpad=5, ylabel_rotation=None, y_tick_number=10, z_label='z', zaxis_bold=False, zaxis_labelpad=5, zlabel_rotation=None, z_tick_number=10, axis_label_size=20, tick_color=None, tick_label_size=12, tick_label_pad=5, xtick_rotation=None, ytick_rotation=None, ztick_rotation=None, floating_text=None, filename=None): # Colorbar parameters self.cb_outlinecolor = cb_outlinecolor if cb_outlinecolor is not None else self.color2 self.cb_outlinewidth = cb_outlinewidth self.cb_length = cb_length self.cb_title = cb_title self.cb_x = cb_x self.cb_y = cb_y self.cb_xpad = cb_labelpad self.cb_nticks = cb_nticks self.cb_tickfontsize = cb_tickfontsize # Mock plot if isinstance(x, type(None)) and isinstance(y, type(None)) and isinstance(z, type(None)) \ and isinstance(u, type(None)) and isinstance(v, type(None)) and isinstance(w, type(None)): df = pd.read_csv( r"C:\Users\xXY4n\AE BSc\AE Year 2\Aerodynamics project\Data Analysis\data\velocity_planes_of_interest\x=-10\x=-10_projected\-10_-8_7.csv", index_col=0) df.columns = list('--xyzuvw') x, y, z, u, v, w = df['x'], df['y'], df['z'], df['u'], df['v'], df['w'] x_scale = (abs(x.max())+abs(x.min()))/max(abs(x.max())+abs(x.min()), abs(y.max())+abs(y.min()), abs(z.max())+abs(z.min())) y_scale = (abs(y.max())+abs(y.min()))/max(abs(x.max())+abs(x.min()), abs(y.max())+abs(y.min()), abs(z.max())+abs(z.min())) z_scale = (abs(z.max())+abs(z.min()))/max(abs(x.max())+abs(x.min()), abs(y.max())+abs(y.min()), abs(z.max())+abs(z.min())) # Individual axis setup axis = dict(showbackground=True, backgroundcolor=pane_fill, showgrid=grid, gridcolor=self.color2, zerolinecolor=self.color2, tickfont={'family': self.font, 'size': tick_label_size, 'color': tick_color}, titlefont={'family': self.font, 'size': axis_label_size}, ) # Layout layout = go.Layout( width=width, height=height, scene=dict(xaxis=dict(axis, range=x_lim, tickangle=xtick_rotation, nticks=x_tick_number, title='<b>'+x_label+'</b>' if xaxis_bold is True else x_label), yaxis=dict(axis, range=y_lim, tickangle=ytick_rotation, nticks=y_tick_number, title='<b>'+y_label+'</b>' if yaxis_bold is True else y_label), zaxis=dict(axis, range=z_lim, tickangle=ztick_rotation, nticks=z_tick_number, title='<b>'+z_label+'</b>' if zaxis_bold is True else z_label), aspectratio=dict(x=x_scale, y=y_scale, z=z_scale) ), template=self.template ) # Plot fig = go.Figure(data=go.Cone(x=x, y=y, z=z, u=u, v=v, w=w, colorscale=self.cmap, sizemode='absolute', sizeref=conesize, colorbar=dict(len=self.cb_length, x=self.cb_x, xpad=self.cb_xpad, y=self.cb_y, outlinecolor=self.cb_outlinecolor, outlinewidth=self.cb_outlinewidth, tick0=0, dtick=0.5, ticklen=5, tickwidth=1, tickfont=dict(size=self.cb_tickfontsize, color=self.color, family=self.font), title=self.cb_title) ), layout=layout) # Makeup fig.update_layout( title={'text': '<b>'+plot_title+'<b>' if title_bold is True else plot_title, 'x': 0.5, 'y': title_y, 'xanchor': 'center', 'yanchor': 'top'}, font=dict( family=self.font, size=title_size, color=self.color, ) ) fig.show() if not isinstance(filename, type(None)): self.save(fig=fig, filename=filename)
from plotly.offline import plot import plotly.graph_objs as go import numpy as np plot_data = np.load('plot.npy') cam_R = plot_data[()]['cam_R'] cam_t = plot_data[()]['cam_t'] verts = plot_data[()]['verts'] faces = plot_data[()]['faces'] voxels_value_flatten = plot_data[()]['voxel_value'] object_point_3D = plot_data[()]['object_point'] trace_object = go.Mesh3d(x=verts[:,0],y=verts[:,1],z=verts[:,2],i=faces[:,0],j=faces[:,1],k=faces[:,2]) trace_camera = go.Cone() #trace_cube = go.Volume(x=,y=object_point_3D[1,:],z=object_point_3D[2,:],value=voxels_value_flatten) # try to using plotly to imshow 3d mesh and camera pose x,y,z=zip(*verts) trace_point = go.Scatter3d(x=x,y=y,z=z,mode='markers', marker=dict( color='rgb(0, 0, 255)', size=2, symbol='circle', line=dict( color='rgb(204, 204, 204)', width=1 ), opacity=0.9 )) plot([trace_point, trace_object]) print('fdsa')
def vector_plot(result, titles, verbose=False, **kwargs): variable = titles['variable'] val0 = list(result.values())[0] if (result[variable].shape == val0.shape) & (val0.shape[1] == 2): if verbose: print('\t 2-d output', result[variable].shape) u = result[variable][:, 0] v = result[variable][:, 1] x = val0[:, 0] y = val0[:, 1] trace = ff.create_quiver( x, y, u, v, # scale=.25, # arrow_scale=.4, name='quiver', line=dict(width=1))['data'][0] # extracts quiver trace layout = go.Layout(title=titles['title'], xaxis=dict(title='x'), yaxis=dict(title='y')) chart_type = '2d-vector' elif (result[variable].shape == val0.shape) & (val0.shape[1] == 3): if verbose: print('\t 3-d output', result[variable].shape, val0.shape) print('\t 3d vector plot') if type(result[variable]) == pd.DataFrame: u = result[variable].values[:, 0].tolist() v = result[variable].values[:, 1].tolist() w = result[variable].values[:, 2].tolist() else: u = result[variable][:, 0].tolist() v = result[variable][:, 1].tolist() w = result[variable][:, 2].tolist() if type(val0) == pd.DataFrame: x = val0.values[:, 0].tolist() y = val0.values[:, 1].tolist() z = val0.values[:, 2].tolist() else: x = val0[:, 0].tolist() y = val0[:, 1].tolist() z = val0[:, 2].tolist() norms = np.linalg.norm(result[variable], axis=1) trace = go.Cone( x=x, y=y, z=z, u=u, v=v, w=w, hoverinfo='x+y+z+u+v+w+norm', colorscale='Reds', cmin=0, cmax=norms.max(), ) layout = go.Layout(title=titles['title'], scene=dict( xaxis=dict(title='x'), yaxis=dict(title='y'), zaxis=dict(title='z'), )) chart_type = '3d-vector' else: raise NotImplementedError('plot type not supported yet') return [trace], chart_type, layout
def generate_scatterplot_3D( word_vectors, user_input=None, words=None, annotation="On", dim_red="PCA", perplexity=0, learning_rate=0, iteration=0, topn=0, ): if dim_red == "PCA": three_dim = calc_3d_pca(word_vectors) else: three_dim = calc_3d_tsne(word_vectors, perplexity, learning_rate, iteration) color = "blue" quiver = go.Cone( x=[0, 0, 0], y=[0, 0, 0], z=[0, 0, 0], u=[1.5, 0, 0], v=[0, 1.5, 0], w=[0, 0, 1.5], anchor="tail", colorscale=[[0, color], [1, color]], showscale=False, ) data = [quiver] count = 0 for i in range(len(user_input)): trace = go.Scatter3d( x=three_dim[count:count + topn, 0], y=three_dim[count:count + topn, 1], z=three_dim[count:count + topn, 2], text=words[count:count + topn] if annotation == "On" else "", name=user_input[i], textposition="top center", textfont_size=30, mode="markers+text", marker={ "size": 10, "opacity": 0.8, "color": 2 }, ) data.append(trace) count = count + topn trace_input = go.Scatter3d( x=three_dim[count:, 0], y=three_dim[count:, 1], z=three_dim[count:, 2], text=words[count:], name="input words", textposition="top center", textfont_size=30, mode="markers+text", marker={ "size": 10, "opacity": 1, "color": "black" }, ) data.append(trace_input) # Configure the layout. layout = go.Layout( margin={ "l": 0, "r": 0, "b": 0, "t": 0 }, showlegend=True, legend=dict(x=1, y=0.5, font=dict(family="Courier New", size=24, color="black")), font=dict(family=" Courier New ", size=15), autosize=False, width=800, height=600, ) return go.Figure(data=data, layout=layout)
def quiverly(self, *args, fig=None, showarrow=True, color="black", scale=5, origin=None, arrow_size='scaled', line_kwargs=None, name='Vector', showlegend=False): """ """ if origin is None: origin = np.zeros(3) assert isinstance(self, Vector) import plotly.graph_objs as go x = np.stack([0, self[0].squeeze()]) + origin[0] y = np.stack([0, self[1].squeeze()]) + origin[1] color_scale = [[0, color], [1, color]] if fig is None: fig = go.Figure() if len(self) == 2: z = np.zeros_like(x) + origin[2] else: z = np.stack([0, self[2].squeeze()]) + origin[2] if arrow_size == 'scaled': u = [(x[1] - x[0]) / scale] v = [(y[1] - y[0]) / scale] w = [(z[1] - z[0]) / scale] elif isinstance(arrow_size, (int, float)): du = (x[1] - x[0]) dv = (y[1] - y[0]) dz = (z[1] - z[0]) mag_du = np.sqrt(du**2 + dv**2 + dz**2) u = [du / mag_du * arrow_size] v = [dv / mag_du * arrow_size] w = [dz / mag_du * arrow_size] else: raise Exception( "size must either be set to scaled or an int or float") obj = go.Scatter3d(x=x, y=y, z=z, marker=dict(size=0), line=dict(color=color), name=name, showlegend=showlegend) cone = go.Cone(x=[x[1]], y=[y[1]], z=[z[1]], u=u, v=v, w=w, colorscale=color_scale, showscale=False, name=None) fig.add_trace(obj) fig.add_trace(cone) return fig, obj
def plot_3D_quiver(pts_world: Union[Dict, torch.Tensor], pts_world_grad: Union[Dict, torch.Tensor], mesh_gt: Optional[Meshes] = None, mesh: List[trimesh.Trimesh] = None, camera: CamerasBase = None, n_debug_points: int = -1, save_html: Optional[str] = None) -> go.Figure: """ Plot 3D quiver plots (cone), for each point, plot the normalized negative gradient. Accept dictionaries of {str: tensor(N,3)} or tensors (N,3). In case dictionaries are proviced, the keys are used for hovertext, otherwise, the indices of points are used. Args: pts_world (tensor): pts_world_grad (tensor): the vector projected to world space, i.e. proj(pts+grad) - pts_world mesh_gt (Meshes): (H,W) image value range [0,1] save_html (str): If given, then save to file """ n_pts_per_cat = None text_to_id = None if isinstance(pts_world, torch.Tensor): n_pts_per_cat = OrderedDict(all=pts_world.shape[0]) if n_debug_points > 0: n_pts_per_cat['all'] = min(n_debug_points, n_pts_per_cat['all']) pts_world = pts_world.cpu()[:n_pts_per_cat['all']] pts_world_grad = pts_world_grad.cpu()[:n_pts_per_cat['all']] text = np.array([str(i) for i in range(pts_world.shape[0])]) elif isinstance(pts_world, dict): n_pts_per_cat = OrderedDict( (k, (pts.shape[0])) for k, pts in pts_world.items()) if n_debug_points > 0: for k in n_pts_per_cat: n_pts_per_cat[k] = min(n_debug_points, n_pts_per_cat[k]) text_to_id = {k: i for i, k in enumerate(pts_world)} pts_world = torch.cat( [pts_world[k][:v] for k, v in n_pts_per_cat.items()], dim=0) pts_world_grad = torch.cat( [pts_world_grad[k][:v] for k, v in n_pts_per_cat.items()], dim=0) pts_world = pts_world.cpu() pts_world_grad = pts_world_grad.cpu() text = np.array( [k for k, pts in n_pts_per_cat.items() for i in range(pts)]) # one 3D plot for the pts_world fig3D = go.Figure() # log scale pts_world_grad and clip grad with very large norms grad_norm = torch.norm(pts_world_grad, dim=-1, keepdim=True) pts_world_grad_normalized = torch.nn.functional.normalize(pts_world_grad) # plot Scatter3D with different colors if len(n_pts_per_cat) > 1 and pts_world.shape[0] > 0: # plot all pts and grad together t0 = time.time() fig3D.add_trace( go.Cone( x=pts_world.cpu().numpy()[:, 0], y=pts_world.cpu().numpy()[:, 1], z=pts_world.cpu().numpy()[:, 2], u=-pts_world_grad.cpu().numpy()[:, 0], v=-pts_world_grad.cpu().numpy()[:, 1], w=-pts_world_grad.cpu().numpy()[:, 2], customdata=grad_norm.cpu().numpy(), name='all', visible=True, anchor='tail', text=text, hovertemplate= '<b>%{text}</b> ||Fp|| = %{customdata} <extra></extra>', sizemode="scaled", # absolute|scaled sizeref=1.0, showscale=False, colorscale='Reds')) t1 = time.time() # print('Cone All {:.3f}'.format(t1-t0)) # plot gradients _start_pts = 0 for k, n_pts in n_pts_per_cat.items(): pts = pts_world[_start_pts:(n_pts + _start_pts)].cpu().numpy() grad = pts_world_grad[_start_pts:(n_pts + _start_pts)].cpu().numpy() norm = grad_norm[_start_pts:(n_pts + _start_pts)].cpu().numpy() _start_pts += n_pts if pts.size == 0: continue t0 = time.time() fig3D.add_trace( go.Cone( x=pts[:, 0], y=pts[:, 1], z=pts[:, 2], u=-grad[:, 0], v=-grad[:, 1], w=-grad[:, 2], customdata=norm, name=k + ' grad', visible=False, anchor='tail', hovertemplate='||Fp|| = %{customdata} <extra></extra>', sizemode="scaled", # absolute|scaled sizeref=1, showscale=False, colorscale='Reds')) t1 = time.time() # print('Cone {} {:.3f}'.format(k, t1-t0)) # plot all sampled points _start_pts = 0 for k, n_pts in n_pts_per_cat.items(): pts = pts_world[_start_pts:(n_pts + _start_pts)].cpu().numpy() _start_pts += n_pts if pts.size == 0: continue t0 = time.time() fig3D.add_trace( go.Scatter3d( x=pts[:, 0], y=pts[:, 1], z=pts[:, 2], name=k, visible=False, mode='markers', marker_size=5, )) t1 = time.time() # print('Scatter3d {} {:.3f}'.format(k, t1-t0)) # make first plot visible fig3D.data[0].visible = True # plot ground truth mesh # TODO(yifan): toggle visibility n_always_visible_plots = 0 if mesh_gt is not None: t0 = time.time() fig3D.add_trace( go.Mesh3d(x=mesh_gt.verts_list()[0][:, 0], y=mesh_gt.verts_list()[0][:, 1], z=mesh_gt.verts_list()[0][:, 2], i=mesh_gt.faces_list()[0][:, 0], j=mesh_gt.faces_list()[0][:, 1], k=mesh_gt.faces_list()[0][:, 2], name='mesh_gt', opacity=0.5, color='gold')) t1 = time.time() # print('Mesh GT {:.3f}'.format(t1-t0)) n_always_visible_plots += 1 # plot predicted mesh # TODO(yifan): toggle visibility if mesh is not None and not mesh.is_empty: t0 = time.time() fig3D.add_trace( go.Mesh3d(x=mesh.vertices[:, 0], y=mesh.vertices[:, 1], z=mesh.vertices[:, 2], i=mesh.faces[:, 0], j=mesh.faces[:, 1], k=mesh.faces[:, 2], name='predicted surface', opacity=0.2, color='lightgray', hoverinfo='name')) t1 = time.time() # print('Mesh Predicted {:.3f}'.format(t1-t0)) n_always_visible_plots += 1 menu_buttons = [] for i, trace in enumerate(fig3D.data): visibles = [False] * len(fig3D.data) visibles[i] = True for p in range(n_always_visible_plots): visibles[len(fig3D.data) - p - 1] = True menu_buttons.append({ 'label': trace.name, 'args': [{ 'visible': visibles }, { 'title': trace.name }], 'method': 'update' }) cam_up = camera.get_full_projection_transform().inverse().get_matrix()[ 0, 1, :3].tolist() cam_up = dict(x=cam_up[0], y=cam_up[1], z=cam_up[2]) cam_eye = camera.get_camera_center()[0, :].tolist() cam_eye = dict(x=cam_eye[0], y=cam_eye[1], z=cam_eye[2]) fig3D.update_layout(updatemenus=[dict( active=0, buttons=menu_buttons, )], scene=dict(xaxis=dict(range=[-1.2, 1.2], autorange=False), yaxis=dict(range=[-1.2, 1.2], autorange=False), zaxis=dict(range=[-1.2, 1.2], autorange=False), aspectratio=dict(x=1, y=1, z=1), camera=dict(up=cam_up, center=dict(x=0, y=0, z=0), eye=cam_eye))) if save_html is not None: os.makedirs(os.path.dirname(save_html), exist_ok=True) # figures_to_html([fig3D], save_html) fig3D.write_html(save_html) return fig3D
def genereate_json_for_3d_graph(): ''' this function create the json file that is used by plotly to create the figure for the 3d visualization OUTPUT: string in the form of a json file ''' import pandas as pd import networkx as nx import json import plotly.graph_objs as go import plotly import random random.seed(10) # import data df_edges = pd.read_excel("raan_case_study.xlsx", sheet_name=0) df_nodes = pd.read_excel("raan_case_study.xlsx", sheet_name=1) # create graph (create 2 lists dictionary with the edges and with the nodes and their attributes) edges_list = [(el[0], el[1], el[2]) for _, el in df_edges.T.items()] nodes_list = [(el[0], { 'color': el[1], 'label': el[2] }) for _, el in df_nodes.T.items()] # create graph G = nx.DiGraph() # add nodes and edges to graph G.add_nodes_from(nodes_list) G.add_weighted_edges_from(edges_list) # get positions of nodes in 3D plane pos = nx.layout.spring_layout(G, dim=3) Xn = [pos[el][0] for el in pos] # x-coordinates of nodes Yn = [pos[el][1] for el in pos] # y-coordinates Zn = [pos[el][2] for el in pos] # z-coordinates # creates lists with attributes of nodes names_list = [el[1]['label'] for el in G.nodes(data=True)] # labels attr_list = [(el[0], el[1]['label']) for el in G.nodes(data=True)] # id and label id_list = [el[0] for el in G.nodes(data=True)] # id color_list = [el[1]['color'] for el in G.nodes(data=True)] # colors # 3D plot of the graph # interactive 3D plot # create list of position of cones and direction of edges # position of the cones Xs = [0.55 * pos[el[1]][0] + 0.45 * pos[el[0]][0] for el in G.edges()] Ys = [0.55 * pos[el[1]][1] + 0.45 * pos[el[0]][1] for el in G.edges()] Zs = [0.55 * pos[el[1]][2] + 0.45 * pos[el[0]][2] for el in G.edges()] # direction of the cones Us = [pos[el[1]][0] - pos[el[0]][0] for el in G.edges()] Vs = [pos[el[1]][1] - pos[el[0]][1] for el in G.edges()] Ws = [pos[el[1]][2] - pos[el[0]][2] for el in G.edges()] trace1 = go.Scatter3d(x=Xn, y=Yn, z=Zn, mode='text+markers', name='nodes', text=id_list, marker=dict(symbol='circle', size=10, color=color_list, line=dict(color='rgb(50,50,50)', width=0.5)), textposition="bottom center", meta=attr_list, hoverinfo='text', hovertext=names_list) # set axis for plot axis = dict(showbackground=False, showline=False, zeroline=False, showgrid=False, showticklabels=True, title='') # set layout for plot layout = go.Layout( title="", width=1000, height=1000, showlegend=False, scene=dict(xaxis=dict(axis), yaxis=dict(axis), zaxis=dict(axis)), margin=dict(t=100), hovermode='closest', annotations=[ dict(showarrow=False, text="", xref='paper', yref='paper', x=0, y=0.1, xanchor='left', yanchor='bottom', font=dict(size=14)) ], ) # create figure data = [trace1] fig = go.Figure(data=data, layout=layout) # plotly does not allow to draw directe arrow # to show the direction of the edge in the direction of the edge is plotted in the middle of the edge # create trace for cones (used to indicate direction of edge) # hovering over the edge source and target nodes as well as the trace = go.Cone(x=Xs, y=Ys, z=Zs, u=Us, v=Vs, w=Ws, opacity=0.4, showscale=False, colorscale=[[0, 'rgb(125,125,125)'], [1, 'rgb(125,125,125)']], hoverinfo='text', text=[ 'edge from ' + str(G.nodes(data=True)[e[0]]['label']) + ' (' + str(e[0]) + ') ' + ' to ' + str(G.nodes(data=True)[e[1]]['label']) + ' (' + str(e[1]) + ') ' + ': weight: ' + str(e[2]['weight']) for e in G.edges(data=True) ]) fig.add_trace(trace) # get list of weights weights_list = [el[2]['weight'] for el in G.edges(data=True)] # use a frozenset to get the distinct elements (use frozenset because it is iterable) unique_weights = frozenset(weights_list) # loop over different weights and insert edges with corresponding width proportional to the weigth for el in unique_weights: filtered_edges = [ e[0:2] for e in G.edges(data=True) if e[2]['weight'] == el ] # filter out edges with a certain weight Xe = [] Ye = [] Ze = [] # create lists of position of the nodes of filtered edges (add none after every 2 coordinates) for e in filtered_edges: Xe += [pos[e[0]][0], pos[e[1]][0], None] Ye += [pos[e[0]][1], pos[e[1]][1], None] Ze += [pos[e[0]][2], pos[e[1]][2], None] # create trace with filtered edges (line wwidth = 1.5 * edge weight) trace2 = go.Scatter3d(x=Xe, y=Ye, z=Ze, mode='lines', name=str(el), line=dict(color='rgb(125,125,125)', width=el * 1.5), hoverinfo='text', textposition='middle right') # add trace to figure fig.add_trace(trace2) # create json from figure full_json = plotly.io.to_json(fig) # transform json to dict to perform operations on it full_dict = json.loads(full_json) # extact values relative to data and layout keys data = json.dumps(full_dict['data']) layout = json.dumps(full_dict['layout']) # concatenate the 2 graphJSON = data + ',' + layout return graphJSON