def assert_have_dot2tex(): """ Tests whether ``dot2tex`` >= 2.8.7 and graphviz are installed and functional, and raises an error otherwise EXAMPLES:: sage: sage.graphs.dot2tex_utils.assert_have_dot2tex() # optional - dot2tex graphviz """ check_error_string = """ An error occurs while testing the dot2tex installation. Please see :meth:`sage.graphs.generic_graph.GenericGraph.layout_graphviz` and check the installation of graphviz and the dot2tex spkg. For support, please contact <sage-combinat-devel at googlegroups.com>. """ import_error_string = """ An error occurred when importing dot2tex. Please see :meth:`sage.graphs.generic_graph.GenericGraph.layout_graphviz` for installation instructions. """ try: import dot2tex except ImportError: print(import_error_string) raise # re-raise current exception else: if dot2tex.dot2tex("graph {}", format="positions") != {}: raise RuntimeError(check_error_string)
def savedotfile(vertices): fh = open("output/hypergraphhasse.dot","w") #L = genhypergraphlattice(vertices) #dotstring = genhypergraphhasse(L) ghc=genhypergraphs([1,2,3,4]) chg = filteracyclic(ghc,4) dotstring = genhypergraphhasse(chg) fh.write("%s" % dotstring) fh.close() texcode = dot2tex.dot2tex(dotstring, format='tikz', crop=True) texcode = re.sub(r"\{\}","empty",texcode) # using node name {} # produces a latex error fh = open("output/hypergraphhasse.tex","w") fh.write("%s" % texcode) fh.close() subprocess.call("cd output && latexmk -pdf hypergraphhasse.tex",shell=True) subprocess.call("cd output && rm hypergraphhasse.log \ hypergraphhasse.fdb_latexmk \ hypergraphhasse.fls \ hypergraphhasse.aux",shell=True) subprocess.call("evince output/hypergraphhasse.pdf &",shell=True) subprocess.call("pdf2svg output/hypergraphhasse.pdf \ output/hypergraphhasse.svg",shell=True) # subprocess.call("dot -Tps output/hypergraphhasse.dot -o output/hypergraphhasse.ps",shell=True) # subprocess.call("epstopdf output/hypergraphhasse.ps",shell=True) # subprocess.call("evince output/hypergraphhasse.pdf",shell=True) return dotstring
def _diagrams__graphviz(ctx, src, **kargs): ''' Take a dot graph and recoded as a tikz graph. Source should be a graph wrapped in a fenced-code block: src == """ ```foo digraph G { a_1-> a_2 -> a_3 -> a_1; } ``` """ Return a Latex literal. Arguments are passed to dot2tex. ''' src = strip_fenced_code_block_markers(src) # Ensure that codeonly or figonly is True. The former # generates Tikz code without an environment (so we could keep # adding Tikz code) and the latter includes the environment. # One of them must be set otherwise dot2tex will generate # a full Tex document. if not kargs.get('codeonly', False): kargs['figonly'] = True tex = dot2tex.dot2tex(src, **kargs) return as_markup_latex(tex)
def test_head_and_tail_labels(self): """Test for issue 12""" graph = "digraph { a -> b [headlabel=HEADLABEL,taillabel=TAILLABEL,label=LABEL] }" code = dot2tex.dot2tex(graph, format="pgf", autosize=True) self.assertTrue('HEADLABEL' in code) self.assertTrue('LABEL' in code) self.assertTrue('TAILLABEL' in code)
def write_to_tex(self, fname_graph): try: import dot2tex except: logger.warn('dot2tex missing. Plasma graph will not be ' 'generated.') return temp_fname = tempfile.NamedTemporaryFile().name self.write_to_dot(temp_fname) dot_string = open(temp_fname).read() open(fname_graph, 'w').write(dot2tex.dot2tex(dot_string, texmode='raw')) for line in fileinput.input(fname_graph, inplace=1): print(line.replace( r'\documentclass{article}', r'\documentclass[class=minimal,border=20pt]{standalone}'), end='') for line in fileinput.input(fname_graph, inplace=1): print(line.replace(r'\enlargethispage{100cm}', ''), end='')
def test_russian(self): testgraph = """digraph {AAA [label="ЯЯЯ"];}""" source = dot2tex.dot2tex(testgraph, debug=True, format='tikz', codeonly=True) self.assertTrue(source.find("{ЯЯЯ}") > 0, "Found %s" % source)
def test_not_numeral_in_label(self): testgraph = """ digraph { a[label="1.2.3.4"] ; b } """ source = dot2tex.dot2tex(testgraph, debug=True, figonly=True, format='tikz', autosize=True) self.failUnless(r'{1.2.3.4}' in source)
def _document_fe_graph(self) -> None: """Add FE execution graphs into the traceability document. """ with self.doc.create(Section("FastEstimator Architecture")): for mode in self.system.pipeline.data.keys(): scheduled_items = self.system.pipeline.get_scheduled_items( mode) + self.system.network.get_scheduled_items(mode) + self.system.traces signature_epochs = get_signature_epochs(scheduled_items, total_epochs=self.system.epoch_idx, mode=mode) epochs_with_data = self.system.pipeline.get_epochs_with_data(total_epochs=self.system.epoch_idx, mode=mode) if set(signature_epochs) & epochs_with_data: self.doc.append(NoEscape(r'\FloatBarrier')) with self.doc.create(Subsection(mode.capitalize())): for epoch in signature_epochs: if epoch not in epochs_with_data: continue self.doc.append(NoEscape(r'\FloatBarrier')) with self.doc.create( Subsubsection(f"Epoch {epoch}", label=Label(Marker(name=f"{mode}{epoch}", prefix="ssubsec")))): diagram = self._draw_diagram(mode, epoch) ltx = d2t.dot2tex(diagram.to_string(), figonly=True) args = Arguments(**{'max width': r'\textwidth, max height=0.9\textheight'}) args.escape = False with self.doc.create(Center()): with self.doc.create(AdjustBox(arguments=args)) as box: box.append(NoEscape(ltx))
def test_russian2(self): testgraph = """digraph {AAA [label=aaЯЯЯ];}""" source = dot2tex.dot2tex(testgraph, debug=True, format='tikz', codeonly=True) self.failUnless(source.find("{aaЯЯЯ}") > 0, "Found %s" % source)
def test_name_with_parantheses(self): testgraph = """ digraph { { "F(K)/R-1"}} """ source = dot2tex.dot2tex(testgraph, debug=True, figonly=True, format='tikz') self.failUnless(r'\node (F{K}/R-1)' in source)
def assert_have_dot2tex(): """ Tests whether ``dot2tex`` >= 2.8.7 and graphviz are installed and functional, and raises an error otherwise EXAMPLES:: sage: sage.graphs.dot2tex_utils.assert_have_dot2tex() # optional - dot2tex graphviz """ check_error_string = """ An error occurs while testing the dot2tex installation. Please see :meth:`sage.graphs.generic_graph.GenericGraph.layout_graphviz` and check the installation of graphviz and the dot2tex spkg. For support, please contact <sage-combinat-devel at googlegroups.com>. """ import_error_string = """ An error occured when importing dot2tex. Please see :meth:`sage.graphs.generic_graph.GenericGraph.layout_graphviz` for installation instructions. """ try: import dot2tex except ImportError as e: print import_error_string raise # re-raise current exception else: if dot2tex.dot2tex("graph {}", format = "positions") != {}: raise RuntimeError(check_error_string)
def tex_from_dfa(dfa): """Computes a representation of dfa in the TEX-format.""" return _postprocess_tex(dot2tex( dot_from_dfa(dfa), format='tikz', crop=True, program='dot', figonly=True ))
def createGraphTikz(st, eL): def replaceChars(s): return (s.replace('#', '\#').replace('#', '\\#').replace( u'è', 'e\'').replace(u'é', 'e\'').replace(u'ù', 'u\'').replace( u'ì', 'i\'').replace(u'à', 'a\'').replace(u'ò', 'o\'').replace(u'’', '\'')) G = nx.DiGraph() nodes = list(i for i in range(len(st))) edges = list((st.index(t[0]), st.index(t[1]), t[2]) for t in eL) G.add_nodes_from(nodes) G.add_weighted_edges_from(edges) G.graph['edge'] = {'arrowsize': '1', 'splines': 'curved'} G.graph['graph'] = {'scale': '1000000'} A = to_agraph(G) A.layout('dot') for i, s in enumerate(st): n = A.get_node(i) n.attr['label'] = replaceChars(s) for triplet in edges: e = A.get_edge(triplet[0], triplet[1]) e.attr['label'] = toLatexProb(triplet[2]) A.draw('image.png') texcode = dot2tex.dot2tex(A.to_string(), format='tikz', crop=True) regEx = re.compile(r'(\\begin\{tikzpicture\})(.*?)(\\end\{tikzpicture\})', re.M | re.DOTALL) return ''.join(regEx.findall(texcode)[0])
def test_tikz118option(self): source = dot2tex.dot2tex(testgraph, debug=True, format='tikz', pgf118=True) self.failUnless(source.find("\usepackage{pgflibrarysnakes}") >= 0) self.failIf(source.find("\usetikzlibrary") >= 0) self.failIf(source.find("line join=bevel") >= 0)
def test_multiline_autosize(self): """There should be three lines""" test_graph = r""" digraph { a -> b [label="line1\nline2\nline3"] } """ code = dot2tex.dot2tex(test_graph, codeonly=True, format="tikz", autosize=True) self.assertGreaterEqual(code.count("node {line"), 3)
def graph_to_tikz(g): agraph = nx.drawing.nx_agraph.to_agraph(g) return dot2tex.dot2tex( agraph.to_string(), figonly=True, texmode="math", crop=True, autosize=True, )
def test_multiline(self): """There should be three lines""" test_graph = r""" digraph { a -> b [label="line1\nline2\nline3"] } """ code = dot2tex.dot2tex(test_graph, codeonly=True, format="tikz") self.assertGreaterEqual(code.count("node {line"), 3)
def test_small_label(self): testgraph = """ digraph { "objects" [label="sdfsdf", texlbl="$1$"]; } """ source = dot2tex.dot2tex(testgraph, debug=True, autosize=True, figonly=True, format='tikz') self.failUnless('$1$' in source)
def test_name_with_parantheses(self): testgraph = """ digraph { { "F(K)/R-1"}} """ source = dot2tex.dot2tex(testgraph, debug=True, figonly=True, format='tikz') self.assertTrue(r'\node (F{K}/R-1)' in source)
def test_draw_statements(self): """There should be at least two \\draw statements""" test_graph = r""" digraph { start[shape="box", style=rounded]; } """ code = dot2tex.dot2tex(test_graph, codeonly=True) self.assertGreaterEqual(code.count("\\draw"), 2) self.assertTrue("controls" in code)
def test_d2toptions(self): testgraph = """ digraph SSA { d2toptions = "--graphstyle=insertedstyle"; B } """ source = dot2tex.dot2tex(testgraph, debug=True) self.failUnless(source.find("insertedstyle") >= 0)
def test_semicolon(self): """Test for issue 5""" testgraph1 = """ digraph example { a -> b a -> c {rank=same; b;c} }""" testgraph2 = """ digraph example { a -> b; a -> c; {rank=same; b;c} }""" source1 = dot2tex.dot2tex(testgraph1, figonly=True, format='tikz', autosize=True) source2 = dot2tex.dot2tex(testgraph2, figonly=True, format='tikz', autosize=True) self.failUnless(source1 == source2)
def test_not_numeral_in_label(self): testgraph = """ digraph { a[label="1.2.3.4"] ; b } """ source = dot2tex.dot2tex(testgraph, debug=True, figonly=True, format='tikz', autosize=True) self.assertTrue(r'{1.2.3.4}' in source)
def test_d2tcommented(self): testgraph = """ digraph SSA { //d2toptions = "--graphstyle=insertedstyle"; B } """ source = dot2tex.dot2tex(testgraph, debug=True) self.assertFalse(source.find("insertedstyle") >= 0)
def test_parsing2(self): """Should not throw a ParseException""" test_graph = r""" digraph G { node [shape="circle"]; a -> b -> 3 -> -4 -> a; } """ try: code = dot2tex.dot2tex(test_graph, codeonly=True, format="tikz") except ParseException: self.fail("Failed to parse graph")
def test_single_line_preamble(self): test_graph = """ digraph { d2tdocpreamble = "\usepackage{amssymb} \usetikzlibrary{arrows, automata}"; { A -> B -> C; } } """ code = dot2tex.dot2tex(test_graph, format="tikz") self.assertTrue(r"\usetikzlibrary{arrows, automata}" in code)
def test_single_line_preamble(self): test_graph = r""" digraph { d2tdocpreamble = "\usepackage{amssymb} \usetikzlibrary{arrows, automata}"; { A -> B -> C; } } """ code = dot2tex.dot2tex(test_graph, format="tikz") self.assertTrue(r"\usetikzlibrary{arrows, automata}" in code)
def test_include_4(self): test_graph = """ digraph { "objects" [label="sdfsdf", texlbl="\input{dymmyfilename.dot}"]; } """"" try: code = dot2tex.dot2tex(test_graph) except IOError: self.fail("Tried to load external dot file")
def test_include_4(self): test_graph = r""" digraph { "objects" [label="sdfsdf", texlbl="\input{dymmyfilename.dot}"]; } """ "" try: code = dot2tex.dot2tex(test_graph) except IOError: self.fail("Tried to load external dot file")
def test_point_shape(self): """Nodes with the point shape should not have labels""" testgraph = r""" digraph G { { node[shape=point] a-> b-> c -> a; } e -> a; a [label="dummy"] } """ code = dot2tex.dot2tex(testgraph, format="tikz") self.assertFalse("dummy" in code)
def test_semicolon(self): """Test for issue 5""" testgraph1 = """ digraph example { a -> b a -> c {rank=same; b;c} }""" testgraph2 = """ digraph example { a -> b; a -> c; {rank=same; b;c} }""" source1 = dot2tex.dot2tex(testgraph1, figonly=True, format='tikz', autosize=True) source2 = dot2tex.dot2tex(testgraph2, figonly=True, format='tikz', autosize=True) self.assertEqual(source1, source2)
def test_multi_line_preamble(self): test_graph = """ digraph { d2tdocpreamble = " % My preamble \usepackage{amssymb}"; { A -> B -> C; } } """ code = dot2tex.dot2tex(test_graph, format="tikz") self.assertTrue(r"% My preamble" in code)
def test_point_shape(self): """Nodes with the point shape should not have labels""" testgraph = """ digraph G { { node[shape=point] a-> b-> c -> a; } e -> a; a [label="dummy"] } """ code = dot2tex.dot2tex(testgraph, format="tikz") self.failIf("dummy" in code)
def test_multi_line_preamble(self): test_graph = r""" digraph { d2tdocpreamble = " % My preamble \usepackage{amssymb}"; { A -> B -> C; } } """ code = dot2tex.dot2tex(test_graph, format="tikz") self.assertTrue(r"% My preamble" in code)
def test_floating_point_coordinates(self): testxdotgraph = r""" digraph G { node [label="\N"]; graph [bb="0,0,127.21,49.639", _draw_="c 9 -#ffffffff C 9 -#ffffffff P 4 0 -1 0 50 128 50 128 -1 ", xdotversion="1.2"]; a [pos="28,30.139", width="0.75", height="0.51389", _draw_="c 9 -#000000ff e 28 30 27 18 ", _ldraw_="F 14.000000 11 -Times-Roman c 9 -#000000ff T 28 25 0 9 1 -a "]; b [pos="99.21,19.5", width="0.75", height="0.51389", _draw_="c 9 -#000000ff e 99 20 27 18 ", _ldraw_="F 14.000000 11 -Times-Roman c 9 -#000000ff T 99 15 0 9 1 -b "]; a -> b [pos="e,72.434,23.5 54.516,26.177 57.076,25.795 59.704,25.402 62.341,25.008", _draw_="c 9 -#000000ff B 4 55 26 57 26 60 25 62 25 ", _hdraw_="S 5 -solid c 9 -#000000ff C 9 -#000000ff P 3 63 28 72 24 62 22 "]; } """ positions = dot2tex.dot2tex(testxdotgraph, format='positions') self.assertEqual(type(positions), dict) self.assertEqual(type(positions['a'][0]), float) self.assertEqual(type(positions['b'][0]), float)
def test_floating_point_coordinates(self): testxdotgraph = """ digraph G { node [label="\N"]; graph [bb="0,0,127.21,49.639", _draw_="c 9 -#ffffffff C 9 -#ffffffff P 4 0 -1 0 50 128 50 128 -1 ", xdotversion="1.2"]; a [pos="28,30.139", width="0.75", height="0.51389", _draw_="c 9 -#000000ff e 28 30 27 18 ", _ldraw_="F 14.000000 11 -Times-Roman c 9 -#000000ff T 28 25 0 9 1 -a "]; b [pos="99.21,19.5", width="0.75", height="0.51389", _draw_="c 9 -#000000ff e 99 20 27 18 ", _ldraw_="F 14.000000 11 -Times-Roman c 9 -#000000ff T 99 15 0 9 1 -b "]; a -> b [pos="e,72.434,23.5 54.516,26.177 57.076,25.795 59.704,25.402 62.341,25.008", _draw_="c 9 -#000000ff B 4 55 26 57 26 60 25 62 25 ", _hdraw_="S 5 -solid c 9 -#000000ff C 9 -#000000ff P 3 63 28 72 24 62 22 "]; } """ positions = dot2tex.dot2tex(testxdotgraph, format='positions') self.failUnless(type(positions) == dict) self.failUnless(type(positions['a'][0]) == float) self.failUnless(type(positions['b'][0]) == float)
def have_dot2tex(): """ Returns whether ``dot2tex`` >= 2.8.7 and graphviz are installed and functional EXAMPLES:: sage: sage.graphs.dot2tex_utils.have_dot2tex() # optional - dot2tex graphviz True sage: sage.graphs.dot2tex_utils.have_dot2tex() in [True, False] True """ try: import dot2tex # Test for this required feature from dot2tex 2.8.7 return dot2tex.dot2tex("graph {}", format="positions") == {} except (Exception, SystemExit): return False
def have_dot2tex(): """ Returns whether ``dot2tex`` >= 2.8.7 and graphviz are installed and functional EXAMPLES:: sage: sage.graphs.dot2tex_utils.have_dot2tex() # optional - dot2tex graphviz True sage: sage.graphs.dot2tex_utils.have_dot2tex() in [True, False] True """ try: import dot2tex # Test for this required feature from dot2tex 2.8.7 return dot2tex.dot2tex("graph {}", format = "positions") == {} except (Exception, SystemExit): return False
def write_to_tex(self, fname_graph, fname_formulae): try: import dot2tex except ImportError: raise ImportError("dot2tex is needed for method'write_to_tex'") temp_fname = tempfile.NamedTemporaryFile().name self.write_to_dot(temp_fname) dot_string = open(temp_fname).read() open(fname_graph, "w").write(dot2tex.dot2tex(dot_string, texmode="raw")) for line in fileinput.input(fname_graph, inplace=1): print line.replace("\documentclass{article}", "\documentclass[class=minimal,border=20pt]{standalone}"), for line in fileinput.input(fname_graph, inplace=1): print line.replace("\enlargethispage{100cm}", ""),
def totikz(dot_input:str, math_trans=make_math_trans(), coef=BP_TO_CM) -> str: '''Translate a dot-string into `tikz` code editable by Tikzit.''' raw = d2t.dot2tex(dot_input, format='tikz', prog='neato', codeonly='True') code = math_trans(raw).split('\n') label_count = 0 node_lines, edge_lines = [], [] for line in code[1:-1]: if line.strip().startswith('\\node'): node_lines.append(node_line_transform(line, coef)) elif line.strip().startswith('\\draw') and 'node' in line: node_lines.append(label_line_transform(line, label_count, coef)) label_count += 1 elif line.strip().startswith('\\draw') and 'node' not in line: edge_lines.append(edge_line_transform(line)) return in_frame(node_lines, edge_lines)
def write_to_tex(self, fname_graph): try: import dot2tex except: logger.warn("dot2tex missing. Plasma graph will not be " "generated.") return temp_fname = tempfile.NamedTemporaryFile().name self.write_to_dot(temp_fname) dot_string = open(temp_fname).read() open(fname_graph, "w").write(dot2tex.dot2tex(dot_string, texmode="raw")) for line in fileinput.input(fname_graph, inplace=1): print line.replace("\documentclass{article}", "\documentclass[class=minimal,border=20pt]{standalone}"), for line in fileinput.input(fname_graph, inplace=1): print line.replace("\enlargethispage{100cm}", ""),
def write_to_tex(self, fname_graph, fname_formulae): try: import dot2tex except ImportError: raise ImportError('dot2tex is needed for method\'write_to_tex\'') temp_fname = tempfile.NamedTemporaryFile().name self.write_to_dot(temp_fname) dot_string = open(temp_fname).read() open(fname_graph, 'w').write(dot2tex.dot2tex(dot_string, texmode='raw')) for line in fileinput.input(fname_graph, inplace = 1): print line.replace('\documentclass{article}', '\documentclass[class=minimal,border=20pt]{standalone}'), for line in fileinput.input(fname_graph, inplace = 1): print line.replace('\enlargethispage{100cm}', ''),
def write_to_tex(self, fname_graph, fname_formulae): try: import dot2tex except: logger.warn('dot2tex missing. Plasma graph will not be ' 'generated.') return temp_fname = tempfile.NamedTemporaryFile().name self.write_to_dot(temp_fname) dot_string = open(temp_fname).read() open(fname_graph, 'w').write(dot2tex.dot2tex(dot_string, texmode='raw')) for line in fileinput.input(fname_graph, inplace = 1): print line.replace('\documentclass{article}', '\documentclass[class=minimal,border=20pt]{standalone}'), for line in fileinput.input(fname_graph, inplace = 1): print line.replace('\enlargethispage{100cm}', ''),
def gen_tikz_from_model(model): dot = model_to_dot(model) return d2t.dot2tex(dot.to_string(), format='tikz', crop=True)
def main(): global fonts description="This program parses an Arabic text file in order to build a family genealogical tree.\nThe file is analysed line by line, "\ "every line is expected to expand a parent (at the first position) together with his children separated by periods '.'. "\ "If everything works fine, the tree is saved as a figure in pdf format and consequently can be inserted later in other documents "\ "or printed directly. Since the structure is hierarchical, every parent name (except the first) should have been previously mentioned. "\ "In order to highlight (a) special path(s) in the tree, the special names should be marked with (an) asterisk(s) '*' at the beginning "\ "and/or at the end of that special name. For special names you can specify particular styles and/or particular fonts."\ "Every name can be preceded/followed by small comments by separating them by ':'. In such case, the order will be respected, "\ "and the main name should be marked with '-' sign(s) at one/both of its sides if it is not the first.'-' and '*' sign(s) can be safely mixed. "\ "Three typesetting systems are supported at the moment, namely: 'Arabi', 'ArabXeTeX', and 'Polyglossia'. Arabi is simpler and supports less fonts. "\ "With ArabXeTeX or Polyglossia you can use any of your installed fonts, but you need a new version of the 'Preview' package. "\ "Please report any feedback to Mohammed Mediani: [email protected] " usage = "Usage: %prog [options] tree-source-file" parser = OptionParser(usage) parser.set_description(description) parser.add_option("-s", "--style", action="store",type="string", dest="style", help="{straight|square} straight: default style, straight connectors,\rsquare: squared connectors", default="straight") parser.add_option("-o", "--order", action="store",type="string", dest="order", help="{fifo|lifo} fifo: the parent name refers to the last occurence of this name, lifo: the name refers to the earliest occurence, default: fifo", default="fifo") parser.add_option("-f", "--font", action="store",type="string", dest="font", help="Select a specific font. supported fonts for 'pdftex' (in the format: 'code: font name'): {%s}. Available Arabic fonts for 'XeTeX'/'Polyglossia' (Unix only) {%s}" % ("|".join(" %s: %s " % (x, descriptionof(y)) for x, y in fonts.items()), "|".join(available_arabic_fonts())), default="") parser.add_option("-n", "--node-style", action="store",type="string", dest="node_style", help="String describing TikzStyle for the nodes (eg. 'fill=red!20', to get nodes filled with 20% of red). Enclose inside SINGLE quotes if contains spaces or special characters", default="") parser.add_option("-e", "--edge-style", action="store",type="string", dest="edge_style", help="String describing TikzStyle forthe edges (eg. '-diamond, blue' to get zigzagged green edges). Enclose inside SINGLE quotes if contains spaces or special characters", default="") parser.add_option("-N", "--special-node-styles", action="store",type="string", dest="special_styles", help="%s-seprated string of node styles for special nodes in order to highlight a particular path in the tree. The program will cycle through this list and assign styles accordingly to special names. Enclose inside SINGLE quotes if contains spaces or special characters" % separator, default="") parser.add_option("-F", "--special-fonts", action="store",type="string", dest="special_fonts", help="%s-seprated string of fonts for special nodes in order to highlight a particular path in the tree. The program will cycle through this list and assign fonts accordingly to special names. Enclose inside SINGLE quotes if contains spaces or special characters"% separator, default="") parser.add_option("-E", "--special-edge-styles", action="store",type="string", dest="special_edge_styles", help="%s-seprated string of edge styles for special paths in order to highlight a particular path in the tree. The program will cycle through this list and assign styles accordingly to special edges. Enclose inside SINGLE quotes if contains spaces or special characters"%separator, default="") parser.add_option("-d", "--dir", action="store",type="string", dest="dir", help="{BT|TB|LR|RL} direction if the tree. B: bottom, T: top, L: left, R: right", default="tb") parser.add_option("-x", "--texformat", action="store",type="string", dest="tex_format", help="{tikz|pgf} package used to generate the graph in Latex.", default="tikz") parser.add_option("-p", "--node-shape", action="store",type="string", dest="node_shape", help="The shape of nodes {%s}." % "|".join(shapes), default="box") parser.add_option("-P", "--special-node-shape", action="store",type="string", dest="special_node_shapes", help="%s-seprated string of shapes for special nodes. This would allow a node to be more visually attractive. The program will cycle through this list and assign shapes accordingly to special names. Enclose inside SINGLE quotes if contains spaces or special characters" % separator, default="") parser.add_option("-c", "--tex-compiler", action="store",type="string", dest="tex_compiler", help="{pdftex|xetex|polyglo} TeX system. The Arabi typesetting system will be used for 'pdftex', the ArabXeTeX system will be used for 'xetex', and Polyglossia will be used for 'polyglo'", default="pdftex") parser.add_option("-a", "--explicit-orig-anchor", action="store_true", help="Use this flag if the edges start points don't anchor correctly. This adds an explicit anchor in the TeX code.", dest="fix_orig") #, # default="False") parser.add_option("-b", "--explicit-dest-anchor", action="store_true", help="Use this flag if the edges ending points don't anchor correctly. This adds an explicit anchor in the TeX code.", dest="fix_dest")#, # default="False") parser.add_option("-l", "--explicit-node-anchor", action="store_true", help="Use this flag if the nodes in one level don't align correctly. This adds an explicit anchor in the TeX code.", dest="fix_alignments")#, parser.add_option("-u", "--unify-special-paths", action="store_true", help="Use this flag in order to propagate the special styles for one node over all its anscestors. Intersecting special paths cause the style to be changed.", dest="unify_styles")#, parser.add_option("-z", "--normalize", action="store_true", help="Use this flag to normalize the Arabic input text. For instance: all forms of 'Hamza' will be normalized to a single form, 'Tatweel' will be removed, any 'Tashkeel' will be removed, etc", dest="normalize")#, parser.add_option("-i", "--use-indexes", action="store_true", help="In case many similar names occur in the tree and it becomes difficult to choose either 'fifo' or 'lifo', names can be numerically indexed by pre/suf-fixing them with digits to avoid conflicts. If this flag is used, the indexes will be automatically removed before writing the names out.", dest="use_indexes") (options, args) = parser.parse_args() if len(args) < 1: parser.error("No tree source file given") sys.stdout = codecs.getwriter('utf8')(sys.stdout) sys.stderr= codecs.getwriter('utf8')(sys.stderr) pstyle=options.style.lower() if pstyle not in ["straight","square"]: parser.error("Unknown style '%s'"% pstyle) order=options.order.lower() if order not in ["fifo", "lifo"]: parser.error("Unknown order'%s'. Should belong to {fifo,lifo}"%(options.order)) texcomp=options.tex_compiler.lower() if texcomp not in ["pdftex","xetex", "polyglo"]: parser.error("Unknown TeX system '%s'. Should belong to {pdftex,xetex,polyglo}"% options.tex_compiler) font=options.font font=font_like(font, fonts_desc.keys() if texcomp=="pdftex" else available_arabic_fonts()) if font and texcomp=="pdftex": font=norm_font(font).lower() if font not in fonts.keys(): parser.error("Unknown font '%s'. Supported fonts are: %s"% (font, fonts.keys())) dir=options.dir.upper() if dir not in ["TB", "BT","LR", "RL"]: parser.error("Unknown direction'%s'. Should belong to {TB,BT,LR,RL}"% options.dir) texfmt=options.tex_format.lower() if texfmt not in ["tikz","pgf"]: parser.error("Unknown TeX format'%s'. Should belong to {tikz,pgf}"% options.tex_format) try: f=codecs.open(args[0],"r","utf8") except IOError: parser.error("Could not open file: '%s'"% args[0]) print "Source file: '%s'\nOrder: '%s'\nStyle: %s" %(args[0], order, pstyle) if font: if texcomp=="pdftex": print "Font: %s" % descriptionof(fonts.get(font, font)) else: print "Font:", font print "Direction: %s" % dir print "TeX format: %s" %texfmt print "TeX system: %s"%texcomp node_shape=options.node_shape.lower() if node_shape in ["mcircle", "msquare","mdiamond" ]: node_shape=node_shape.title() if node_shape not in shapes: parser.error("Unknown shape '%s'. Should belong to {%s}"% (options.node_shape, "|".join(shapes))) print "Shape of nodes: %s" % node_shape node_style=options.node_style if node_style: print "Node style=", node_style edge_style=options.edge_style #.replace(" ", "") if edge_style: print "Edge style=", edge_style special_shapes=map(lambda s: s in ["mcircle", "msquare","mdiamond"] and s.title() or s, filter(None,options.special_node_shapes.lower().split(separator))) or [] for nshape in special_shapes: if nshape not in shapes: parser.error("Unknown shape '%s'. Should belong to {%s}"% (nshape, "|".join(shapes))) if special_shapes: print "Special node shapes:", special_shapes special_styles=filter(None,options.special_styles.split(separator)) if options.special_styles else [] if special_styles: print "Special node styles=", special_styles special_fonts=filter(None,options.special_fonts.split(separator)) if options.special_fonts else [] # print "Special fonts before:", special_fonts if special_fonts: # for ft in special_fonts: special_fonts=[font_like(ft, fonts_desc.keys() if texcomp=="pdftex" else available_arabic_fonts()) for ft in special_fonts] if texcomp=="pdftex": special_fonts=[x.lower() for x in map(norm_font, special_fonts)] unknowns=filter(lambda x: x not in fonts.keys() , special_fonts) if unknowns: #ft not in fonts.keys(): parser.error("Unknown special fonts %s. Supported fonts are: %s"% (unknowns, fonts.keys())) else: fonts=dict((ft, ["\\"+refine_font_name(spaces.sub("", ft)), ft]) for ft in special_fonts) print "Special node fonts=",[descriptionof(fonts[ft ]) for ft in special_fonts] special_edge_styles=filter(None,options.special_edge_styles.split(separator) ) if options.special_edge_styles else [] if special_edge_styles: print "Special edge styles=", special_edge_styles print "Explicit origin anchors:", ("yes" if options.fix_orig else "no") print "Explicit destination anchors:", ("yes" if options.fix_dest else "no") print "Explicit node alignment anchors:", ("yes" if options.fix_alignments else "no") print "Propagate special features over ancsestors:", ("yes" if options.unify_styles else "no") print "Normalize Arabic text:", ("yes" if options.normalize else "no") print "Using indexes in names:", (options.use_indexes and "yes" or "no") print print g=AGraph( strict=False,directed=True) print "Generating the tree..." ids=generate_tree(f, order, options.normalize) print "Tree generated\nGenerating TeX code..." anchor_style=",anchor="+anchors[dir]["dest"][1:] first_anchor_style=",anchor="+anchors[dir]["orig"][1:] set_node_attributes(ids, node_style, special_styles,font, special_fonts, node_shape, special_shapes, options.unify_styles , texcomp) for id in ids: style="" if options.fix_alignments and texfmt=="tikz": if id==0: style=first_anchor_style else: style=anchor_style g.add_node(ids[id].idstr, style=ids[id].style+style, shape=ids[id].shape) if special_edge_styles and options.unify_styles: sp_paths=get_special_paths(ids) sp_paths_edges=map(lambda path: set(zip(sorted(path), sorted(path)[1:])) , sp_paths) # print "sp_paths_edges:", sp_paths_edges sp_segs=min_segments(sp_paths_edges) # print "special segments:", sp_segs segs_styles=zip(sp_segs, cycle(special_edge_styles)) # print "segs_styles:", segs_styles sp_edges=set([]) sp_edges.update(*sp_segs) edges=filter(lambda x: x not in sp_edges, [(ids[i].parent, i) for i in ids if ids[i].parent>=0]) # print "special edges:", sp_edges for seg, style in segs_styles: g.add_edges_from([(ids[id0].idstr, ids[id1].idstr) for id0, id1 in seg], style=edge_style+","+style) else: edges=[(ids[i].parent, i) for i in ids if ids[i].parent>=0] g.add_edges_from([(ids[id0].idstr, ids[id1].idstr) for (id0, id1) in edges], style=edge_style) preamble="" path="" if pstyle=="square": if dir in ["TB", "BT"]: preamble=r"\usetikzlibrary{calc}\tikzstyle{fork vertical} =[to path={|- ($(\tikztostart)!0.3!(\tikztotarget)$) -| (\tikztotarget) \tikztonodes}]" path="fork vertical" else: preamble=r"\usetikzlibrary{calc}\tikzstyle{fork horizontal} =[to path={-| ($(\tikztostart)!0.3!(\tikztotarget)$) |- (\tikztotarget) \tikztonodes}]" path="fork horizontal" g.graph_attr.update( rankdir=dir, ratio="compress", size="10,8", d2tdocpreamble = preamble); #d2tdocpreamble = "\\usepackage[T1,LFE,LAE]{fontenc}\n\\usepackage[english,arabic]{babel }\n")#r"\tikzstyle{every state}=[draw=blue!50,very thick,fill=red!20]") g.node_attr.update( texmode='verbatim', shape=node_shape, style=node_style) g.edge_attr.update(lblstyle="auto",topath=path , style=edge_style) getname=replacer(ids,texcomp, options.use_indexes)#, font,special_fonts ) g=conv_labels(g, ids) texcode = d2t.dot2tex(g.string(), prog="dot", autosize=True, format=texfmt,usepdflatex=True, tikzedgelabels=False,crop=True, straightedges=True) print "Code generated\nPost-processing the code..." code_lines=texcode.split("\n") pline="" # ins1=False # ins2=False code_lines=rep_ids(code_lines, getname, texfmt) if texfmt=="tikz": code_lines=fix_anchors(code_lines,dir, options.fix_orig,options.fix_dest ) code_lines=refine_code(code_lines, texcomp, font, special_fonts) ## for i, line in enumerate(code_lines): # if not ins1 and not line.startswith(r"\usepackage") and pline.startswith(r"\usepackage"): # code_lines.insert(i, r"\usepackage[english,arabic]{babel }") # code_lines.insert(i, r"\usepackage[T1,LFE,LAE]{fontenc}") # code_lines.insert(i, r"\usepackage{cmap}") # ins1=True # if not ins2 and pline==r"\begin{document}": # code_lines.insert(i,r"\selectlanguage{english}") # ins2=True ## if (texfmt=="tikz" and node_line.match(line)) or (texfmt=="pgf" and node_line_pgf.match(line)): # print line # print "Line before:", code_lines[i] ## code_lines[i]=repl_id.sub(getname, line) # print "line after:", code_lines[i] # pline=line texfilename=args[0]+".tex" print "Code saved to: '%s'"% texfilename codecs.open(texfilename, "w", "utf8").write("\n".join(code_lines)) # g.draw(args[0]+".eps", prog="dot") g.write(args[0]+".dot") print "Compiling TeX code" p=subprocess.Popen("%s -halt-on-error %s"%(compilers[texcomp], texfilename), shell=True, stdout=subprocess.PIPE, stderr=subprocess.PIPE) out, err=p.communicate() if p.returncode: print >>sys.stderr, "An error occured while compiling:%s\nHave a look into '%s.log' to find out more." % (err, args[0]) else: print "Successfully compiled\nResult saved to: '%s'" % (args[0]+".pdf") p.wait()
def main(): global fonts description="This program parses an Arabic text file in order to build a family genealogical tree.\nThe file is analysed line by line, "\ "every line is expected to expand a parent (at the first position) together with his children separated by periods '.'. "\ "If everything works fine, the tree is saved as a figure in pdf format and consequently can be inserted later in other documents "\ "or printed directly. Since the structure is hierarchical, every parent name (except the first) should have been previously mentioned. "\ "In order to highlight (a) special path(s) in the tree, the special names should be marked with (an) asterisk(s) '*' at the beginning "\ "and/or at the end of that special name. For special names you can specify particular styles and/or particular fonts."\ "Every name can be preceded/followed by small comments by separating them by ':'. In such case, the order will be respected, "\ "and the main name should be marked with '-' sign(s) at one/both of its sides if it is not the first.'-' and '*' sign(s) can be safely mixed. "\ "Three typesetting systems are supported at the moment, namely: 'Arabi', 'ArabXeTeX', and 'Polyglossia'. Arabi is simpler and supports less fonts. "\ "With ArabXeTeX or Polyglossia you can use any of your installed fonts, but you need a new version of the 'Preview' package. "\ "Please report any feedback to Mohammed Mediani: [email protected] " usage = "Usage: %prog [options] tree-source-file" parser = OptionParser(usage) parser.set_description(description) parser.add_option( "-s", "--style", action="store", type="string", dest="style", help= "{straight|square} straight: default style, straight connectors,\rsquare: squared connectors", default="straight") parser.add_option( "-o", "--order", action="store", type="string", dest="order", help= "{fifo|lifo} fifo: the parent name refers to the last occurence of this name, lifo: the name refers to the earliest occurence, default: fifo", default="fifo") parser.add_option( "-f", "--font", action="store", type="string", dest="font", help= "Select a specific font. supported fonts for 'pdftex' (in the format: 'code: font name'): {%s}. Available Arabic fonts for 'XeTeX'/'Polyglossia' (Unix only) {%s}" % ("|".join(" %s: %s " % (x, descriptionof(y)) for x, y in fonts.items()), "|".join( available_arabic_fonts())), default="") parser.add_option( "-n", "--node-style", action="store", type="string", dest="node_style", help= "String describing TikzStyle for the nodes (eg. 'fill=red!20', to get nodes filled with 20% of red). Enclose inside SINGLE quotes if contains spaces or special characters", default="") parser.add_option( "-e", "--edge-style", action="store", type="string", dest="edge_style", help= "String describing TikzStyle forthe edges (eg. '-diamond, blue' to get zigzagged green edges). Enclose inside SINGLE quotes if contains spaces or special characters", default="") parser.add_option( "-N", "--special-node-styles", action="store", type="string", dest="special_styles", help= "%s-seprated string of node styles for special nodes in order to highlight a particular path in the tree. The program will cycle through this list and assign styles accordingly to special names. Enclose inside SINGLE quotes if contains spaces or special characters" % separator, default="") parser.add_option( "-F", "--special-fonts", action="store", type="string", dest="special_fonts", help= "%s-seprated string of fonts for special nodes in order to highlight a particular path in the tree. The program will cycle through this list and assign fonts accordingly to special names. Enclose inside SINGLE quotes if contains spaces or special characters" % separator, default="") parser.add_option( "-E", "--special-edge-styles", action="store", type="string", dest="special_edge_styles", help= "%s-seprated string of edge styles for special paths in order to highlight a particular path in the tree. The program will cycle through this list and assign styles accordingly to special edges. Enclose inside SINGLE quotes if contains spaces or special characters" % separator, default="") parser.add_option( "-d", "--dir", action="store", type="string", dest="dir", help= "{BT|TB|LR|RL} direction if the tree. B: bottom, T: top, L: left, R: right", default="tb") parser.add_option( "-x", "--texformat", action="store", type="string", dest="tex_format", help="{tikz|pgf} package used to generate the graph in Latex.", default="tikz") parser.add_option("-p", "--node-shape", action="store", type="string", dest="node_shape", help="The shape of nodes {%s}." % "|".join(shapes), default="box") parser.add_option( "-P", "--special-node-shape", action="store", type="string", dest="special_node_shapes", help= "%s-seprated string of shapes for special nodes. This would allow a node to be more visually attractive. The program will cycle through this list and assign shapes accordingly to special names. Enclose inside SINGLE quotes if contains spaces or special characters" % separator, default="") parser.add_option( "-c", "--tex-compiler", action="store", type="string", dest="tex_compiler", help= "{pdftex|xetex|polyglo} TeX system. The Arabi typesetting system will be used for 'pdftex', the ArabXeTeX system will be used for 'xetex', and Polyglossia will be used for 'polyglo'", default="pdftex") parser.add_option( "-a", "--explicit-orig-anchor", action="store_true", help= "Use this flag if the edges start points don't anchor correctly. This adds an explicit anchor in the TeX code.", dest="fix_orig") #, # default="False") parser.add_option( "-b", "--explicit-dest-anchor", action="store_true", help= "Use this flag if the edges ending points don't anchor correctly. This adds an explicit anchor in the TeX code.", dest="fix_dest") #, # default="False") parser.add_option( "-l", "--explicit-node-anchor", action="store_true", help= "Use this flag if the nodes in one level don't align correctly. This adds an explicit anchor in the TeX code.", dest="fix_alignments") #, parser.add_option( "-u", "--unify-special-paths", action="store_true", help= "Use this flag in order to propagate the special styles for one node over all its anscestors. Intersecting special paths cause the style to be changed.", dest="unify_styles") #, parser.add_option( "-z", "--normalize", action="store_true", help= "Use this flag to normalize the Arabic input text. For instance: all forms of 'Hamza' will be normalized to a single form, 'Tatweel' will be removed, any 'Tashkeel' will be removed, etc", dest="normalize") #, parser.add_option( "-i", "--use-indexes", action="store_true", help= "In case many similar names occur in the tree and it becomes difficult to choose either 'fifo' or 'lifo', names can be numerically indexed by pre/suf-fixing them with digits to avoid conflicts. If this flag is used, the indexes will be automatically removed before writing the names out.", dest="use_indexes") (options, args) = parser.parse_args() if len(args) < 1: parser.error("No tree source file given") sys.stdout = codecs.getwriter('utf8')(sys.stdout) sys.stderr = codecs.getwriter('utf8')(sys.stderr) pstyle = options.style.lower() if pstyle not in ["straight", "square"]: parser.error("Unknown style '%s'" % pstyle) order = options.order.lower() if order not in ["fifo", "lifo"]: parser.error("Unknown order'%s'. Should belong to {fifo,lifo}" % (options.order)) texcomp = options.tex_compiler.lower() if texcomp not in ["pdftex", "xetex", "polyglo"]: parser.error( "Unknown TeX system '%s'. Should belong to {pdftex,xetex,polyglo}" % options.tex_compiler) font = options.font font = font_like( font, fonts_desc.keys() if texcomp == "pdftex" else available_arabic_fonts()) if font and texcomp == "pdftex": font = norm_font(font).lower() if font not in fonts.keys(): parser.error("Unknown font '%s'. Supported fonts are: %s" % (font, fonts.keys())) dir = options.dir.upper() if dir not in ["TB", "BT", "LR", "RL"]: parser.error("Unknown direction'%s'. Should belong to {TB,BT,LR,RL}" % options.dir) texfmt = options.tex_format.lower() if texfmt not in ["tikz", "pgf"]: parser.error("Unknown TeX format'%s'. Should belong to {tikz,pgf}" % options.tex_format) try: f = codecs.open(args[0], "r", "utf8") except IOError: parser.error("Could not open file: '%s'" % args[0]) print "Source file: '%s'\nOrder: '%s'\nStyle: %s" % (args[0], order, pstyle) if font: if texcomp == "pdftex": print "Font: %s" % descriptionof(fonts.get(font, font)) else: print "Font:", font print "Direction: %s" % dir print "TeX format: %s" % texfmt print "TeX system: %s" % texcomp node_shape = options.node_shape.lower() if node_shape in ["mcircle", "msquare", "mdiamond"]: node_shape = node_shape.title() if node_shape not in shapes: parser.error("Unknown shape '%s'. Should belong to {%s}" % (options.node_shape, "|".join(shapes))) print "Shape of nodes: %s" % node_shape node_style = options.node_style if node_style: print "Node style=", node_style edge_style = options.edge_style #.replace(" ", "") if edge_style: print "Edge style=", edge_style special_shapes = map( lambda s: s in ["mcircle", "msquare", "mdiamond"] and s.title() or s, filter(None, options.special_node_shapes.lower().split(separator))) or [] for nshape in special_shapes: if nshape not in shapes: parser.error("Unknown shape '%s'. Should belong to {%s}" % (nshape, "|".join(shapes))) if special_shapes: print "Special node shapes:", special_shapes special_styles = filter(None, options.special_styles.split( separator)) if options.special_styles else [] if special_styles: print "Special node styles=", special_styles special_fonts = filter(None, options.special_fonts.split( separator)) if options.special_fonts else [] # print "Special fonts before:", special_fonts if special_fonts: # for ft in special_fonts: special_fonts = [ font_like( ft, fonts_desc.keys() if texcomp == "pdftex" else available_arabic_fonts()) for ft in special_fonts ] if texcomp == "pdftex": special_fonts = [x.lower() for x in map(norm_font, special_fonts)] unknowns = filter(lambda x: x not in fonts.keys(), special_fonts) if unknowns: #ft not in fonts.keys(): parser.error( "Unknown special fonts %s. Supported fonts are: %s" % (unknowns, fonts.keys())) else: fonts = dict( (ft, ["\\" + refine_font_name(spaces.sub("", ft)), ft]) for ft in special_fonts) print "Special node fonts=", [ descriptionof(fonts[ft]) for ft in special_fonts ] special_edge_styles = filter( None, options.special_edge_styles.split( separator)) if options.special_edge_styles else [] if special_edge_styles: print "Special edge styles=", special_edge_styles print "Explicit origin anchors:", ("yes" if options.fix_orig else "no") print "Explicit destination anchors:", ("yes" if options.fix_dest else "no") print "Explicit node alignment anchors:", ("yes" if options.fix_alignments else "no") print "Propagate special features over ancsestors:", ( "yes" if options.unify_styles else "no") print "Normalize Arabic text:", ("yes" if options.normalize else "no") print "Using indexes in names:", (options.use_indexes and "yes" or "no") print print g = AGraph(strict=False, directed=True) print "Generating the tree..." ids = generate_tree(f, order, options.normalize) print "Tree generated\nGenerating TeX code..." anchor_style = ",anchor=" + anchors[dir]["dest"][1:] first_anchor_style = ",anchor=" + anchors[dir]["orig"][1:] set_node_attributes(ids, node_style, special_styles, font, special_fonts, node_shape, special_shapes, options.unify_styles, texcomp) for id in ids: style = "" if options.fix_alignments and texfmt == "tikz": if id == 0: style = first_anchor_style else: style = anchor_style g.add_node(ids[id].idstr, style=ids[id].style + style, shape=ids[id].shape) if special_edge_styles and options.unify_styles: sp_paths = get_special_paths(ids) sp_paths_edges = map( lambda path: set(zip(sorted(path), sorted(path)[1:])), sp_paths) # print "sp_paths_edges:", sp_paths_edges sp_segs = min_segments(sp_paths_edges) # print "special segments:", sp_segs segs_styles = zip(sp_segs, cycle(special_edge_styles)) # print "segs_styles:", segs_styles sp_edges = set([]) sp_edges.update(*sp_segs) edges = filter(lambda x: x not in sp_edges, [(ids[i].parent, i) for i in ids if ids[i].parent >= 0]) # print "special edges:", sp_edges for seg, style in segs_styles: g.add_edges_from([(ids[id0].idstr, ids[id1].idstr) for id0, id1 in seg], style=edge_style + "," + style) else: edges = [(ids[i].parent, i) for i in ids if ids[i].parent >= 0] g.add_edges_from([(ids[id0].idstr, ids[id1].idstr) for (id0, id1) in edges], style=edge_style) preamble = "" path = "" if pstyle == "square": if dir in ["TB", "BT"]: preamble = r"\usetikzlibrary{calc}\tikzstyle{fork vertical} =[to path={|- ($(\tikztostart)!0.3!(\tikztotarget)$) -| (\tikztotarget) \tikztonodes}]" path = "fork vertical" else: preamble = r"\usetikzlibrary{calc}\tikzstyle{fork horizontal} =[to path={-| ($(\tikztostart)!0.3!(\tikztotarget)$) |- (\tikztotarget) \tikztonodes}]" path = "fork horizontal" g.graph_attr.update(rankdir=dir, ratio="compress", size="10,8", d2tdocpreamble=preamble) #d2tdocpreamble = "\\usepackage[T1,LFE,LAE]{fontenc}\n\\usepackage[english,arabic]{babel }\n")#r"\tikzstyle{every state}=[draw=blue!50,very thick,fill=red!20]") g.node_attr.update(texmode='verbatim', shape=node_shape, style=node_style) g.edge_attr.update(lblstyle="auto", topath=path, style=edge_style) getname = replacer(ids, texcomp, options.use_indexes) #, font,special_fonts ) g = conv_labels(g, ids) texcode = d2t.dot2tex(g.string(), prog="dot", autosize=True, format=texfmt, usepdflatex=True, tikzedgelabels=False, crop=True, straightedges=True) print "Code generated\nPost-processing the code..." code_lines = texcode.split("\n") pline = "" # ins1=False # ins2=False code_lines = rep_ids(code_lines, getname, texfmt) if texfmt == "tikz": code_lines = fix_anchors(code_lines, dir, options.fix_orig, options.fix_dest) code_lines = refine_code(code_lines, texcomp, font, special_fonts) ## for i, line in enumerate(code_lines): # if not ins1 and not line.startswith(r"\usepackage") and pline.startswith(r"\usepackage"): # code_lines.insert(i, r"\usepackage[english,arabic]{babel }") # code_lines.insert(i, r"\usepackage[T1,LFE,LAE]{fontenc}") # code_lines.insert(i, r"\usepackage{cmap}") # ins1=True # if not ins2 and pline==r"\begin{document}": # code_lines.insert(i,r"\selectlanguage{english}") # ins2=True ## if (texfmt=="tikz" and node_line.match(line)) or (texfmt=="pgf" and node_line_pgf.match(line)): # print line # print "Line before:", code_lines[i] ## code_lines[i]=repl_id.sub(getname, line) # print "line after:", code_lines[i] # pline=line texfilename = args[0] + ".tex" print "Code saved to: '%s'" % texfilename codecs.open(texfilename, "w", "utf8").write("\n".join(code_lines)) # g.draw(args[0]+".eps", prog="dot") g.write(args[0] + ".dot") print "Compiling TeX code" p = subprocess.Popen("%s -halt-on-error %s" % (compilers[texcomp], texfilename), shell=True, stdout=subprocess.PIPE, stderr=subprocess.PIPE) out, err = p.communicate() if p.returncode: print >> sys.stderr, "An error occured while compiling:%s\nHave a look into '%s.log' to find out more." % ( err, args[0]) else: print "Successfully compiled\nResult saved to: '%s'" % (args[0] + ".pdf") p.wait()
def test_styleonly_tikz_preproc(self): """Test for a bug in get_node_preproc_code. Used to raise a TypeError""" code = dot2tex.dot2tex(testgraph, format="tikz", preproc=True, styleonly=True)
def test_tikz210option(self): source = dot2tex.dot2tex(testgraph, debug=True, format='tikz', pgf210=True) self.failUnless(source.find("dot2tex template for PGF 2.10") >= 0)
def test_head_label_pstricks(self): source = dot2tex.dot2tex(self.test_graph, autosize=True, format="pstricks") self.failUnless("HEADLABEL" in source)
def test_nopgf118option(self): source = dot2tex.dot2tex(testgraph, debug=True, pgf118=False) self.failIf(source.find("\usepackage{pgflibrarysnakes}") >= 0) self.failUnless(source.find("\usetikzlibrary") >= 0) self.failUnless(source.find("line join=bevel") >= 0)
def test_tail_label_pstricks_duplicate(self): source = dot2tex.dot2tex(self.test_graph, autosize=True, format="pstricks", duplicate=True) self.failUnless("TAILLABEL" in source)
def test_tail_label_tikz(self): source = dot2tex.dot2tex(self.test_graph, autosize=True, format="tikz") self.failUnless("TAILLABEL" in source)
def test_head_label_tikz_duplicate(self): source = dot2tex.dot2tex(self.test_graph, autosize=True, format="tikz", duplicate=True) self.failUnless("HEADLABEL" in source)