def render_rg(rg): """ Render an ivy_arg.AnalysisGraph object """ g = CyElements() # add nodes for states for s in rg.states: if s.is_bottom(): classes = ['bottom_state'] else: classes = ['state'] g.add_node( obj=s, label=str(s.id), classes=classes, short_info=str(s.id), long_info=[str(x) for x in s.clauses.to_open_formula()], locked=True, ) # add edges for transitions for source, op, label, target in rg.transitions: if label == 'join': classes = ['transition_join'] label = 'join' info = 'join' else: classes = ['transition_action'] # Curly braces don't survive dot (even if they balance). We work around this by replacing them with digraphs # and then fixing it later by modding the text of the canvas items. Also, we want our code labels to be left # justified, so we end the lines with \l, which dot recognizes. Note the backslashes are escaped, since this # is *not* a special character, it is a two-character sequence. label = label.replace('}',']-').replace('{','-[') label = label.replace('\n','\\l')+'\\l' info = str(op) g.add_edge( op, source, target, label=label, classes=classes, short_info=info, long_info=info, ) # add edges for covering for covered, by in rg.covering: g.add_edge( 'cover', covered, by, label='', classes=['cover'], short_info='', long_info='', events=[], actions=[], ) return g
def render_concept_graph(widget): """ Render the result of concept_alpha to an annotated graph. The graph is represented using Python objects compatible with Cytoscape's JSON format. TODO: maybe this should be a method of ConceptSessionWidget """ concept_session = widget.concept_session a = dict(concept_session.abstract_value) domain = concept_session.domain # treat custom_edge_info and custom_node_label custom = set() for tag in a.keys(): if tag[0].startswith('custom_'): not_custom_tag = (tag[0][len('custom_'):], ) + tag[1:] a[not_custom_tag] = a[tag] custom.add(tag[2:]) # get information from the abstract value nodes = set() node_labels = set() edges = set() for tag in a: if tag[0] == 'node_info': nodes.add(tag[2]) elif tag[0] == 'edge_info': nodes.add(tag[3]) nodes.add(tag[4]) edges.add(tag[2:]) elif tag[0] == 'node_label': nodes.add(tag[2]) node_labels.add(tag[3]) nodes = sorted(nodes) node_labels = sorted(node_labels) edges = sorted(edges) g = CyElements() # add nodes non_existing_nodes = set() for node in nodes: if a[('node_info', 'none', node)]: non_existing_nodes.add(node) classes = ['non_existing'] class_disp = 'non existing' elif a[('node_info', 'at_least_one', node)] and a[('node_info', 'at_most_one', node)]: classes = ['exactly_one'] class_disp = 'exactly one' elif a[('node_info', 'at_least_one', node)]: classes = ['at_least_one'] class_disp = 'at least one' elif a[('node_info', 'at_most_one', node)]: classes = ['at_most_one'] class_disp = 'at most one' else: classes = ['node_unknown'] class_disp = 'maybe non existing, maybe more than one' possible_splits = [] label_lines = [] for label_name in node_labels: if ('node_label', 'node_necessarily', node, label_name) not in a: # label not present, probably not well sorted, skip continue possible_splits.append(label_name) if a[('node_label', 'node_necessarily', node, label_name)]: k = 'node_necessarily' elif a[('node_label', 'node_necessarily_not', node, label_name)]: k = 'node_necessarily_not' else: k = 'node_maybe' if (widget.node_label_display_checkboxes[label_name][k].value is False and (node, label_name) not in custom): # don't add invisible labels continue lab = widget.concept_label(domain.concepts[label_name]) if k == 'node_maybe': lab += '?' elif k == 'node_necessarily_not': lab = '~' + lab label_lines.append(lab) disp = widget.node_label(domain.concepts[node]) label = '\n'.join([disp] + label_lines) info = '\n'.join([ node, str(domain.concepts[node]), class_disp, ] + label_lines) cluster = domain.concepts[node].sort.name if hasattr(widget, 'apply_structure_renaming'): label = widget.apply_structure_renaming(label) info = widget.apply_structure_renaming(info) actions = [(widget.apply_structure_renaming(action[0]), ) + tuple(action[1:]) for action in actions] shape = get_shape(node) g.add_node( obj=node, label=label, classes=classes, short_info=info, long_info=info, events=[], locked=True, cluster=cluster, shape=shape, ) # add edges hidden_by_transitive = get_transitive_reduction(widget, a, edges) for edge, source, target in edges: x = (edge, source, target) if (x in hidden_by_transitive and x not in custom): # don't draw edges hidden by transitive reduction continue if (source in non_existing_nodes or target in non_existing_nodes): # don't draw edges to non-existing nodes continue classes = [] if a[('edge_info', 'none_to_none') + x]: classes.append('none_to_none') elif a[('edge_info', 'all_to_all') + x]: classes.append('all_to_all') else: classes.append('edge_unknown') if (widget.edge_display_checkboxes[edge][classes[0]].value is False and x not in custom): # don't add invisible edges continue if not a[('edge_info', 'none_to_none') + x]: classes += [ c for c in [ 'total', 'functional', 'surjective', 'injective', ] if a.get(('edge_info', c) + x) ] # TODO: custom edge labels labels = ['{}({}, {}):'.format(edge, source, target)] labels += [ c.replace('_', ' ') for c in [ 'none_to_none', 'all_to_all', 'total', 'functional', 'surjective', 'injective', ] if a.get(('edge_info', c) + x) ] if hasattr(widget, 'apply_structure_renaming'): labels[0] = widget.apply_structure_renaming(labels[0]) transitive = widget.edge_display_checkboxes[edge]['transitive'].value g.add_edge( edge, source, target, label=edge, classes=classes, short_info='\n'.join(labels), long_info=[str(domain.concepts[edge])] + labels[1:], events=[], transitive=transitive, ) return g
def render_concept_graph(widget): """ Render the result of concept_alpha to an annotated graph. The graph is represented using Python objects compatible with Cytoscape's JSON format. TODO: maybe this should be a method of ConceptSessionWidget """ concept_session = widget.concept_session a = dict(concept_session.abstract_value) domain = concept_session.domain # treat custom_edge_info and custom_node_label custom = set() for tag in a.keys(): if tag[0].startswith('custom_'): not_custom_tag = (tag[0][len('custom_'):],) + tag[1:] a[not_custom_tag] = a[tag] custom.add(tag[2:]) # get information from the abstract value nodes = set() node_labels = set() edges = set() for tag in a: if tag[0] == 'node_info': nodes.add(tag[2]) elif tag[0] == 'edge_info': nodes.add(tag[3]) nodes.add(tag[4]) edges.add(tag[2:]) elif tag[0] == 'node_label': nodes.add(tag[2]) node_labels.add(tag[3]) nodes = sorted(nodes) node_labels = sorted(node_labels) edges = sorted(edges) g = CyElements() # add nodes non_existing_nodes = set() for node in nodes: if a[('node_info', 'none', node)]: non_existing_nodes.add(node) classes = ['non_existing'] class_disp = 'non existing' elif a[('node_info', 'at_least_one', node)] and a[('node_info', 'at_most_one', node)]: classes = ['exactly_one'] class_disp = 'exactly one' elif a[('node_info', 'at_least_one', node)]: classes = ['at_least_one'] class_disp = 'at least one' elif a[('node_info', 'at_most_one', node)]: classes = ['at_most_one'] class_disp = 'at most one' else: classes = ['node_unknown'] class_disp = 'maybe non existing, maybe more than one' possible_splits = [] label_lines = [] for label_name in node_labels: if ('node_label', 'node_necessarily', node, label_name) not in a: # label not present, probably not well sorted, skip continue possible_splits.append(label_name) if a[('node_label', 'node_necessarily', node, label_name)]: k = 'node_necessarily' elif a[('node_label', 'node_necessarily_not', node, label_name)]: k = 'node_necessarily_not' else: k = 'node_maybe' if (widget.node_label_display_checkboxes[label_name][k].value is False and (node, label_name) not in custom): # don't add invisible labels continue lab = widget.concept_label(domain.concepts[label_name]) if k == 'node_maybe': lab += '?' elif k == 'node_necessarily_not': lab = '~' + lab label_lines.append(lab) disp = widget.node_label(domain.concepts[node]) label = '\n'.join([disp] + label_lines) info = '\n'.join( [ node, str(domain.concepts[node]), class_disp, ] + label_lines ) cluster = domain.concepts[node].sort.name if hasattr(widget, 'apply_structure_renaming'): label = widget.apply_structure_renaming(label) info = widget.apply_structure_renaming(info) actions = [ (widget.apply_structure_renaming(action[0]), ) + tuple(action[1:]) for action in actions ] shape = get_shape(node) g.add_node( obj=node, label=label, classes=classes, short_info=info, long_info=info, events=[], locked=True, cluster=cluster, shape=shape, ) # add edges hidden_by_transitive = get_transitive_reduction(widget, a, edges) for edge, source, target in edges: x = (edge, source, target) if (x in hidden_by_transitive and x not in custom): # don't draw edges hidden by transitive reduction continue if (source in non_existing_nodes or target in non_existing_nodes): # don't draw edges to non-existing nodes continue classes = [] if a[('edge_info', 'none_to_none') + x]: classes.append('none_to_none') elif a[('edge_info', 'all_to_all') + x]: classes.append('all_to_all') else: classes.append('edge_unknown') if (widget.edge_display_checkboxes[edge][classes[0]].value is False and x not in custom): # don't add invisible edges continue if not a[('edge_info', 'none_to_none') + x]: classes += [ c for c in [ 'total', 'functional', 'surjective', 'injective', ] if a.get(('edge_info', c) + x) ] # TODO: custom edge labels labels = ['{}({}, {}):'.format(edge, source, target)] labels += [ c.replace('_', ' ') for c in [ 'none_to_none', 'all_to_all', 'total', 'functional', 'surjective', 'injective', ] if a.get(('edge_info', c) + x) ] if hasattr(widget, 'apply_structure_renaming'): labels[0] = widget.apply_structure_renaming(labels[0]) transitive = widget.edge_display_checkboxes[edge]['transitive'].value g.add_edge( edge, source, target, label=edge, classes=classes, short_info='\n'.join(labels), long_info=[str(domain.concepts[edge])] + labels[1:], events=[], transitive = transitive, ) return g
def render_rg(rg): """ Render an ivy_arg.AnalysisGraph object """ g = CyElements() # add nodes for states for s in rg.states: if s.is_bottom(): classes = ['bottom_state'] else: classes = ['state'] g.add_node( obj=s, label=str(s.id), classes=classes, short_info=str(s.id), long_info=[str(x) for x in s.clauses.to_open_formula()], locked=True, ) # add edges for transitions for source, op, label, target in rg.transitions: if label == 'join': classes = ['transition_join'] label = 'join' info = 'join' else: classes = ['transition_action'] # Curly braces don't survive dot (even if they balance). We work around this by replacing them with digraphs # and then fixing it later by modding the text of the canvas items. Also, we want our code labels to be left # justified, so we end the lines with \l, which dot recognizes. Note the backslashes are escaped, since this # is *not* a special character, it is a two-character sequence. label = label.replace('}', ']-').replace('{', '-[') label = label.replace('\n', '\\l') + '\\l' info = str(op) g.add_edge( op, source, target, label=label, classes=classes, short_info=info, long_info=info, ) # add edges for covering for covered, by in rg.covering: g.add_edge( 'cover', covered, by, label='', classes=['cover'], short_info='', long_info='', events=[], actions=[], ) return g