def plot_vector_field_cones(self, mesh, vector_field): """ Plots a vector field as cones. Parameters ---------- mesh : `compas.datastructures.Mesh` A COMPAS mesh with 3D vertices. vector_field : `directional_clustering.fields.VectorField` The vector field to plot. Notes ----- Automatic color scale is set to vary with magnitude of the vector. """ num_faces = mesh.number_of_faces() field = vectors_dict_to_array(vector_field, num_faces) c_x, c_y, c_z = face_centroids(mesh) self.add_trace( go.Cone(x=c_x, y=c_y, z=c_z, u=field[:, 0], v=field[:, 1], w=field[:, 2]))
def _draw_cones(points, field, NA=10, cone_opacity=1.0): """Generates cones object for drawing vector field in 3D in plotly. Arrows are white and normalised. Args: points (Point_Array3): coordinates field (Field3): Magnetic field vector NA (int, optional): Number of cones per axis. Defaults to 10. cone_opacity (float, optional): opacity of cones. Defaults to 1.0. Returns: dict: cone data structure for plotting """ x = points.x.reshape(field.x.shape) y = points.y.reshape(field.y.shape) z = points.z.reshape(field.z.shape) maxB = field.n[::NA, ::NA].ravel() cscale = [[0, "rgb(255,255,255)"], [1, "rgb(255,255,255)"]] data_object = _go.Cone( x=x[::NA, ::NA].ravel(), y=y[::NA, ::NA].ravel(), z=z[::NA, ::NA].ravel(), u=field.x[::NA, ::NA].ravel() / maxB, v=field.y[::NA, ::NA].ravel() / maxB, w=field.z[::NA, ::NA].ravel() / maxB, sizemode="scaled", colorscale=cscale, showscale=False, opacity=cone_opacity, ) return data_object
def _cone_plot(function, size=10, showscale=True, normalize=False, **kwargs): mesh = function.function_space().mesh() points = mesh.coordinates() vectors = _get_vertex_values(function) if len(points[0, :]) == 2: points = np.c_[points, np.zeros(len(points[:, 0]))] if vectors.shape[1] == 2: vectors = np.c_[vectors, np.zeros(len(vectors[:, 0]))] if normalize: vectors = np.divide(vectors.T, np.linalg.norm(vectors, axis=1)).T cones = go.Cone( x=points[:, 0], y=points[:, 1], z=points[:, 2], u=vectors[:, 0], v=vectors[:, 1], w=vectors[:, 2], sizemode="absolute", sizeref=size, showscale=showscale, ) return cones
def arrow(start, end, fig=None, **kwargs): start_offset = kwargs.get("start_offset") or 0.98 tip_ratio = kwargs.get("tip_ratio") or 0.1 x_0, y_0, z_0 = start + start_offset * (end - start) u_0, v_0, w_0 = tip_ratio * (end - start) cone = go.Cone( x=[x_0], y=[y_0], z=[z_0], u=[u_0], v=[v_0], w=[w_0], showlegend=False, showscale=False, sizemode="absolute", sizeref=10, **kwargs.get("cone", {}), ) coords = np.vstack((start, end)) line = go.Scatter3d( x=coords[:, 0], y=coords[:, 1], z=coords[:, 2], mode="lines+text", line=kwargs.get("line"), text=["", "h"], textfont=dict(size=30, family="sans-serif", color="black"), textposition="top center", ) if fig is not None: fig.add_trace(line) fig.add_trace(cone) else: return line, cone
def makeDipole(moment=(0.0, 0.0, 1), pos=(0.0, 0.0, 0.0), angle=0.0, axis=(0.0, 0.0, 1.0), color=None, sizeref=2, showlegend=True, **kwargs): x, y, z = np.array([[p] for p in pos]) mom_mag = np.linalg.norm(moment) mom = np.array(moment) / mom_mag if color is None: color = 'rgb(33,33,33)' if angle != 0: mom = angleAxisRotation(mom, angle, axis, anchor=pos) u, v, w = [[m] for m in moment] dipole = go.Cone(x=x, y=y, z=z, u=u, v=v, w=w, colorscale=[[0, color], [1, color]], sizeref=sizeref, sizemode='absolute', showscale=False, showlegend=showlegend, name=f'''dipole ({mom_mag:.2f}T/m³)''') dipole.update(**kwargs) return dipole
def rodConstraintFigure(self, constraintDisplaySize, opa, name="", select="X"): figs = [] U = np.eye(3) DX = ["X", "Y", "Z"] for i in range(self.con["NR"].shape[0]): n = self.con["NR"][i] // 3 a = self.con["NR"][i] % 3 if self.dim == 2 and a == 2: continue text = "<br>节点{:}<br>D{:} = {:} ".format(n + 1, DX[a], self.con["DX"][i]) figs.append( go.Cone(x=[self.geo[select][0, n]] * 2, y=[self.geo[select][1, n]] * 2, z=[self.geo[select][2, n]] * 2, u=[U[0, a], -U[0, a]], v=[U[1, a], -U[1, a]], w=[U[2, a], -U[2, a]], colorscale='Greens', sizemode="absolute", sizeref=(0.4 * constraintDisplaySize), anchor="tip", showscale=False, name=name + 'constraint_' + str(i + 1), showlegend=True, hovertemplate='constraint_' + str(i + 1) + text, opacity=opa)) return figs
def create_cone(pos, dir1, dir2, name): dir1/=np.linalg.norm(dir1) dir2/=np.linalg.norm(dir2) return go.Cone(x=[pos[0],pos[0]], y=[pos[1],pos[1]], z=[pos[2],pos[2]], u=[dir1[0], dir2[0]], v=[dir1[1], dir2[1]], w=[dir1[2], dir2[2]], sizemode="absolute", sizeref=2, anchor="tip", name=name)
def makeLine(curr=0.0, vertices=[(-1.0, 0.0, 0.0), (1.0, 0.0, 0.0)], pos=(0.0, 0.0, 0.0), N=12, angle=0.0, axis=(0.0, 0.0, 1.0), sizeref=None, color=None, showlegend=True, **kwargs): vert = np.array(vertices) Nv = len(vertices) points = [] moments = [] for i in range(Nv - 1): pts = np.linspace(vert[i], vert[i + 1], N) moms = np.tile((vert[i + 1] - vert[i]) * np.sign(curr), (N, 1)) points += [*pts] moments += [*moms] x, y, z = points = (np.array(points) + np.array(pos)).T u, v, w = moments = np.array(moments).T if color is None: color = 'rgb(33,33,33)' if sizeref is None: sizeref = np.sqrt(np.power(np.diff(vert, axis=0), 2).sum(axis=1)).sum() if angle != 0: x, y, z = np.array([ angleAxisRotation(p, angle, axis, anchor=pos) for p in points.T ]).T u, v, w = np.array([ angleAxisRotation(p, angle, axis, anchor=(0, 0, 0)) for p in moments.T ]).T lineCurrent = go.Cone(x=x, y=y, z=z, u=u, v=v, w=w, sizeref=sizeref, sizemode='absolute', showscale=False, showlegend=showlegend, colorscale=[[0, color], [1, color]], name=f'line current ({curr:.2f}A)') lineCurrent.update(**kwargs) return lineCurrent
def visualize_normal_mode(geometry, eigenvector, scale=10): vec = eigenvector.reshape(-1, 3) trace2 = go.Cone( x=geometry[:, 0], y=geometry[:, 1], z=geometry[:, 2], u=vec[:, 0] * scale, v=vec[:, 1] * scale, w=vec[:, 2] * scale, sizemode="absolute", # "absolute" sizeref=2, anchor="tail" ) return [trace2]
def add_projection_plane_in_3d(embedder, reducer, fig3d=None): max_em_0 = max(abs(embedder.em["col0"])) max_em_1 = max(abs(embedder.em["col1"])) max_em_2 = max(abs(embedder.em["col2"])) # Plot Projection Plane X = np.outer( np.linspace(-max_em_0, max_em_0, 2), np.ones(2), ) Y = np.outer( np.linspace(-max_em_1, max_em_1, 2), np.ones(2), ).T Z = plane_z(reducer.normal_vectors, reducer.initial_points_of_normal_vectors, X, Y) fig = go.Figure(data=[go.Surface(x=X, y=Y, z=Z, opacity=0.5)]) # Plot cone representiing Basis of Projection Plane fig.add_trace( go.Cone( x=[0], y=[0], z=[0], u=[reducer.normal_vectors[0] * max_em_0 / 10], v=[reducer.normal_vectors[1] * max_em_1 / 10], w=[reducer.normal_vectors[2] * max_em_2 / 10], ) ) normal_vectors_line = ( np.array([max_em_0, max_em_1, max_em_2]) * reducer.normal_vectors ) print(normal_vectors_line) fig.add_trace( go.Scatter3d( x=[-normal_vectors_line[0], normal_vectors_line[0]], y=[-normal_vectors_line[1], normal_vectors_line[1]], z=[-normal_vectors_line[2], normal_vectors_line[2]], mode="lines", line=dict(color="darkblue", width=2), ) ) if fig3d is None: fig3d = fig else: for goel in fig.data: fig3d.add_trace(goel) return fig3d
def load_vector_plot(data, time_step, z_slice): """ Loads the vector visualization in plotly """ # Make the grid x = [] y = [] z = [] u = [] v = [] w = [] selector = 1 for i in range(32): for j in range(32): if (i % selector == 0 and j % selector == 0): x.append(i) y.append(j) z.append(0) u.append(data[z_slice,i,j, time_step, 3]) v.append(-data[z_slice,i,j, time_step, 2]) w.append(-data[z_slice,i,j, time_step, 1]) fig = go.Figure(data = go.Cone( x=x, y=y, z=z, u=u, v=v, w=w, colorscale='magenta', sizemode='absolute', sizeref=25, showscale=True, colorbar=dict(thickness=20, ticklen=4), )) fig.update_layout(scene=dict(aspectratio=dict(x=1, y=1, z=0.8), camera_eye=dict(x=1.2, y=1.2, z=0.6))) st.write("Below we show the 3D Vector visualization of the above 3 channels. Color according to norm of the vectors." ) st.plotly_chart(fig, width = 1, height= 800)
def add_dipole(self, wfn, style="ball_and_stick", geometry=True): if geometry is True: molecule = qcel.models.Molecule.from_data( wfn.basisset().molecule().save_string_xyz()) self.add_molecule("name" + "_geometry", molecule, style) r = 0.08 vec1 = np.array([0.1, 0, 0]) vec2 = np.array([ wfn.variables()["CURRENT DIPOLE X"], wfn.variables()["CURRENT DIPOLE Y"], wfn.variables()["CURRENT DIPOLE Z"] ]) length = np.linalg.norm(vec2 - vec1) R = rotation_matrix(np.array([0, 0, 1]), vec2 - vec1) cyl = get_single_cylinder(radius=r) cyl[:, 2] *= length cyl = R.dot(cyl.T).T cyl += vec1 cylinder = get_bond_mesh(cyl, 0, ["H"], "matte") cylinder.color = "rgba(204, 0.0, 0.0, 1.0)" # line = go.Scatter3d(x=[0, wfn.variables()["CURRENT DIPOLE X"]], # y=[0, wfn.variables()["CURRENT DIPOLE Y"]], # z=[0, wfn.variables()["CURRENT DIPOLE Z"]]) # cone_norm = np.linalg.norm([wfn.variables()["CURRENT DIPOLE X"], # wfn.variables()["CURRENT DIPOLE Y"], # wfn.variables()["CURRENT DIPOLE Z"]]) cone = go.Cone(x=[wfn.variables()["CURRENT DIPOLE X"]], y=[wfn.variables()["CURRENT DIPOLE Y"]], z=[wfn.variables()["CURRENT DIPOLE Z"]], u=[wfn.variables()["CURRENT DIPOLE X"]], v=[wfn.variables()["CURRENT DIPOLE Y"]], w=[wfn.variables()["CURRENT DIPOLE Z"]], colorscale="reds", showscale=False) self.fig.add_trace(cylinder) self.fig.add_trace(cone)
def makeCircular(curr=0.0, dim=1.0, pos=(0.0, 0.0, 0.0), angle=0.0, axis=(0.0, 0.0, 1.0), color=None, N=40, sizeref=1, showlegend=True, **kwargs): t = np.linspace(0, 2 * np.pi, N) x = dim / 2 * np.cos(t) + pos[0] y = dim / 2 * np.sin(t) + pos[1] z = np.ones(N) * pos[2] points = np.array([x, y, z]) u = -np.ones(N) * np.sin(t) * np.sign(curr) v = np.ones(N) * np.cos(t) * np.sign(curr) w = np.ones(N) * 0 if color is None: color = 'rgb(33,33,33)' if angle != 0: x, y, z = np.array([ angleAxisRotation(p, angle, axis, anchor=pos) for p in points.T ]).T moments = np.array([u, v, w]) u, v, w = np.array([ angleAxisRotation(p, angle, axis, anchor=(0, 0, 0)) for p in moments.T ]).T circularCurrent = go.Cone(x=x, y=y, z=z, u=u, v=v, w=w, sizeref=sizeref, sizemode='absolute', showscale=False, showlegend=showlegend, colorscale=[[0, color], [1, color]], name=f'circular current ({curr:.2f}A)') circularCurrent.update(**kwargs) return circularCurrent
def rodNodeForceFigure(self, forceDisplaySize, opa, name="", select="X", constraint=False): figs = [] if constraint: Ftype = "constraint" color = "magenta" else: Ftype = "node" color = "blues" F = self.force[Ftype].reshape(-1, 3).T Fn = 0 # print(F) for i in range(F.shape[1]): if np.abs(F[:, i]).sum() != 0: text="<br>u:{:4e}<br>v:{:4e}<br>w:{:4e}<br>norm:{:4e}"\ .format(F[0,i],F[1,i],F[2,i],np.sum(F[:,i]**2)**0.5) figs.append( go.Cone( x=[self.geo[select][0, i]], y=[self.geo[select][1, i]], z=[self.geo[select][2, i]], u=[F[0, i]], v=[F[1, i]], w=[F[2, i]], colorscale=color, sizemode="absolute", sizeref=( 0.8 * forceDisplaySize * (np.abs(F[:, i]).sum() / self.force["max"])**0.5), anchor="tip", showscale=False, name=name + Ftype + "_force_" + str(Fn + 1), hovertemplate=name + Ftype + "_force_" + str(Fn + 1) + text, showlegend=True, opacity=opa)) Fn += 1 return figs
def plot_3d_quiver(omega1, omega2, omega3): # skew_matrix = skew3d(omega1, omega2, omega3) skew_matrix = np.array([[0, -omega3, omega2], [omega3, 0, -omega1], [-omega2, omega1, 0]]) x,y,z = np.meshgrid(np.arange(-2, 2, 1), np.arange(-2, 2, 1), np.arange(-2, 2, 1)) # z = x + y + z # u, v, w = np.gradient(z, .2, .2, .2) u = skew_matrix[0][0] * x + skew_matrix[0][1] * y + skew_matrix[0][2] * z v = skew_matrix[1][0] * x + skew_matrix[1][1] * y + skew_matrix[1][2] * z w = skew_matrix[2][0] * x + skew_matrix[2][1] * y + skew_matrix[2][2] * z x = x.reshape(-1) y = y.reshape(-1) z = z.reshape(-1) u = u.reshape(-1) v = v.reshape(-1) w = w.reshape(-1) # Create quiver figure fig = go.Figure(data = go.Cone( x=x, y=y, z=z, u=u, v=v, w=w, colorscale='Blues', sizemode="absolute", sizeref=5)) return fig
def fleche(vecI, vecDir, rgb=(0, 0, 0), s=1 / 10, l=1, name='trace'): """ vecI : np.array([x,y,z]) coordonées du point de départ de la flèche vecDir : np.array([x,y,z]) vecteur unitaire donnant la direction du vecteur scale : nombre entre 0 et 1 grossit ou diminue la dimension du cone l : nombre > 0 longueur de la tige de la flèche rgb : tuple (r,g,b) code rgb de la couleur de la flêche """ xi, yi, zi = vecI xf, yf, zf = vecI + vecDir * l u, v, w = vecDir color = 'rgb({},{},{})'.format(rgb[0], rgb[1], rgb[2]) cone = go.Cone(x=[xf], y=[yf], z=[zf], u=[u], v=[v], w=[w], showscale=False, cauto=True, sizemode='absolute', sizeref=s, colorscale=[[0, color], [1, color]], anchor='cm', name=name) tige = go.Scatter3d(x=[xi, xf], y=[yi, yf], z=[zi, zf], name=name, mode='lines', line=dict(width=5, color=color)) return [tige, cone]
def arrow(go, p0, p1, c): traces = {} traces["arrow_line1"] = go.Scatter3d(x=[p0[0], p1[0]], y=[p0[1], p1[1]], z=[p0[2], p1[2]], showlegend=False, mode='lines', line=dict(color=c, dash="longdash", width=5)) veo = sub(p1, p0) veo = normalize(veo) traces["Cone"] = go.Cone(x=[p1[0]], y=[p1[1]], z=[p1[2]], u=[veo[0]], v=[veo[1]], w=[veo[2]], sizemode='scaled', sizeref=0.25, showscale=False, anchor="tip", colorscale=[[0, c], [1, c]]) return traces
# gradient dx = (val[:-2, 1:-1, 1:-1] - val[2:, 1:-1, 1:-1]) * 0.5 dy = (val[1:-1, :-2, 1:-1] - val[1:-1, 2:, 1:-1]) * 0.5 dz = (val[1:-1, 1:-1, :-2] - val[1:-1, 1:-1, 2:]) * 0.5 # Initialize figure with 4 3D subplots fig = make_subplots(rows=1, cols=1) fig.add_trace( go.Cone( x=X[1:-1, 1:-1, 1:-1].flatten(), y=Y[1:-1, 1:-1, 1:-1].flatten(), z=Z[1:-1, 1:-1, 1:-1].flatten(), u=dx.flatten(), v=dy.flatten(), w=dz.flatten(), sizemode="absolute", colorscale='Blues', opacity=1, sizeref=0.5, colorbar=dict(len=1, x=1), )) # set to dark mode fig.layout.template = 'plotly_dark' # write plot to html html_path = "VIS/PY_VectorField/VectorField.html" fig.write_html(html_path) # show the figure
def make_figures(entry, plotby="larmatch", minprob=0.0): print("making figures for entry={} plot-by={}".format(entry, plotby)) global io io.go_to(entry) ev_lfhits = io.get_data(larlite.data.kLArFlow3DHit, "larmatch") npoints = ev_lfhits.size() print("num larflow hits: ", npoints) hitindex = 0 if plotby == "ssn-bg": hitindex = 10 elif plotby == "ssn-track": hitindex = 11 elif plotby == "ssn-shower": hitindex = 12 elif plotby == "keypoint-nu": hitindex = 13 elif plotby == "keypoint-track": hitindex = 14 elif plotby == "keypoint-shower": hitindex = 15 detdata = lardly.DetectorOutline() traces_v = [] if args.draw_flash: ev_flash = io.get_data(larlite.data.kOpFlash, "simpleFlashBeam") nflashes = 0 for iflash in range(ev_flash.size()): flash = ev_flash.at(iflash) if flash.Time() > 2.94 and flash.Time() < 4.86: flash_trace_v = lardly.data.visualize_larlite_opflash_3d(flash) traces_v += flash_trace_v nflashes += 1 break if nflashes == 0: traces_v += lardly.data.visualize_empty_opflash() if plotby == "larmatch": lfhits_v = [ lardly.data.visualize_larlite_larflowhits(ev_lfhits, "larmatch", score_threshold=minprob) ] traces_v += lfhits_v + detdata.getlines() elif plotby in [ "ssn-bg", "ssn-track", "ssn-shower", "ssn-class", "keypoint-nu", "keypoint-track", "keypoint-shower" ]: xyz = np.zeros((npoints, 4)) ptsused = 0 for ipt in xrange(npoints): hit = ev_lfhits.at(ipt) if hit.track_score < minprob: continue xyz[ptsused, 0] = hit[0] xyz[ptsused, 1] = hit[1] xyz[ptsused, 2] = hit[2] if plotby == "ssn-class": idx = np.argmax(np.array((hit[10], hit[11], hit[12]))) xyz[ptsused, 3] = float(idx) / 2.0 else: xyz[ptsused, 3] = hit[hitindex] #print(xyz[ptsused,3]) ptsused += 1 print("make hit data[", plotby, "] npts=", npoints, " abovethreshold(plotted)=", ptsused) larflowhits = { "type": "scatter3d", "x": xyz[:ptsused, 0], "y": xyz[:ptsused, 1], "z": xyz[:ptsused, 2], "mode": "markers", "name": plotby, "marker": { "color": xyz[:ptsused, 3], "size": 1, "opacity": 0.8, "colorscale": 'Viridis' }, } #print(xyz[:ptsused,3]) traces_v += [larflowhits] + detdata.getlines() elif plotby in ["flow-field"]: # must sample, if trying to draw triangles ptsused = 0 index = np.arange(npoints) np.random.shuffle(index) xyz = np.zeros((npoints, 7)) for ipt in index: if ptsused >= 10000: break hit = ev_lfhits.at(ipt) if hit.track_score < minprob: continue paflen = np.sqrt(hit[16] * hit[16] + hit[17] * hit[17] + hit[18] * hit[18]) if paflen == 0: paflen = 1.0 xyz[ptsused, 0] = hit[0] xyz[ptsused, 1] = hit[1] xyz[ptsused, 2] = hit[2] xyz[ptsused, 3] = hit.track_score xyz[ptsused, 4] = hit[16] / paflen xyz[ptsused, 5] = hit[17] / paflen xyz[ptsused, 6] = hit[18] / paflen ptsused += 1 print("make hit data[", plotby, "] npts=", npoints, " abovethreshold(plotted)=", ptsused) fig = go.Cone(x=xyz[:ptsused, 0], y=xyz[:ptsused, 1], z=xyz[:ptsused, 2], u=xyz[:ptsused, 4], v=xyz[:ptsused, 5], w=xyz[:ptsused, 6], colorscale='Blues', sizeref=10, sizemode="absolute") traces_v += [fig] + detdata.getlines() if args.has_mc: mctrack_v = lardly.data.visualize_larlite_event_mctrack(io.get_data( larlite.data.kMCTrack, "mcreco"), origin=1) traces_v += mctrack_v mcshower_v = lardly.data.visualize_larlite_event_mcshower( io.get_data(larlite.data.kMCShower, "mcreco"), return_dirplot=True) traces_v += mcshower_v[1:] return traces_v
def bloch_sphere(vectors=None, vectors_color=None, vectors_alpha=None, vectors_annotation=False, points=None, points_color=None, points_alpha=None, figsize=(350, 350), label_fontsize=16, annotation_fontsize=10, as_widget=False): """Generates a Bloch sphere from a given collection of vector and/or points data expressed in cartesian coordinates, [x, y, z]. Parameters: vectors (list, ndarray): Collection of one or more vectors to display. vectors_color (str or list): List of colors to use when plotting vectors. vectors_alpha (float or list): List of alphas to use when plotting vectors. vectors_annotation (bool or list): Boolean values to determine if a annotation should be displayed. points (list, ndarray): Collection of one or more points to display. points_color (str or list): List of colors to use when plotting points. points_alpha (float or list): List of alphas to use when plotting points. figsize (tuple): Figure size in pixels. label_fontsize (int): Font size for axes labels. annotation_fontsize (int): Font size for annotations. as_widget (bool): Return plot as a widget. Returns: PlotlyFigure or PlotlyWidget: A Plotly figure or widget instance Raises: ValueError: Input lengths do not match. KaleidoscopeError: Invalid vector input. Example: .. jupyter-execute:: import numpy as np from matplotlib.colors import LinearSegmentedColormap, rgb2hex from kaleidoscope.interactive import bloch_sphere cm = LinearSegmentedColormap.from_list('graypurple', ["#999999", "#AA00FF"]) pointsx = [[0, -np.sin(th), np.cos(th)] for th in np.linspace(0, np.pi/2, 20)] pointsz = [[np.sin(th), -np.cos(th), 0] for th in np.linspace(0, 3*np.pi/4, 30)] points = pointsx + pointsz points_alpha = [np.linspace(0.8, 1, len(points))] points_color = [[rgb2hex(cm(kk)) for kk in np.linspace(-1,1,len(points))]] vectors_color = ["#777777", "#AA00FF"] bloch_sphere(points=points, vectors=[[0, 0, 1], [1/np.sqrt(2), 1/np.sqrt(2), 0]], vectors_color=vectors_color, points_alpha=points_alpha, points_color=points_color) """ # Output figure instance fig = go.Figure() # List for vector annotations, if any fig_annotations = [] idx = 0 if points is not None: nest_depth = nest_level(points) # Take care of single point passed if nest_depth == 1: points = [[points]] # A single list of points passes elif nest_depth == 2: points = [points] # nest_depth = 3 means multiple lists passed if points_color is None: # passed a single point if nest_depth == 1: points_color = [DARK2[0]] elif nest_depth == 2: points_color = [[ DARK2[kk % 8] for kk in range(len(points[0])) ]] elif nest_depth == 3: points_color = [] for kk, pnts in enumerate(points): points_color.append(DARK2[kk % 8] * len(pnts)) if nest_depth == 2 and nest_level(points_color) == 1: points_color = [points_color] if isinstance(points_color, str): points_color = [points_color] if points_alpha is None: points_alpha = [[1.0] * len(p) for p in points] if nest_depth == 2 and nest_level(points_alpha) == 1: points_alpha = [points_alpha] if isinstance(points_alpha, (int, float)): points_alpha = [[points_alpha]] for idx, point_collection in enumerate(points): x_pnts = [] y_pnts = [] z_pnts = [] if isinstance(points_color[idx], str): _colors = [points_color[idx]] * len(point_collection) else: _colors = points_color[idx] if len(points_alpha[idx]) != len(point_collection): err_str = 'number of alpha values ({}) does not equal number of points ({})' raise ValueError( err_str.format(len(points_alpha[idx]), len(x_pnts))) mcolors = [] for kk, point in enumerate(point_collection): x_pnts.append(point[0]) y_pnts.append(point[1]) z_pnts.append(point[2]) mcolors.append("rgba({},{},{},{})".format( *hex_to_rgb(_colors[kk]), points_alpha[idx][kk])) fig.add_trace( go.Scatter3d( x=x_pnts, y=y_pnts, z=z_pnts, mode='markers', marker=dict(size=7, color=mcolors), )) idx += 1 if vectors is not None: if vectors.__class__.__name__ in ['Statevector'] \ and 'qiskit' in vectors.__class__.__module__: vectors = bloch_components(vectors.data) elif not isinstance(vectors[0], (list, np.ndarray)): if vectors[0].__class__.__name__ not in ['Statevector']: vectors = [[vectors[0], vectors[1], vectors[2]]] new_vecs = [] for vec in vectors: if vec.__class__.__name__ in [ 'Statevector' ] and 'qiskit' in vec.__class__.__module__: # pylint: disable=no-member new_vecs.append(bloch_components(vec.data)[0]) else: nst_lvl = nest_level(vec) if nst_lvl == 1: new_vecs.append(vec) elif nst_lvl == 2: new_vecs.append(vec[0]) else: raise KaleidoscopeError("Invalid vector input.") if vectors_color is None: vectors_color = [ DARK2[kk + idx % 8] for kk in range(len(new_vecs)) ] if isinstance(vectors_color, str): vectors_color = [vectors_color] if vectors_alpha is None: vectors_alpha = [1.0] * len(new_vecs) if isinstance(vectors_alpha, (int, float)): vectors_alpha = [vectors_alpha] if vectors_annotation is True: vectors_annotation = [True] * len(new_vecs) elif not vectors_annotation: vectors_annotation = [False] * len(new_vecs) eps = 1e-12 for idx, vec in enumerate(new_vecs): vec = np.asarray(vec) if np.linalg.norm(vec) > 1.0 + eps: raise ValueError('Vector norm must be <= 1.') # So that line does not go out of arrow head vec_line = vec / 1.05 color_str = "rgba({},{},{},{})".format( *hex_to_rgb(vectors_color[idx]), vectors_alpha[idx]) fig.add_trace( go.Scatter3d(x=[0, vec_line[0]], y=[0, vec_line[1]], z=[0, vec_line[2]], mode="lines", hoverinfo=None, line=dict(color=color_str, width=10))) fig.add_trace( go.Cone(x=[vec[0]], y=[vec[1]], z=[vec[2]], u=[vec[0]], v=[vec[1]], w=[vec[2]], sizemode="absolute", showscale=False, opacity=vectors_alpha[idx], colorscale=[vectors_color[idx], vectors_color[idx]], sizeref=0.25, anchor="tip")) if vectors_annotation[idx]: fig_annotations.append( dict( showarrow=False, x=vec[0] * 1.05, y=vec[1] * 1.05, z=vec[2] * 1.05, text="[{},<br> {},<br> {}]".format( round(vec[0], 3), round(vec[1], 3), round(vec[2], 3)), align='left', borderpad=3, xanchor='right' if vec[1] <= 0 else "left", xshift=10, bgcolor="#53565F", font=dict( size=annotation_fontsize, color="#ffffff", family="Courier New, monospace", ), )) # Start construction of sphere # Sphere fig.add_trace(BSPHERE()) # latitudes for kk in LATS: fig.add_trace(kk) # longitudes for kk in LONGS: fig.add_trace(kk) # z-axis fig.add_trace(ZAXIS) # x-axis fig.add_trace(XAXIS) # y-axis fig.add_trace(YAXIS) # zaxis label fig.add_trace(Z0LABEL(fontsize=label_fontsize)) fig.add_trace(Z1LABEL(fontsize=label_fontsize)) # xaxis label fig.add_trace(XLABEL(fontsize=label_fontsize)) # yaxis label fig.add_trace(YLABEL(fontsize=label_fontsize)) fig.update_layout(width=figsize[0], height=figsize[1], autosize=False, hoverdistance=50, showlegend=False, scene_aspectmode='cube', margin=dict(r=0, b=0, l=0, t=0), scene=dict(annotations=fig_annotations, xaxis=dict(showbackground=False, range=[-1.2, 1.2], showspikes=False, visible=False), yaxis=dict(showbackground=False, range=[-1.2, 1.2], showspikes=False, visible=False), zaxis=dict(showbackground=False, range=[-1.2, 1.2], showspikes=False, visible=False)), scene_camera=dict(eye=dict(x=1.5, y=0.4, z=0.4))) if as_widget: return PlotlyWidget(fig) return PlotlyFigure(fig, modebar=True)
def create_static( activations, geom, truth, predict, template, superpose, time_range ): """Create plotly express object without animation. Args: data (pandas.DataFrame): DataFrame to plot. Returns: fig (plotly.ExpressFigure): Plotly Express object. """ # Create plot of activations vectors = direction_vectors(truth, 2000) fig = px.scatter_3d( activations, x='dom_x', y='dom_y', z='dom_z', size='dom_charge', color='dom_time', template=template, range_x=[-axis_lims, axis_lims], range_y=[-axis_lims, axis_lims], range_z=[-axis_lims, axis_lims], color_continuous_scale=px.colors.diverging.RdYlBu, range_color=time_range, size_max=20 ) # Add DOM geometry fig.add_scatter3d( x=geom.x, y=geom.y, z=geom.z, mode='markers', marker={'size': 0.8, 'color': 'black', 'opacity': 0.2}, name='DOM' ) if 'Truth' in superpose: fig.add_scatter3d( x=vectors['true'][0], y=vectors['true'][1], z=vectors['true'][2], mode='lines', name='Truth', marker={'size': 6.0, 'color': 'red'} ) fig.add_scatter3d( x=[vectors['entry'][0]], y=[vectors['entry'][1]], z=[vectors['entry'][2]], marker={'color': 'red'}, mode='markers', name='Entry' ) fig.add_trace( go.Cone( x=[vectors['entry'][0]], y=[vectors['entry'][1]], z=[vectors['entry'][2]], u=100 * truth.true_primary_direction_x, v=100 * truth.true_primary_direction_y, w=100 * truth.true_primary_direction_z, showscale=False ) ) if 'ToI' in superpose: fig.add_scatter3d( x=vectors['toi'][0], y=vectors['toi'][1], z=vectors['toi'][2], mode='lines', name='ToI', marker={'size': 6.0, 'color': 'orange'} ) if 'Predict' in superpose: fig.add_scatter3d( x=predict['true'][0], y=predict['true'][1], z=predict['true'][2], mode='lines', name='Prediction', marker={'size': 6.0, 'color': 'orange'} ) return fig
def create_figure(self): data = [] for face_vertices in self._bz_plot_info.faces: vertex_coords = sort_coords(np.array(face_vertices)) # data.append(go.Mesh3d(**make_triangles(vertex_coords), # alphahull=-1, opacity=0.1, hoverinfo='skip', # color="blue")) for s, t in pairwise(vertex_coords): data.append( go.Scatter3d(x=[s[0], t[0]], y=[s[1], t[1]], z=[s[2], t[2]], mode="lines", hoverinfo="none", marker_color="black")) for label, coords in self._bz_plot_info.labels.items(): c_coords, f_coords = coords["cart"], coords["frac"] data.append( go.Scatter3d(x=[c_coords[0]], y=[c_coords[1]], z=[c_coords[2]], text=[plotly_sanitize_label(label)], mode="markers+text", marker=dict(color="orange", size=6), meta=f_coords, hovertemplate= "(%{meta[0]:.2f} %{meta[1]:.2f} %{meta[2]:.2f})", textposition="middle center", textfont=dict(size=32))) for i, l in self._bz_plot_info.band_paths: data.append( go.Scatter3d(x=[i[0], l[0]], y=[i[1], l[1]], z=[i[2], l[2]], mode="lines", opacity=0.5, hoverinfo="none", line_width=8, marker_color="purple")) _max = np.amax(np.array(sum(self._bz_plot_info.faces, []))) c_max = _max * 1.3 c_cone = _max * 0.3 data.append( go.Cone(x=[c_max], y=[0], z=[0], u=[c_cone], v=[0], w=[0], colorscale=[[0, 'rgb(200,200,200)'], [1, 'rgb(200,200,200)']], showscale=False, hovertemplate="<b>x</b>")) data.append( go.Cone(x=[0], y=[c_max], z=[0], u=[0], v=[c_cone], w=[0], colorscale=[[0, 'rgb(200,200,200)'], [1, 'rgb(200,200,200)']], showscale=False, hovertemplate="<b>y</b>")) data.append( go.Cone(x=[0], y=[0], z=[c_max], u=[0], v=[0], w=[c_cone], colorscale=[[0, 'rgb(200,200,200)'], [1, 'rgb(200,200,200)']], showscale=False, hovertemplate="<b>z</b>")) data.append( go.Scatter3d(x=[0, c_max], y=[0, 0], z=[0, 0], mode="lines", hoverinfo="none", marker_color="black")) data.append( go.Scatter3d(x=[0, 0], y=[0, c_max], z=[0, 0], mode="lines", hoverinfo="none", marker_color="black")) data.append( go.Scatter3d(x=[0, 0], y=[0, 0], z=[0, c_max], mode="lines", hoverinfo="none", marker_color="black")) for i, direct in zip(self._bz_plot_info.rec_lat_vec, ["kx", "ky", "kz"]): nn = sqrt(i[0]**2 + i[1]**2 + i[2]**2) kx, ky, kz = np.array(i) * c_max / nn * 1.15 norm_kx, norm_ky, norm_kz = np.array(i) * c_cone / nn data.append( go.Cone(x=[kx], y=[ky], z=[kz], u=[norm_kx], v=[norm_ky], w=[norm_kz], colorscale=[[0, 'rgb(100,100,100)'], [1, 'rgb(100,100,100)']], showscale=False, hovertemplate=f"<b>{direct}</b>")) data.append( go.Scatter3d(x=[0, kx], y=[0, ky], z=[0, kz], mode="lines", hoverinfo="none", marker_color="black")) range_max = c_max * 1.4 fig = go.Figure(data=data) fig.update_layout(title_font_size=30, font_size=24, width=900, height=900, showlegend=False, scene=dict(xaxis=dict(showspikes=False, range=[-range_max, range_max], showticklabels=False, visible=False), yaxis=dict(showspikes=False, range=[-range_max, range_max], showticklabels=False, visible=False), zaxis=dict(showspikes=False, range=[-range_max, range_max], showticklabels=False, visible=False))) return fig
def plot_photon_path(photon): """ Plot propagation path of a single photon in 3-D. :param photon: Photon object :return: Plotly Figure object. """ # fig = go.Figure( # data=[go.Scatter3d( # x=photon.path[:, 0], # y=photon.path[:, 1], # z=photon.path[:, 2], # mode='lines+markers', # marker=dict( # size=3, # opacity=0.8, # color=np.array(range(0, len(photon.path))) / (len(photon.path) - 1), # # set color to an array/list of desired values # colorscale='Viridis', # choose a colorscale # colorbar=dict( # thickness=20, # tickmode='array', # tickvals=[0, 1], # ticktext=["Start", "End"]) # ), # line=dict( # color='#1f77b4', # width=5) # )] # ) fig = go.Figure(data=[ go.Cone(x=photon.path[:, 0], y=photon.path[:, 1], z=photon.path[:, 2], u=[ direction_cosine[0] for direction_cosine in photon.direction_cosines ], v=[ direction_cosine[1] for direction_cosine in photon.direction_cosines ], w=[ direction_cosine[2] for direction_cosine in photon.direction_cosines ], anchor="tail", colorscale="Viridis", hoverinfo="all", showscale=False, sizemode="absolute", sizeref=3) ]) fig.add_trace( go.Scatter3d( x=photon.path[:, 0], y=photon.path[:, 1], z=photon.path[:, 2], mode='lines', marker=dict( size=2, opacity=0.8, color=np.array(range(0, len(photon.path))) / (len(photon.path) - 1), # set color to an array/list of desired values colorscale='Viridis', # choose a colorscale colorbar=dict(thickness=20, tickmode='array', tickvals=[0, 1], ticktext=["Start", "End"])), line=dict(color='#1f77b4', width=5))) # fig = plt.figure() # ax = plt.axes(projection='3d') # ax.scatter(photon.path[:, 0], photon.path[:, 1], photon.path[:, 2], s=5) # ax.plot(photon.path[:, 0], photon.path[:, 1], photon.path[:, 2]) return fig
def plot_photons(photons, objective, show_aperture=False, cones=False): """ Plot positions of photons in 3-D. Colours accepted photons in green and rejected photons in red. :param photons: List of Photon objects :param objective: Objective object :param show_aperture: Flag to plot circle representing front aperture of objective. Default is `False`. :param cones: Flag to plot photons as dots or cones (indicating propagation direction). Default is `False`. :return: Plotly Figure object. """ # Filter accepted photons acceptance_list = list(map(objective.photon_accepted, photons)) accepted_photons = list(compress(photons, acceptance_list)) # Get coordinates of accepted photons accepted_positions = np.array( [photon.path[-1] for photon in accepted_photons]) # Filter rejected photons rejected_photons = list( compress(photons, [not photon for photon in acceptance_list])) # Get coordinates of rejected photons rejected_positions = np.array( [photon.path[-1] for photon in rejected_photons]) if cones is False: try: fig = go.Figure(data=[ go.Scatter3d( x=accepted_positions[:, 0], y=accepted_positions[:, 1], z=accepted_positions[:, 2], mode='markers', marker=dict( size=3, opacity=0.8, color='green', ), name='Accepted photons', ) ]) fig.add_trace( go.Scatter3d( x=rejected_positions[:, 0], y=rejected_positions[:, 1], z=rejected_positions[:, 2], mode='markers', marker=dict( size=3, opacity=0.2, color='red', ), name='Rejected photons', )) except IndexError: fig = go.Figure(data=[ go.Scatter3d( x=rejected_positions[:, 0], y=rejected_positions[:, 1], z=rejected_positions[:, 2], mode='markers', marker=dict( size=3, opacity=0.2, color='red', ), name='Rejected photons', ) ]) else: # Define constant colorscale pl_red = [[0, '#bd1540'], [1, '#bd1540']] pl_green = [[0, '#009900'], [1, '#009900']] try: fig = go.Figure(data=[ go.Cone(x=accepted_positions[:, 0], y=accepted_positions[:, 1], z=accepted_positions[:, 2], u=[photon.mu_x for photon in accepted_photons], v=[photon.mu_y for photon in accepted_photons], w=[photon.mu_z for photon in accepted_photons], anchor="tail", name='Accepted photons', colorscale=pl_green, hoverinfo="all", showscale=False, sizeref=3) ]) fig.add_trace( go.Cone(x=rejected_positions[:, 0], y=rejected_positions[:, 1], z=rejected_positions[:, 2], u=[photon.mu_x for photon in rejected_photons], v=[photon.mu_y for photon in rejected_photons], w=[photon.mu_z for photon in rejected_photons], anchor="tail", name='Rejected photons', colorscale=pl_red, hoverinfo="all", showscale=False, sizeref=3)) except IndexError: fig = go.Figure(data=[ go.Scatter3d( x=rejected_positions[:, 0], y=rejected_positions[:, 1], z=rejected_positions[:, 2], mode='markers', marker=dict( size=3, opacity=0.2, color='red', ), name='Rejected photons', ) ]) if show_aperture: # Show objective aperture aperture_z = (np.cos(objective.theta) * objective.working_distance + objective.sample_thickness) * np.ones((50, 50)) # Need multiple radii to plot surface R = np.linspace(0, objective.front_aperture / 2, 50) # Sample angles of circle u = np.linspace(0, 2 * np.pi, 50) # Calculate x-y coordinates for circle x = np.outer(R, np.cos(u)) y = np.outer(R, np.sin(u)) # Add to plot fig.add_trace(go.Surface(x=x, y=y, z=aperture_z, showscale=False)) fig.update_layout( title=go.layout.Title(text="Photon positions", xref="paper", x=0), annotations=[ go.layout.Annotation( yref="paper", xref='paper', y=0, x=0, text=("Acceptance rate: %.2f%%" % (calc_acceptance_ratio(photons, objective) * 100)), showarrow=False), go.layout.Annotation(yref="paper", xref='paper', y=0.1, x=0, text=("Photons exited: %d" % len(photons)), showarrow=False) ], scene=dict( xaxis_title="x (um)", yaxis_title="y (um)", zaxis_title="z (um)", )) return fig
pio.renderers.default = 'browser' ## NEEDS TO BE CONVERTED TO ITERATED OEPRATION df = pd.read_csv("data/info/data_fitness_landscape.csv") # filter df = df[(df['phi'] == 5) & (df['leader_choices'] == 5)] fig = go.Figure() fig.add_trace( go.Cone(x=df['res_a'], y=df['res_b'], z=df['M_res'], u=df['coef_a'], v=df['coef_b'], w=df['coef_M'], colorscale='Reds', sizemode="absolute", name="some name", sizeref=30)) fig.update_layout(scene=dict(aspectratio=dict(x=0.5, y=0.5, z=0.5), camera_eye=dict(x=1.2, y=1.2, z=0.6), xaxis_title="parameter a", yaxis_title="parameter b", zaxis_title="parameter M")) fig.show() fig.write_html("figs/fig_3d_info_phi5_lc5.html", include_plotlyjs=True)
def _process_series(self, series): self._init_cyclers() # if legend=True and both 3d lines and surfaces are shown, then hide the # surfaces color bars and only shows line labels in the legend. # TODO: can I show both colorbars and legends by scaling down the color # bars? show_3D_colorscales = True show_2D_vectors = False for s in series: if s.is_3Dline: show_3D_colorscales = False if s.is_2Dvector: show_2D_vectors = True self._fig.data = [] count = 0 for ii, s in enumerate(series): if s.is_2Dline: line_kw = self._kwargs.get("line_kw", dict()) if s.is_parametric: x, y, param = s.get_data() # hides/show the colormap depending on self._use_cm mode = "lines+markers" if not s.is_point else "markers" if (not s.is_point) and (not self._use_cm): mode = "lines" lkw = dict( name=s.label, line_color=next(self._cl), mode=mode, marker=dict( color=param, colorscale=(next( self._cyccm) if self._use_cyclic_cm( param, s.is_complex) else next(self._cm)), size=6, showscale=self.legend and self._use_cm, colorbar=self._create_colorbar(ii, s.label, True), ), customdata=param, hovertemplate=( "x: %{x}<br />y: %{y}<br />u: %{customdata}" if not s.is_complex else "x: %{x}<br />y: %{y}<br />Arg: %{customdata}"), ) self._fig.add_trace( go.Scatter(x=x, y=y, **merge({}, lkw, line_kw))) else: x, y = s.get_data() x, y, _ = self._detect_poles(x, y) lkw = dict( name=s.label, mode="lines" if not s.is_point else "markers", line_color=next(self._cl), ) self._fig.add_trace( go.Scatter(x=x, y=y, **merge({}, lkw, line_kw))) elif s.is_3Dline: # NOTE: As a design choice, I decided to show the legend entry # as well as the colorbar (if use_cm=True). Even though the # legend entry shows the wrong color (black line), it is useful # in order to hide/show a specific series whenever we are # plotting multiple series. x, y, z, param = s.get_data() if not s.is_point: lkw = dict( name=s.label, mode="lines", line=dict( width=4, colorscale=(next(self._cm) if self._use_cm else self._solid_colorscale()), color=param, showscale=self.legend and self._use_cm, colorbar=self._create_colorbar(ii, s.label, True), ), ) else: lkw = dict(name=s.label, mode="markers", line_color=next(self._cl)) line_kw = self._kwargs.get("line_kw", dict()) self._fig.add_trace( go.Scatter3d(x=x, y=y, z=z, **merge({}, lkw, line_kw))) elif (s.is_3Dsurface and (not s.is_complex)) or (s.is_3Dsurface and s.is_complex and (s.real or s.imag)): xx, yy, zz = s.get_data() # create a solid color to be used when self._use_cm=False col = next(self._cl) colorscale = [[0, col], [1, col]] colormap = next(self._cm) skw = dict( name=s.label, showscale=self.legend and show_3D_colorscales, colorbar=self._create_colorbar(ii, s.label), colorscale=colormap if self._use_cm else colorscale, ) surface_kw = self._kwargs.get("surface_kw", dict()) self._fig.add_trace( go.Surface(x=xx, y=yy, z=zz, **merge({}, skw, surface_kw))) # TODO: remove this? Making it works with iplot is difficult if self._kwargs.get("wireframe", False): line_marker = dict(color=next(self._wfcm), width=2) for i, j, k in zip(xx, yy, zz): self._fig.add_trace( go.Scatter3d( x=i, y=j, z=k, mode="lines", line=line_marker, showlegend=False, )) for i, j, k in zip(xx.T, yy.T, zz.T): self._fig.add_trace( go.Scatter3d( x=i, y=j, z=k, mode="lines", line=line_marker, showlegend=False, )) count += 1 elif s.is_contour and (not s.is_complex): xx, yy, zz = s.get_data() xx = xx[0, :] yy = yy[:, 0] # default values ckw = dict( contours=dict( coloring=None, showlabels=False, ), colorscale=next(self._cm), colorbar=self._create_colorbar(ii, s.label, show_2D_vectors), ) # user-provided values contour_kw = self._kwargs.get("contour_kw", dict()) self._fig.add_trace( go.Contour(x=xx, y=yy, z=zz, **merge({}, ckw, contour_kw))) count += 1 elif s.is_implicit: points = s.get_data() if len(points) == 2: # interval math plotting x, y, pixels = self._get_pixels(s, points[0]) ckw = dict( colorscale=[ [0, "rgba(0,0,0,0)"], [1, next(self._cl)], ], showscale=False, name=s.label, ) contour_kw = self._kwargs.get("contour_kw", dict()) self._fig.add_trace( go.Heatmap(x=x, y=y, z=pixels, **merge({}, ckw, contour_kw))) else: x, y, z, ones, plot_type = points zf = z.flatten() m, M = min(zf), max(zf) col = next(self._cl) # default values ckw = dict( contours=dict( coloring="none" if plot_type == "contour" else None, showlabels=False, type="levels" if plot_type == "contour" else "constraint", operation="<", value=[(m + M) / 2], ), colorscale=[ [0, "rgba(0,0,0,0)"], [1, next(self._cl)], ], fillcolor=col, showscale=True, name=s.label, line=dict(color=col), ) contour_kw = self._kwargs.get("contour_kw", dict()) # TODO: sadly, Plotly does not support yet setting contour # levels, hence the visualization will look ugly whenever # plot_type="contour". # https://github.com/plotly/plotly.js/issues/4503 self._fig.add_trace( go.Contour(x=x, y=y, z=ones, **merge({}, ckw, contour_kw))) count += 1 elif s.is_vector: if s.is_2Dvector: xx, yy, uu, vv = s.get_data() streamlines = self._kwargs.get("streamlines", False) if streamlines: # NOTE: currently, it is not possible to create streamlines with # a color scale: https://community.plotly.com/t/how-to-make-python-quiver-with-colorscale/41028 # default values skw = dict(line_color=next(self._qc), arrow_scale=0.15, name=s.label) # user-provided values stream_kw = self._kwargs.get("stream_kw", dict()) stream = create_streamline(xx[0, :], yy[:, 0], uu, vv, **merge({}, skw, stream_kw)) self._fig.add_trace(stream.data[0]) else: # NOTE: currently, it is not possible to create quivers with # a color scale: https://community.plotly.com/t/how-to-make-python-quiver-with-colorscale/41028 # default values qkw = dict(line_color=next(self._qc), scale=0.075, name=s.label) # user-provided values quiver_kw = self._kwargs.get("quiver_kw", dict()) quiver = create_quiver( xx, yy, uu, vv, **merge({}, qkw, quiver_kw)) # merge two dictionaries self._fig.add_trace(quiver.data[0]) else: xx, yy, zz, uu, vv, ww = s.get_data() streamlines = self._kwargs.get("streamlines", False) if streamlines: seeds_points = get_seeds_points(xx, yy, zz, uu, vv, ww) # default values skw = dict( colorscale=next(self._cm), sizeref=0.3, colorbar=self._create_colorbar(ii, s.label), starts=dict( x=seeds_points[:, 0], y=seeds_points[:, 1], z=seeds_points[:, 2], ), ) # user-provided values stream_kw = self._kwargs.get("stream_kw", dict()) self._fig.add_trace( go.Streamtube(x=xx.flatten(), y=yy.flatten(), z=zz.flatten(), u=uu.flatten(), v=vv.flatten(), w=ww.flatten(), **merge({}, skw, stream_kw))) else: # default values qkw = dict( showscale=(not s.is_slice) or self.legend, colorscale=next(self._cm), sizemode="absolute", sizeref=40, colorbar=self._create_colorbar(ii, s.label), ) # user-provided values quiver_kw = self._kwargs.get("quiver_kw", dict()) self._fig.add_trace( go.Cone(x=xx.flatten(), y=yy.flatten(), z=zz.flatten(), u=uu.flatten(), v=vv.flatten(), w=ww.flatten(), **merge({}, qkw, quiver_kw))) count += 1 elif s.is_complex: if s.is_domain_coloring: x, y, magn_angle, img, colors = s.get_data() xmin, xmax = x.min(), x.max() ymin, ymax = y.min(), y.max() self._fig.add_trace( go.Image( x0=xmin, y0=ymin, dx=(xmax - xmin) / s.n1, dy=(ymax - ymin) / s.n2, z=img, name=s.label, customdata=magn_angle, hovertemplate= ("x: %{x}<br />y: %{y}<br />RGB: %{z}" + "<br />Abs: %{customdata[0]}<br />Arg: %{customdata[1]}" ), )) if colors is not None: # chroma/phase-colorbar self._fig.add_trace( go.Scatter( x=[xmin, xmax], y=[ymin, ymax], showlegend=False, mode="markers", marker=dict( opacity=0, colorscale=[ "rgb(%s, %s, %s)" % tuple(c) for c in colors ], color=[-self.pi, self.pi], colorbar=dict( tickvals=[ -self.pi, -self.pi / 2, 0, self.pi / 2, self.pi, ], ticktext=[ "-π", "-π / 2", "0", "π / 2", "π", ], x=1 + 0.1 * count, title="Argument", titleside="right", ), showscale=True, ), )) if s.coloring == "f": # lightness/magnitude-colorbar self._fig.add_trace( go.Scatter( x=[xmin, xmax], y=[ymin, ymax], showlegend=False, mode="markers", marker=dict( opacity=0, colorscale=[[0, "black"], [1, "white"]], color=[0, 1e20], colorbar=dict( tickvals=[0, 1e20], ticktext=["0", "∞"], x=1 + 0.1 * (count + 1), title="Magnitude", titleside="right", ), showscale=True, ), )) count += 2 else: xx, yy, mag_angle, colors, colorscale = s.get_data() mag, angle = mag_angle[:, :, 0], mag_angle[:, :, 1] if s.coloring != "a": warnings.warn( "Plotly doesn't support custom coloring " + "over surfaces. The surface color will show the " + "argument of the complex function.") # create a solid color to be used when self._use_cm=False col = next(self._cl) colorscale = [[0, col], [1, col]] colormap = next(self._cm) if not s.is_complex else next( self._cyccm) skw = dict( name=s.label, showscale=self.legend and show_3D_colorscales, colorbar=dict( x=1 + 0.1 * count, title=s.label, titleside="right", ), colorscale=colormap if self._use_cm else colorscale, surfacecolor=angle, customdata=angle, hovertemplate= "x: %{x}<br />y: %{y}<br />Abs: %{z}<br />Arg: %{customdata}", ) m, M = min(angle.flatten()), max(angle.flatten()) # show pi symbols on the colorbar if the range is close # enough to [-pi, pi] if (abs(m + self.pi) < 1e-02) and (abs(M - self.pi) < 1e-02): skw["colorbar"]["tickvals"] = [ m, -self.pi / 2, 0, self.pi / 2, M, ] skw["colorbar"]["ticktext"] = [ "-π", "-π / 2", "0", "π / 2", "π", ] surface_kw = self._kwargs.get("surface_kw", dict()) self._fig.add_trace( go.Surface(x=xx, y=yy, z=mag, **merge({}, skw, surface_kw))) count += 1 elif s.is_geometry: x, y = s.get_data() lkw = dict(name=s.label, mode="lines", fill="toself", line_color=next(self._cl)) line_kw = self._kwargs.get("line_kw", dict()) self._fig.add_trace( go.Scatter(x=x, y=y, **merge({}, lkw, line_kw))) else: raise NotImplementedError("{} is not supported by {}".format( type(s), type(self).__name__))
def main(): """ Script to visualize surface motion based on a displacement field. Output includes plot of area as a function of time and a movie of mesh motion """ # Script Inputs MAKE_MOVIE = True surface_directory = '/Users/mbarbour/Research/Trachea/Patient_Data/Pt109/Attempt3/displacement_surfaces/' cl_file = '/Users/mbarbour/Research/Trachea/Patient_Data/Pt109/Segmentations/Processed/Pt109_centerline.dat' movie_dir = '/Users/mbarbour/Research/Trachea/Patient_Data/Pt109/Movie/' fig_dit = '/Users/mbarbour/Research/Trachea/Patient_Data/Pt109/Figures/' # surface_directory = '/Users/mbarbour/Dropbox/Respiratory/image_data/Pt_106/DisplacementSurfaces/' # cl_file = '/Users/mbarbour/Dropbox/Respiratory/image_data/Pt_106/Pt_106_centerline.dat' # movie_dir = '/Users/mbarbour/Dropbox/Respiratory/image_data/Pt_106/Movie/' # fig_dit = '/Users/mbarbour/Dropbox/Respiratory/image_data/Pt_106/Figures/' n_planes = 20 # Load surface files and centerline file files = glob.glob(surface_directory + '*.vtk') files = natsorted(files) n_files = len(files) print("Number of files (time_steps): ", n_files) # Inverting between RTS and LPS (switching signs of first two components) x_cl = -np.genfromtxt(cl_file, skip_header=1, usecols=0) y_cl = -np.genfromtxt(cl_file, skip_header=1, usecols=1) z_cl = np.genfromtxt(cl_file, skip_header=1, usecols=2) print("Number of centerline data points:", len(x_cl)) # Define plane centroids and normal vectors plane_ints = np.linspace(0, len(x_cl)-2, n_planes, dtype=int) plane_centroids = np.array(([x_cl[plane_ints], y_cl[plane_ints], z_cl[plane_ints]])) plane_normal_vectors = np.array(([x_cl[plane_ints+1] - x_cl[plane_ints], y_cl[plane_ints+1] - y_cl[plane_ints], z_cl[plane_ints+1] - z_cl[plane_ints]])) plane_area = np.zeros((n_files, n_planes)) volume = np.zeros(n_files) contours = np.empty(n_planes,dtype=object) # Main Loop - loop over surfaces and compute the motion for i in range(len(files)): # print(files[i]) # for i in range(5): # Open surface and displacement fields surface, displacment, X = extract_surface_data(files[i]) # Apply surface displacment apply_surface_displacement(surface, displacment) poly = pv.PolyData(surface) volume[i] = poly.volume # Make movie if MAKE_MOVIE: #camera=dict(eye = dict(x=1.5, y=0.0, z=0.0)) #camera=dict(eye = dict(x=0, y=0.0, z=1.5)) camera = dict( up=dict(x=0, y=0, z=1), center=dict(x=0, y=0, z=0), eye=dict(x=-1.35, y=1.25, z=1.25) ) surf_fig = go.Figure() polydata_mesh_plot(surface, surf_fig, 0.8, 'blue') surf_fig.update_layout(template='plotly_white', scene_camera=camera) surf_fig.write_image(movie_dir+'frame_ortho_'+str(i)+'.png',scale=3) # Extract contours - plane extract and compute area for j in range(n_planes): contour_polydata = slice_extract(surface, plane_centroids[:,j], plane_normal_vectors[:,j]) plane_area[i,j]=slice_area(contour_polydata) contours[j] = contour_polydata # ================================================================ # Figure Generation # ================================================================ slices=np.array([1,2,4,8,9,10,12,13,17]) fig = go.Figure() plot_contour(contours, fig, n_planes, slices) polydata_mesh_plot(surface, fig, opacity=0.1) fig.update_layout(template='plotly_white', title='Slice Locations') fig.show() # Plot the average mesh area in time - normalized fig = go.Figure() for i in slices: fig.add_trace(go.Scatter(y=plane_area[:,i]/np.mean(plane_area[:,i]))) fig.update_layout(template='plotly_white', title='Slice Expansion', font_size=18) fig.update_yaxes(title=r'$\text{Area/Time-averaged Area}, A(t)/\bar{A(t)}$') fig.update_xaxes(title=r"$\text{Time Steps} (\cdot)$") fig.show() # Plot centerline and show the location of the planes with normal vectors fig = go.Figure() skip = 10 fig.add_trace(go.Scatter3d(x=x_cl[::skip], y=y_cl[::skip], z=z_cl[::skip],marker_color='grey')) fig.add_trace(go.Cone(x=plane_centroids[0,:], y=plane_centroids[1,:], z=plane_centroids[2,:], u=plane_normal_vectors[0,:], v=plane_normal_vectors[1,:], w=plane_normal_vectors[2,:], sizemode='absolute',sizeref=0.5)) polydata_mesh_plot(surface, fig, opacity=0.1) fig.update_layout(scene=dict(aspectmode='data',aspectratio=dict(x=1, y=1, z=1)), template='plotly_white', title="Surface Centerlines") fig.show() fig = go.Figure() fig.add_trace(go.Scatter(y = volume)) fig.update_layout(template='plotly_white', title='Volume', font_size=19) fig.update_yaxes(title=r'$\text{Mesh Volume (mm)}$') fig.update_xaxes(title='image (time)') fig.show() # Plot peak motion for all slices at the same instant in time fig = go.Figure() num = 1 for tstep in (5,11): fig.add_trace(go.Scatter(y=plane_area[tstep,:]/np.mean(plane_area, axis=0), mode='markers+lines', name="Inspiration Peak "+str(num))) num = num + 1 fig.add_shape(type='line', x0=0, y0=1, x1=len(plane_area[15,:]), y1=1, line=dict( color="grey", width=4, dash="dashdot")) fig.update_layout(template='plotly_white', title='Peak Motion', font_size=19) fig.update_yaxes(title=r'$\text{Area/Time-averaged Area}, A(t)/\bar{A(t)}$') fig.update_xaxes(title='Length of Domain') fig.show()
def pintar_elementos_gradient_descent(valores_betas): valor_loss = loss_function(*valores_betas) # Betas actuales: punto_beta = go.Scatter3d(x=[valores_betas[0]], y=[valores_betas[1]], z=[valor_loss], marker_color="purple", showlegend=False, name="Valor actual weights", hovertemplate=('w₁: %{x}<br>' + 'w₂: %{y}<br>' + 'Error (loss): %{z}')) valor_gradiente = np.nan_to_num( np.array(gradiente_loss_function(*valores_betas))) if np.linalg.norm(valor_gradiente) == 0.0: return (punto_beta, None, None) valor_gradiente_normalizado = valor_gradiente / np.linalg.norm( valor_gradiente) # Computar flecha del vector gradiente: flecha = [ [ valores_betas[0] - valor_gradiente_normalizado[0], valores_betas[0] + valor_gradiente_normalizado[0] ], [ valores_betas[1] - valor_gradiente_normalizado[1], valores_betas[1] + valor_gradiente_normalizado[1] ], [ valor_loss + np.dot(valor_gradiente, -valor_gradiente_normalizado), valor_loss + np.dot(valor_gradiente, valor_gradiente_normalizado) ] ] # Nuestro vector algebraico por tanto es: vector_gradiente = np.array([ flecha[0][1] - flecha[0][0], flecha[1][1] - flecha[1][0], flecha[2][1] - flecha[2][0] ]) # Para que siempre tenga un tamaño razonable en el gráfico, # debemos escalarlo acorde al tamaño de los ejes y al aspect # ratio del gráfico: vector_gradiente_normalizado = vector_gradiente / np.linalg.norm( vector_gradiente) longitud_eje_x = rango_eje_x[1] - rango_eje_x[0] longitud_eje_y = rango_eje_y[1] - rango_eje_y[0] longitud_eje_z = rango_eje_z[1] - rango_eje_z[0] cubo = np.array([longitud_eje_x, longitud_eje_y, longitud_eje_z]) / 5.0 norma_escaladora = calcular_norma_escaladora(cubo, vector_gradiente_normalizado, cubo, np.array([1, 1, 1])) vector_gradiente_escalado = (vector_gradiente_normalizado * norma_escaladora * 0.5) # Coordenadas de la línea final para el vector: flecha_final = [[ valores_betas[0] - vector_gradiente_escalado[0], valores_betas[0] + vector_gradiente_escalado[0] ], [ valores_betas[1] - vector_gradiente_escalado[1], valores_betas[1] + vector_gradiente_escalado[1] ], [ valor_loss - vector_gradiente_escalado[2], valor_loss + vector_gradiente_escalado[2] ]] # Pintar línea de la flecha: linea_flecha = go.Scatter3d(x=flecha_final[0], y=flecha_final[1], z=flecha_final[2], mode='lines', line_color="yellow", line_width=6, hoverinfo="skip", showlegend=False) # Pintar punta de la flecha (cono): punta_flecha = go.Cone(x=[flecha_final[0][0]], y=[flecha_final[1][0]], z=[flecha_final[2][0]], u=[-vector_gradiente_escalado[0]], v=[-vector_gradiente_escalado[1]], w=[-vector_gradiente_escalado[2]], anchor="tail", showscale=False, showlegend=False, hoverinfo="skip", colorscale=[[0, "yellow"], [1, "yellow"]], sizemode="scaled") return punto_beta, linea_flecha, punta_flecha
}]]) fig.add_trace(go.Streamtube(x=x, y=y, z=z, u=u, v=v, w=w), 1, 1) fig.add_trace(go.Streamtube(x=x, y=y, z=z, u=w, v=v, w=u), 1, 2) fig.add_trace(go.Streamtube(x=x, y=y, z=z, u=u, v=w, w=v), 1, 3) fig.update_layout(scene_camera_eye=dict(x=2, y=2, z=2), scene2_camera_eye=dict(x=2, y=2, z=2), scene3_camera_eye=dict(x=2, y=2, z=2)) fig.show() # In[ ]: import plotly.graph_objects as go fig = go.Figure(data=go.Cone(x=[1], y=[1], z=[1], u=[1], v=[1], w=[0])) fig.update_layout(scene_camera_eye=dict(x=-0.76, y=1.8, z=0.92)) fig.show() # In[ ]: import plotly.graph_objects as go fig = go.Figure(data=go.Cone(x=[1, 2, 3], y=[1, 2, 3], z=[1, 2, 3], u=[1, 0, 0], v=[0, 3, 0], w=[0, 0, 2],
def add_burn_arrow(figure, burnDV, burnTime, startOrbit, dateFormat = None, scale=1/2, name = 'Burn', color = (255,0,0), burnDVisAbsolute = True): burnPos, preBurnVel = startOrbit.get_state_vector(burnTime) if burnDVisAbsolute: prograde, normal, radial = get_burn_components(burnDV, burnPos, preBurnVel) else: prograde = burnDV[0] normal = burnDV[1] radial = burnDV[2] burnDV = burn_components_to_absolute(prograde, normal, radial, burnPos, preBurnVel) arrowLength = abs((1-startOrbit.ecc)*startOrbit.a)*scale arrowHeadPos = burnPos + burnDV/norm(burnDV)*arrowLength figure.add_trace(go.Scatter3d( x = [burnPos[0], arrowHeadPos[0]], y = [burnPos[1], arrowHeadPos[1]], z = [burnPos[2], arrowHeadPos[2]], mode = "lines", line = dict( color = 'rgb'+str(color)), hoverinfo = 'skip', showlegend = False, )) figure.add_trace(go.Scatter3d( x = [burnPos[0]], y = [burnPos[1]], z = [burnPos[2]], mode = "markers", marker = dict( color = 'rgb'+str(color), symbol = 'circle-open', size = 5 ), hoverinfo = 'skip', showlegend = False, )) if dateFormat is None: dateFormat = dict(day = 6, year = 426) dateString = seconds_to_date_string(burnTime, dateFormat) direction = burnDV/norm(burnDV) * arrowLength/2 figure.add_trace(go.Cone( x = [arrowHeadPos[0]], y = [arrowHeadPos[1]], z = [arrowHeadPos[2]], u = [direction[0]], v = [direction[1]], w = [direction[2]], colorscale = [[0, 'rgb'+str(color)], [1, 'rgb'+str(color)]], showscale = False, showlegend = False, name = name, hovertemplate = \ "{:.2f}".format(prograde) + 'm/s prograde' + "<br>" + \ "{:.2f}".format(normal) + 'm/s normal' + "<br>" + \ "{:.2f}".format(radial) + 'm/s radial'+"<br>"+"<br>"+ \ dateString ))