')
# attributes.append(f'')
attributes.append(f'| Type | {net["type"]} | ')
attributes.append(f'| Bidirectional | {"true" if net["bidirectional"] else "false"} | ')
attributes.append(f'| Size | {net["size"]} | ')
attributes.append(f'| Readers | {net["readers"]} | ')
attributes.append(f'| Writers | {net["writers"]} | ')
attributes.append(f' | ')
attributes.append(' ')
return f'"{name}" [label=<{"".join(attributes)}> shape=none fillcolor="{bgcolor}" margin="0.05"]'
def node_label(element):
attributes = ['']
short_name = element["name"]
if short_name.startswith('ROOT/'):
short_name = short_name[5:]
# Header
attributes.append(f'| {html.escape(short_name)} | ')
# Nets
attributes.append(f'')
if 'nets' in element and element['nets']:
nets = ''.join(f'| {str(i)} | ' for i,net in enumerate(element['nets']))
attributes.append(f'{nets}')
else:
attributes.append('| ∅ | ')
attributes.append(f' | ')
# Args
attributes.append(f'')
if 'args' in element and element['args']:
args = ''.join(f'| {html.escape(shorten(v["value"]))} | ' for v in element['args'])
attributes.append(f'{args}')
else:
attributes.append('| ∅ | ')
attributes.append(f' | ')
# Kwargs
attributes.append(f'')
if 'kwargs' in element and element['kwargs']:
kwargs = ''.join(f'| {html.escape(k)} | {html.escape(shorten(v["value"]))} | ' for k, v in element['kwargs'].items())
attributes.append(f'{kwargs}')
else:
attributes.append('| ∅ | ')
attributes.append(f' | ')
attributes.append(' ')
return f'"{element["name"]}" [label=<{"".join(attributes)}> shape=none margin="0"]'
def edge(element):
if 'nets' in element:
for i,net in enumerate(element['nets']):
# yield f'"{element["name"]}":"{str(i)}" -- "{net}":"head"'
yield f'"{element["name"]}":"{str(i)}" -> "{net}":"middle"[ arrowhead = none ]'
def generate_graph(description):
result = []
result.append('digraph G {')
# result.append(' fontname="Helvetica,Arial,sans-serif"')
# result.append(' node [fontname="Helvetica,Arial,sans-serif"]')
# result.append(' edge [fontname="Helvetica,Arial,sans-serif"]')
result.append(' fontname="Cascadia,Courrier,mono"')
result.append(' node [fontname="Cascadia,Courrier,mono"]')
result.append(' edge [fontname="Cascadia,Courrier,mono"]')
result.append(' layout="sfdp"')
result.append(' overlap=false')
result.append(' splines=curved')
for name, net in description["nets"].items():
result.append(' ' + edge_label(name, net))
for element in description["elements"]:
result.append(' ' + node_label(element))
result.extend(' ' + e for e in edge(element))
result.append('}')
return '\n'.join(result)
def draw_graph(json_file, out_file):
with open(json_file) as f:
description = json.load(f)
dot_src = generate_graph(description)
# print(dot_src)
graph = graphviz.Source(dot_src)
graph.render(outfile=out_file)
print(f'Results written to {out_file}')
def main():
try:
json_file = sys.argv[1]
except IndexError:
print('First and only argument should be a JSON description of the circuit')
try:
out_file = sys.argv[2]
except IndexError:
out_file = json_file + ".png"
with open(json_file) as f:
description = json.load(f)
dot_src = generate_graph(description)
# print(dot_src)
graph = graphviz.Source(dot_src)
graph.render(outfile=out_file)
print(f'Results written to {out_file}')
if __name__ == '__main__':
main()
|