def draw(self, filename, engine='graphviz'): """Draws the TS. The filename extension determines the format. [engine] Rendering engine used to draw the TS. Valid values: cairo, graphviz, astg (for draw_astg) If [filename] is None and engine is 'cairo', then the interactive window is used""" if engine == 'graphviz': vprops = {'label':self.vp_state_name} eprops = {'label':self.ep_edge_label} if 'frequency' in self.g.vertex_properties: # vp_width = self.g.new_vertex_property("float") all_traces = self.vp_state_frequency[self.get_state(self.get_initial_state())] # for v in self.g.vertices(): # vp_width[v] = 3.0*self.vp_state_frequency[v]/all_traces # vprops['width'] = vp_width vsize=(self.vp_state_frequency, 2.0/all_traces) else: vsize=0.105 if 'frequency' in self.g.edge_properties: all_traces = self.vp_state_frequency[self.get_state(self.get_initial_state())] penwidth=(self.ep_edge_frequency, 10.0/all_traces) else: penwidth=1.0 print(vprops) if self.g.num_vertices() < 150: layout = 'dot' overlap = False else: layout = None overlap = 'Prism' gt.graphviz_draw(self.g, ratio='auto', vprops=vprops, splines=True, eprops=eprops, sep=1.0, overlap=overlap, vsize=vsize, penwidth=penwidth, layout=layout, output=filename)
def draw_svg(self,filename="graph.svg"): gt.graphviz_draw(self.g, # pos=pos, vprops=self.vprops, eprops=self.eprops, gprops=self.gprops, layout='dot', output=filename)
def render_graphviz(g, file_name): gt.graphviz_draw(g, vcolor='#0055FF', elen=10, layout='dot', output=file_name, size=(30, 30), vsize=1, penwidth=4, vprops={ 'label': g.vertex_properties['label'], 'labeljust': 'b', 'labelloc': 'b', 'labeldistance': 7.5, 'labelangle': 75 })
def graphviz_sentence_graph_draw( sentence_graph, sentence, output_folder_name="sentence-graphs-visualization", output_file_name="sentence-graph-debug", file_extension=".png", base_vertex_size=25, base_vertex_font_size=25): output_file_name = output_file_name.replace("/", "-slash-") output_file_path = os.path.join(output_folder_name, output_file_name) shortened_output_file_path = output_file_path[:252] graphviz_draw( sentence_graph.get_graph(), size=(50000, 50000), output=shortened_output_file_path + "--graphviz" + file_extension, #vertex_text=sentence_graph.get_word_vertex_properties(), vsize=base_vertex_size, #vertex_font_size=base_vertex_font_size,#vertex_font_size_property_map, output_format='png') #,
def draw(self, filename, engine='graphviz'): """Draws the TS. The filename extension determines the format. [engine] Rendering engine used to draw the TS. Valid values: cairo, graphviz, astg (for draw_astg) If [filename] is None and engine is 'cairo', then the interactive window is used""" if engine == 'graphviz': vprops = {'label':self.vp_state_name} eprops = {'label':self.ep_edge_label} if 'frequency' in self.g.vertex_properties: # vp_width = self.g.new_vertex_property("float") all_traces = self.vp_state_frequency[self.get_state(self.get_initial_state())] # for v in self.g.vertices(): # vp_width[v] = 3.0*self.vp_state_frequency[v]/all_traces # vprops['width'] = vp_width vsize=(self.vp_state_frequency, 2.0/all_traces) else: vsize=0.105 if 'frequency' in self.g.edge_properties: all_traces = self.vp_state_frequency[self.get_state(self.get_initial_state())] penwidth=(self.ep_edge_frequency, 10.0/all_traces) else: penwidth=1.0 print vprops if self.g.num_vertices() < 150: layout = 'dot' overlap = False else: layout = None overlap = 'Prism' gt.graphviz_draw(self.g, ratio='auto', vprops=vprops, splines=True, eprops=eprops, sep=1.0, overlap=overlap, vsize=vsize, penwidth=penwidth, layout=layout, output=filename) elif engine=='cairo': #use cairo pos = gt.sfdp_layout(self.g) vprops = {'text':self.vp_state_name} if 'frequency' in self.g.vertex_properties: vp_width = self.g.new_vertex_property("float") all_traces = self.vp_state_frequency[self.get_state(self.get_initial_state())] #use numpy array access # vp_widht.a = int(max(100.0*self.vp_state_frequency.a/all_traces) for v in self.g.vertices(): vp_width[v] = int(100.0*self.vp_state_frequency[v]/all_traces) vprops['size'] = vp_width gt.graph_draw(self.g, pos=pos, vprops=vprops, output=filename) elif engine=='astg': if filename.endswith('.ps'): format = '-Fps' elif filename.endswith('.gif'): format = '-Fgif' elif filename.endswith('.dot'): format = '-Fdot' elif filename.endswith('.png'): format = '-Fpng' elif filename.endswith('.svg'): format = '-Fsvg' else: raise TypeError, 'Unsupported output for draw_astg' #check if file can be forwarded as input_filename if self.filename and not self.modified_since_last_write: input_filename = self.filename else: # or create tmp file with save tmpfile = tempfile.NamedTemporaryFile(mode='w', delete=False) print "Saving TS to temporary file '{0}'".format( tmpfile.name ) self.save(tmpfile) tmpfile.close() input_filename = tmpfile.name params = ['draw_astg', '-sg', '-noinfo', format, input_filename] output = subprocess.check_output( params ) with open(filename,'w+b') as f: f.write(output)
def draw(self, filename, engine='graphviz'): """Draws the TS. The filename extension determines the format. [engine] Rendering engine used to draw the TS. Valid values: cairo, graphviz, astg (for draw_astg) If [filename] is None and engine is 'cairo', then the interactive window is used""" if engine == 'graphviz': vprops = {'label': self.vp_state_name} eprops = {'label': self.ep_edge_label} if 'frequency' in self.g.vertex_properties: # vp_width = self.g.new_vertex_property("float") all_traces = self.vp_state_frequency[self.get_state( self.get_initial_state())] # for v in self.g.vertices(): # vp_width[v] = 3.0*self.vp_state_frequency[v]/all_traces # vprops['width'] = vp_width vsize = (self.vp_state_frequency, 2.0 / all_traces) else: vsize = 0.105 if 'frequency' in self.g.edge_properties: all_traces = self.vp_state_frequency[self.get_state( self.get_initial_state())] penwidth = (self.ep_edge_frequency, 10.0 / all_traces) else: penwidth = 1.0 print vprops if self.g.num_vertices() < 150: layout = 'dot' overlap = False else: layout = None overlap = 'Prism' gt.graphviz_draw(self.g, ratio='auto', vprops=vprops, splines=True, eprops=eprops, sep=1.0, overlap=overlap, vsize=vsize, penwidth=penwidth, layout=layout, output=filename) elif engine == 'cairo': #use cairo pos = gt.sfdp_layout(self.g) vprops = {'text': self.vp_state_name} if 'frequency' in self.g.vertex_properties: vp_width = self.g.new_vertex_property("float") all_traces = self.vp_state_frequency[self.get_state( self.get_initial_state())] #use numpy array access # vp_widht.a = int(max(100.0*self.vp_state_frequency.a/all_traces) for v in self.g.vertices(): vp_width[v] = int(100.0 * self.vp_state_frequency[v] / all_traces) vprops['size'] = vp_width gt.graph_draw(self.g, pos=pos, vprops=vprops, output=filename) elif engine == 'astg': if filename.endswith('.ps'): format = '-Fps' elif filename.endswith('.gif'): format = '-Fgif' elif filename.endswith('.dot'): format = '-Fdot' elif filename.endswith('.png'): format = '-Fpng' elif filename.endswith('.svg'): format = '-Fsvg' else: raise TypeError, 'Unsupported output for draw_astg' #check if file can be forwarded as input_filename if self.filename and not self.modified_since_last_write: input_filename = self.filename else: # or create tmp file with save tmpfile = tempfile.NamedTemporaryFile(mode='w', delete=False) print "Saving TS to temporary file '{0}'".format(tmpfile.name) self.save(tmpfile) tmpfile.close() input_filename = tmpfile.name params = ['draw_astg', '-sg', '-noinfo', format, input_filename] output = subprocess.check_output(params) with open(filename, 'w+b') as f: f.write(output)
def save_drawing(output_folder, g, pos, description, color_property_map=None, color_array=None, formats=None, verbose=True, opacity=0.2, edge_colors=None, draw_vertices=True): if formats is None: formats = ['jpg', 'pdf'] # GraphViz needs the positions to be between 0 and 1. So normalize first. pos_normalized = g.new_vertex_property('vector<double>') vertices = list(g.vertices()) if type(pos) is not np.ndarray: Y = pos.get_2d_array(range(2)) else: Y = pos # Translate s.t. smallest values for both x and y are 0. Y[0, :] += -Y[0, :].min() Y[1, :] += -Y[1, :].min() # Scale s.t. max(max(x, y)) = 1 (while keeping the same aspect ratio!) scaling = 1 / (np.absolute(Y).max()) Y *= scaling pos_normalized.set_2d_array(Y) # Output size in cm (matches UF images) out_size = [14.3] * 2 # Crop for aspect ratio if max(Y[0, :]) < max(Y[1, :]): out_size[0] *= max(Y[0, :]) else: out_size[1] *= max(Y[1, :]) # Use the supplied color array for the vertex colors, if given. if color_array is not None: color_property_map = g.new_vertex_property('double') assert len(color_array) == g.num_vertices() for v in vertices: color_property_map[int(v)] = color_array[int(v)] if verbose: print('[layout_io] Saving layout drawing... ({0})'.format(description)) if edge_colors == "rgb": edge_color = g.new_edge_property('string') edge_length = g.new_edge_property('float') edges = list(g.edges()) for e in edges: v1 = e.source() v2 = e.target() length = ((Y[:, int(v1)] - Y[:, int(v2)])**2).sum()**0.5 edge_length[e] = length lengths = edge_length.get_array() for e in edges: # Colour coding the edges based on edge length x = (edge_length[e] - np.min(lengths)) / (np.max(lengths) - np.min(lengths)) red = min(max(0, 1 - 2 * x), 1) green = max(0, 1 - abs(2 * x - 1)) blue = min(max(0, -1 + 2 * x), 1) edge_color[e] = "#" edge_color[e] += "{0:0{1}x}".format(int(red * 255), 2) edge_color[e] += "{0:0{1}x}".format(int(green * 255), 2) edge_color[e] += "{0:0{1}x}".format(int(blue * 255), 2) edge_color[e] += "{0:0{1}x}".format(int(opacity * 255), 2) else: edge_color = "#000000{0:0{1}x}".format(int(opacity * 255), 2) for extension in formats: # Use the graphviz interface that graph_tool supplies to save drawings. if not draw_vertices: # For this to work correctly, the gt.graphviz_draw implementation needs some tweaking: # * Edge attribute headclip: set to "false" # * Edge attribute tailclip: set to "false" # * Node attribute shape: set to "none" gt.graphviz_draw(g, fork=True, pos=pos_normalized, pin=True, penwidth=1, ecolor=edge_color, vsize=0, vcolor='#00ff0000', output=output_folder + '/' + description + '.' + extension, size=tuple(out_size)) elif color_property_map is None: gt.graphviz_draw(g, fork=True, pos=pos_normalized, pin=True, penwidth=1, ecolor=edge_color, vsize=0.1, vcolor='#009900', output=output_folder + '/' + description + '.' + extension, size=tuple(out_size)) else: gt.graphviz_draw(g, fork=True, pos=pos_normalized, pin=True, penwidth=1, ecolor=edge_color, vsize=0.1, vcmap=matplotlib.cm.hot, vcolor=color_property_map, output=output_folder + '/' + description + '.' + extension, size=tuple(out_size))
e_text_parallel =g.new_edge_property( "bool") e_font_family =g.new_edge_property( "string") e_font_slant =g.new_edge_property( "int") e_font_weight =g.new_edge_property( "int") e_font_size =g.new_edge_property( "double") e_sloppy =g.new_edge_property( "bool") e_seamless =g.new_edge_property( "bool") for e in g.edges(): e_color[e] = Indian_Red e_dash_style[e] = [] e_pen_width[e] = 5 e_end_marker[e] = "arrow" e_marker_size[e] = 30 e_text[e] = "edge text" e_font_size[e] = 20 e_font_family[e] = "Consolas" gt.graphviz_draw(g, pos, vsize = v_size, vcolor=deg, vorder=deg, elen=5, ecolor=ebet, eorder=ebet) raw_input("Press Enter to Continue") # # v_fill = g.degree_property_map("in") # # v_fill = [0.6, 0.6, 0.6, 1] deg.a = 2 * (np.sqrt(deg.a) * 0.8 + 0.4) gt.graphviz_draw(g, pos, vsize = v_size, vcolor=deg, vorder=deg, elen=5, ecolor=ebet, eorder=ebet)
def main(compute_index, output_format, *args, **kwargs): # Attempt to import graph_tool, and share a helpful debugging message if it's not found. try: import graph_tool.all as gt except ImportError as e: print str(e) print '\n'.join([ "", "ERROR: The \"graph_tool\" module could not be imported.", "Install the package and then point to it with PYTHONPATH.", "", "Details: graph-tool isn't required for most scripts in this repository.", "But it's needed to draw graphs in *this* script. To download this", "package, see the download instructions on the graph-tool website:", "", "https://graph-tool.skewed.de/download", "" "Note: it's not enough to install \"graph_tool\" through pip.", "It relies on C++ libraries for accelerated graph routines.", "You'll have to use your system package manager or compile from scratch.", "", ]) raise SystemExit # This is the graph that we'll construct graph = gt.Graph() # These data structures hold links to the vertices, edges, and their properties vertices = {} vertex_page_types = [] vertex_total_times = [] vertex_mean_times = [] vertex_occurrences = [] edge_occurrences = [] edge_probabilities = [] # Fetch the set of graph data from the round of computation that the caller wants, # or from the most recent graph if a version hasn't been provided. # Note that the compute_index should be the same for the vertex and edge data, so we # look it up using the same index. if compute_index is None: compute_index = NavigationVertex.select(fn.Max(NavigationVertex.compute_index)).scalar() vertex_models = NavigationVertex.select().where(NavigationVertex.compute_index == compute_index) edge_models = NavigationEdge.select().where(NavigationEdge.compute_index == compute_index) # Add vertices to graph and save vertex properties for vertex_model in vertex_models: # Add a vertex to the graph and save its properties vertex = graph.add_vertex() vertices[vertex_model.id] = vertex vertex_page_types.append(vertex_model.page_type) vertex_total_times.append(vertex_model.total_time) vertex_mean_times.append(vertex_model.mean_time) vertex_occurrences.append(vertex_model.occurrences) # Add edges to the graph and save their properties for edge_model in edge_models: graph.add_edge( # We look up vertices using the '_vertex_id' properties because this is already # retrieved in the fetched rows. Note that if we want to look it up by # page type, this will require two extra queries to the database (one for # each vertex) for each edge added, which is very costly. vertices[edge_model.source_vertex_id], vertices[edge_model.target_vertex_id], ) edge_occurrences.append(edge_model.occurrences) edge_probabilities.append(edge_model.probability) # Fix the positions and colors of the first and final vertices vertex_positions = [] vertex_pins = [] vertex_colors = [] for page_type in vertex_page_types: if page_type == 'Start': vertex_positions.append([0.5, 3]) vertex_pins.append(True) vertex_colors.append("#b2f3ba") # light green elif page_type == 'End': vertex_positions.append([9.5, 3]) vertex_pins.append(True) vertex_colors.append("#f3a4a7") # light red else: vertex_positions.append([5, 3]) vertex_pins.append(False) vertex_colors.append("white") vertex_position_property =\ graph.new_vertex_property(str("vector<double>"), vals=vertex_positions) vertex_pin_property = graph.new_vertex_property(str("boolean"), vals=vertex_pins) vertex_color_property = graph.new_vertex_property(str("string"), vals=vertex_colors) # Because we're using unicode literals, each of the "value types" need to be coerced # to a string explicitly before creating new properties. # When making labels, we take advantage of the fact that most page types only have one # space, and usually they should be split into two new lines if they have a space. split_page_type_names = [_.replace(' ', '\n') for _ in vertex_page_types] vertex_labels = graph.new_vertex_property(str("string"), vals=split_page_type_names) # Determine vertex size based on frequently they have occurred. # While larger size means more visits, the relationship isn't linear. # The "log" is necessary to make sure that the difference isn't too severe between vertices. # This was hand-tailored to just look good. # vertex_occurrences_array = np.array(vertex_occurrences) # vertex_size_array = np.log((vertex_occurrences_array * float(10)) / np.max(vertex_occurrences)) # noqa # small_vertex_indexes = vertex_size_array < MINIMUM_VERTEX_SIZE # vertex_size_array[small_vertex_indexes] = MINIMUM_VERTEX_SIZE # vertex_sizes = graph.new_vertex_property(str("float"), vals=vertex_size_array) # Compute the font sizes to scale with vertex size. # This was hand-tailored to just look good too. # font_size_array = vertex_size_array * 10 # small_font_indexes = font_size_array < MINIMUM_FONT_SIZE # font_size_array[small_font_indexes] = MINIMUM_FONT_SIZE # vertex_font_sizes = graph.new_vertex_property(str("double"), vals=font_size_array) # Edge label is determined by the probability that it is taken edge_labels = graph.new_edge_property(str("float"), vals=np.round(edge_probabilities, 2)) # Edge thickness is determined by how likely a participant was to follow that transition edge_widths = graph.new_edge_property( str("float"), vals=[p * EDGE_PEN_WIDTH_PER_PROBABILITY for p in edge_probabilities], ) # Show only the top most frequently visited page types vertex_occurrences_array = np.array(vertex_occurrences) is_vertex_frequent = vertex_occurrences_array >=\ np.percentile(vertex_occurrences_array, PAGE_TYPE_PERCENTILE) is_vertex_start_or_end = np.logical_or( np.array(vertex_page_types) == "Start", np.array(vertex_page_types) == "End" ) show_vertex = np.logical_or(is_vertex_frequent, is_vertex_start_or_end) vertex_filter = graph.new_vertex_property(str("boolean"), vals=show_vertex) graph.set_vertex_filter(vertex_filter) # Show only the top most taken transitions # This uses two conditions: # First, the transition has to have been taken a large number of times---the # number of occurrences must be within a certain percentile of all occurrences taken # Second, the transition has to have a certain minimum probability of occurring # edge_occurrences_array = np.array(edge_occurrences) edge_probabilities_array = np.array(edge_probabilities) # does_edge_occur_often = edge_occurrences_array >=\ # np.percentile(edge_occurrences_array, TRANSITION_PERCENTILE) does_edge_have_high_probability = edge_probabilities_array >= TRANSITION_PERCENTAGE_THRESHOLD # is_edge_frequent = np.logical_and(does_edge_occur_often, does_edge_have_high_probability) edge_filter = graph.new_edge_property(str("boolean"), vals=does_edge_have_high_probability) graph.set_edge_filter(edge_filter) # Create a new filename for the output that includes the index of the version of # data that was used when drawing it. output_filename = make_dump_filename( __name__ + "_compute_index_" + str(compute_index), "." + output_format, ) # Draw the graph gt.graphviz_draw( graph, size=(30, 15), # resulting image should be about 30cm by 15cm overlap=False, # nodes should not be drawn on top of each other elen=.5, # edges should be ~1/2 in. long penwidth=edge_widths, # edge thickness # vsize=vertex_sizes, # vertex sizes vsize=MINIMUM_VERTEX_SIZE, # vertex sizes layout='fdp', # this layout engine lets us set positions of start and end pin=vertex_pin_property, # pins the positions for some vertices pos=vertex_position_property, # set the position of some vertices vcolor=vertex_color_property, # For reference about graphviz vertex and edge properties in the next # two dictionaries, see this page: # http://www.graphviz.org/doc/info/attrs.html gprops={ 'rankdir': "LR", # layout the vertices from left to right 'splines': 'curved', }, vprops={ # 'fontsize': vertex_font_sizes,# size of labels 'fontsize': MINIMUM_FONT_SIZE, # size of labels 'label': vertex_labels, # text of labels 'shape': 'circle', 'fixedsize': 'shape', # don't scale vertices to fit text (looks weird) }, eprops={ 'xlabel': edge_labels, # xlabel (instead of label) distances labels from edges 'fontsize': 6.0, # Surprisingly, we have to explicitly set these arrow properties # to make sure taht edges appear with a direction 'arrowhead': 'normal', 'dir': 'forward', }, output=output_filename, output_format=output_format, )
return 0.001 g, bm = gt.random_graph(100, lambda: poisson(10), directed=False, block_membership=lambda: randint(50), vertex_corr=corr) gt.graph_draw(g, vertex_fill_color=bm, edge_color="black", output="blockmodel.pdf") print(g.num_vertices(), g.num_edges()) state = gt.minimize_nested_blockmodel_dl(g, deg_corr=True) t = gt.get_hierarchy_tree(state) tree,label,order = t bstack = state.get_bstack() gt.graphviz_draw(tree,layout="sfdp",output="blockmodelhierarchytree.pdf") ''' graph_tool.draw.draw_hierarchy(bstack[1]) gt.graphviz_draw(bstack[3]) for v in g.vertices(): print(v.properties) '''