nxplot_3d.py (9952B)
1 #!/usr/bin/evn python3.10 2 3 import matplotlib.pyplot as plt 4 import matplotlib.cm as cm 5 6 import plotly 7 import plotly.graph_objs as pgo 8 9 def get_trace_nodes_3D_legend(posG, info, color, size, legend_names = None, linewidth=0.000001, opac = 0.9): 10 ''' 11 Get trace of nodes for plotting in 3D. 12 Input: 13 - posG = dictionary with nodes as keys and coordinates as values. 14 - info = hover information for each node, e.g. a dictionary with node IDs and values = hover information 15 - color = a dictionary of key = association name for each color (for legend) and value = hex color 16 - size = a dictionary with node Ids and values=sizes of nodes 17 - legend_names = list of values e.g. strings for each color 18 - linewidth = float; contour of nodes 19 - opac = transparency of nodes 20 21 Return a trace for plotly graph objects plot including a legend. 22 ''' 23 24 # dividing traces based on unique colors > for legend 25 color_dict = {} 26 for i in set(color.values()): 27 sublist = [] 28 for k,v in color.items(): 29 if v == i: 30 sublist.append(k) 31 color_dict[i]= sublist 32 33 d_col_pos = {} 34 for i,j_list in color_dict.items(): 35 sub = {} 36 for ix,(k,v) in enumerate(posG.items()): 37 if k in j_list: 38 #sub[ix] = v 39 sub[k] = v 40 d_col_pos[i] = sub 41 d_col_pos_ordered = dict(sorted(d_col_pos.items(),reverse=True)) 42 43 # creating traces 44 traces = [] 45 46 if legend_names is not None and len(legend_names) == len(set(color.values())): 47 48 for elem,(col, dct) in enumerate(d_col_pos_ordered.items()): 49 50 ids = list(dct.keys()) 51 coords = list(dct.values()) 52 53 l_info_sorted_to_ids = [(info[key]) for key in ids] #{key:info[key] for key in ids} 54 #l_info_sorted_to_ids = list(info_sorted_to_ids.values()) 55 56 l_size_sorted_to_ids = [(size[key]) for key in ids] #{key:size[key] for key in ids} 57 #l_size_sorted_to_ids = list(size_sorted_to_ids.values()) 58 59 trace = pgo.Scatter3d(x=[i[0] for i in coords], 60 y=[i[1] for i in coords], 61 z=[i[2] for i in coords], 62 mode = 'markers', 63 text = l_info_sorted_to_ids, 64 hoverinfo = 'text', 65 marker = dict( 66 color = col, 67 size = l_size_sorted_to_ids, 68 symbol = 'circle', 69 line = dict(width = linewidth, 70 color = 'dimgrey'), 71 opacity = float(col[4:][1:-1].split(', ')[-1]), 72 ), 73 name = "Group: "+str(list(legend_names.values())[elem]) 74 ) 75 traces.append(trace) 76 return traces 77 78 else: 79 for elem,(col, dct) in enumerate(d_col_pos_ordered.items()): 80 81 ids = list(dct.keys()) 82 coords = list(dct.values()) 83 84 l_info_sorted_to_ids = [(info[key]) for key in ids] #{key:info[key] for key in ids} 85 #l_info_sorted_to_ids = list(info_sorted_to_ids.values()) 86 87 l_size_sorted_to_ids = [(size[key]) for key in ids] #{key:size[key] for key in ids} 88 #l_size_sorted_to_ids = list(size_sorted_to_ids.values()) 89 90 trace = pgo.Scatter3d(x=[i[0] for i in coords], 91 y=[i[1] for i in coords], 92 z=[i[2] for i in coords], 93 mode = 'markers', 94 text = l_info_sorted_to_ids, 95 hoverinfo = 'text', 96 marker = dict( 97 color = col, 98 size = l_size_sorted_to_ids, 99 symbol = 'circle', 100 line = dict(width = linewidth, 101 color = 'dimgrey'), 102 opacity = float(col[4:][1:-1].split(', ')[-1])/100, 103 ), 104 name = "Group: "+str(elem) 105 ) 106 traces.append(trace) 107 return traces 108 109 110 def get_trace_edges_3D(G, posG, color = '#C7C7C7', opac = 0.1, linewidth=0.1): 111 ''' 112 Get trace of edges for plotting in 3D. 113 Input: 114 - G = Graph 115 - posG = dictionary with nodes as keys and coordinates as values. 116 - color = string; hex color 117 - opac = transparency of edges e.g. 1.2 118 - linewidth = float; 119 120 Return a trace for plotly graph objects plot. 121 ''' 122 123 edge_x = [] 124 edge_y = [] 125 edge_z = [] 126 for edge in G.edges(): 127 x0, y0, z0 = posG[edge[0]] 128 x1, y1, z1 = posG[edge[1]] 129 edge_x.append(x0) 130 edge_x.append(x1) 131 edge_x.append(None) 132 edge_y.append(y0) 133 edge_y.append(y1) 134 edge_y.append(None) 135 edge_z.append(z0) 136 edge_z.append(z1) 137 edge_z.append(None) 138 139 trace_edges = pgo.Scatter3d( 140 x = edge_x, 141 y = edge_y, 142 z = edge_z, 143 mode = 'lines', hoverinfo='none', 144 line = dict(width = linewidth, color = color), 145 opacity = opac, 146 name = "Links" 147 ) 148 149 return trace_edges 150 151 152 # ------------------------------------------------------------------------------------- 153 # ------------------------------------------------------------------------------------- 154 155 # P L O T T I N G 156 157 # ------------------------------------------------------------------------------------- 158 # ------------------------------------------------------------------------------------- 159 160 161 162 def plot_3D(data, path, fname, scheme='light',annotat=None, show_leg=True, auto_open=True): 163 ''' 164 Create a 3D plot from traces using plotly. 165 Input: 166 - data = list of traces 167 - filename = string 168 - scheme = 'light' or 'dark' 169 - annotations = None or plotly annotations 170 171 Return plot in 3D and file, saved as html. 172 ''' 173 174 fig = pgo.Figure() 175 176 for i in data: 177 fig.add_trace(i) 178 179 if scheme == 'dark' and annotat==None: 180 fig.update_layout(template='plotly_dark', 181 showlegend=show_leg, autosize = True, 182 scene=dict( 183 xaxis_title='', 184 yaxis_title='', 185 zaxis_title='', 186 xaxis=dict(nticks=0,tickfont=dict( 187 color='black')), 188 yaxis=dict(nticks=0,tickfont=dict( 189 color='black')), 190 zaxis=dict(nticks=0,tickfont=dict( 191 color='black')), 192 dragmode="turntable" 193 )) 194 195 elif scheme == 'dark': 196 fig.update_layout(template='plotly_dark', 197 showlegend=show_leg, autosize = True, 198 scene=dict( 199 xaxis_title='', 200 yaxis_title='', 201 zaxis_title='', 202 xaxis=dict(nticks=0,tickfont=dict( 203 color='black')), 204 yaxis=dict(nticks=0,tickfont=dict( 205 color='black')), 206 zaxis=dict(nticks=0,tickfont=dict( 207 color='black')), 208 dragmode="turntable", 209 annotations=annotat, 210 )) 211 212 elif scheme == 'light' and annotat==None: 213 fig.update_layout(template='plotly_white', 214 showlegend=show_leg, width=1200, height=1200, 215 scene=dict( 216 xaxis_title='', 217 yaxis_title='', 218 zaxis_title='', 219 xaxis=dict(nticks=0,tickfont=dict( 220 color='white')), 221 yaxis=dict(nticks=0,tickfont=dict( 222 color='white')), 223 zaxis=dict(nticks=0,tickfont=dict( 224 color='white')), 225 dragmode="turntable", 226 )) 227 228 elif scheme == 'light': 229 fig.update_layout(template='plotly_white', 230 showlegend=show_leg, width=1200, height=1200, 231 scene=dict( 232 xaxis_title='', 233 yaxis_title='', 234 zaxis_title='', 235 xaxis=dict(nticks=0,tickfont=dict( 236 color='white')), 237 yaxis=dict(nticks=0,tickfont=dict( 238 color='white')), 239 zaxis=dict(nticks=0,tickfont=dict( 240 color='white')), 241 dragmode="turntable", 242 annotations = annotat 243 )) 244 else: 245 print('Oops, something went wrong. Please check input parameters.') 246 247 fig.update_xaxes(visible=False) 248 fig.update_yaxes(visible=False) 249 fig.write_html(path+fname+'.html') 250 251 return plotly.offline.plot(fig, filename = path+fname+'.html', auto_open=auto_open)