From 492b6d4ce3662513a11b01fc9f40f1c3bfa0141a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Xavier=20Dupr=C3=A9?= Date: Fri, 1 Mar 2024 16:19:43 +0100 Subject: [PATCH] Fix documentation (#81) * update requirements * fix names in to_dot * doc * fix doc * doc * fix doc * doc --- _doc/api/plotting.rst | 2 ++ _doc/conf.py | 1 + _doc/tutorial/onnx_api.rst | 6 +++- onnx_array_api/plotting/dot_plot.py | 7 +++- onnx_array_api/plotting/graphviz_helper.py | 40 ++++++++++++--------- onnx_array_api/reference/evaluator_yield.py | 7 ++-- onnx_array_api/validation/docs.py | 4 ++- 7 files changed, 44 insertions(+), 23 deletions(-) diff --git a/_doc/api/plotting.rst b/_doc/api/plotting.rst index 830cc86..db6076c 100644 --- a/_doc/api/plotting.rst +++ b/_doc/api/plotting.rst @@ -6,6 +6,8 @@ Dot .. autofunction:: onnx_array_api.plotting.dot_plot.to_dot +.. autofunction:: onnx_array_api.plotting.graphviz_helper.plot_dot + Statistics ++++++++++ diff --git a/_doc/conf.py b/_doc/conf.py index 30356d1..3c7a1ad 100644 --- a/_doc/conf.py +++ b/_doc/conf.py @@ -117,6 +117,7 @@ "ast": "https://docs.python.org/3/library/ast.html", "cProfile.Profile": "https://docs.python.org/3/library/profile.html#profile.Profile", "DOT": "https://graphviz.org/doc/info/lang.html", + "Graphviz": "https://graphviz.org/", "inner API": "https://onnx.ai/onnx/intro/python.html", "JIT": "https://en.wikipedia.org/wiki/Just-in-time_compilation", "onnx": "https://onnx.ai/onnx/", diff --git a/_doc/tutorial/onnx_api.rst b/_doc/tutorial/onnx_api.rst index a4f80be..2b673fb 100644 --- a/_doc/tutorial/onnx_api.rst +++ b/_doc/tutorial/onnx_api.rst @@ -71,7 +71,11 @@ the true implementation would be the following. n2 = oh.make_node("Pow", ["dxy", "two"], ["dxy2"]) n3 = oh.make_node("ReduceSum", ["dxy2"], [output_name]) graph = oh.make_graph([n1, n2, n3], "euclidian", [X, Y], [Z], [two]) - model = oh.make_model(graph, opset_imports=[oh.make_opsetid("", opset)]) + model = oh.make_model( + graph, + opset_imports=[oh.make_opsetid("", opset)], + ir_version=9, + ) return model diff --git a/onnx_array_api/plotting/dot_plot.py b/onnx_array_api/plotting/dot_plot.py index cff93f5..5bfba5d 100644 --- a/onnx_array_api/plotting/dot_plot.py +++ b/onnx_array_api/plotting/dot_plot.py @@ -116,7 +116,12 @@ def myloss(x, y): clean_label_reg2 = re.compile("\\\\p\\{[0-9P]{1,6}\\}") def dot_name(text): - return text.replace("/", "_").replace(":", "__").replace(".", "_") + return ( + text.replace("/", "_") + .replace(":", "__") + .replace(".", "_") + .replace("-", "_") + ) def dot_label(text): if text is None: diff --git a/onnx_array_api/plotting/graphviz_helper.py b/onnx_array_api/plotting/graphviz_helper.py index 2dd93c2..4aec5e4 100644 --- a/onnx_array_api/plotting/graphviz_helper.py +++ b/onnx_array_api/plotting/graphviz_helper.py @@ -73,7 +73,7 @@ def _run_subprocess( shell=False, env=os.environ, stdout=subprocess.PIPE, - stderr=subprocess.STDOUT, + stderr=subprocess.PIPE, ) raise_exception = False output = "" @@ -91,12 +91,14 @@ def _run_subprocess( ): raise_exception = True p.poll() + error = p.stderr.readline().decode(errors="ignore") p.stdout.close() - if raise_exception: + if error and raise_exception: raise RuntimeError( - "An error was found in the output. The build is stopped.\n{output}" + f"An error was found in the output. The build is stopped." + f"\n{output}\n---\n{error}" ) - return output + return output + "\n" + error def _run_graphviz(filename: str, image: str, engine: str = "dot") -> str: @@ -134,8 +136,12 @@ def _run_graphviz(filename: str, image: str, engine: str = "dot") -> str: exe = engine if os.path.exists(image): os.remove(image) - output = _run_subprocess([exe, f"-T{ext[1:]}", filename, "-o", image]) - assert os.path.exists(image), f"Graphviz failed due to {output}" + cmd = [exe, f"-T{ext[1:]}", filename, "-o", image] + output = _run_subprocess(cmd) + assert os.path.exists(image), ( + f"Unable to find {image!r}, command line is " + f"{' '.join(cmd)!r}, Graphviz failed due to\n{output}" + ) return output @@ -190,23 +196,25 @@ def plot_dot( :param image: output image, None, just returns the output :param engine: *dot* or *neato* :param figsize: figsize of ax is None - :return: :epkg:`Graphviz` output or - the dot text if *image* is None + :return: :epkg:`Graphviz` output or, the dot text if *image* is None .. plot:: import matplotlib.pyplot as plt import onnx.parser + from onnx_array_api.plotting.graphviz_helper import plot_dot model = onnx.parser.parse_model( - ''' - - agraph (float[N] x) => (float[N] z) { - two = Constant () - four = Add(two, two) - z = Mul(four, four) - }''') - ax = plot_dot(dot) + ''' + + agraph (float[N] x) => (float[N] z) { + two = Constant () + four = Add(two, two) + z = Mul(four, four) + } + ''') + + ax = plot_dot(model) ax.set_title("Dummy graph") plt.show() """ diff --git a/onnx_array_api/reference/evaluator_yield.py b/onnx_array_api/reference/evaluator_yield.py index f9f587f..88c8a1f 100644 --- a/onnx_array_api/reference/evaluator_yield.py +++ b/onnx_array_api/reference/evaluator_yield.py @@ -237,10 +237,9 @@ def enumerate_summarized( Executes the onnx model and enumerate intermediate results without their names. :param output_names: requested outputs by names, None for all - :param feed_inputs: dictionary `{ input name: input value }` - :param raise_exc: raises an exception if the execution fails or stop - where it is - :param keep_tensor:keep the tensor in order to compute precise distances + :param feed_inputs: dictionary ``{ input name: input value }`` + :param raise_exc: raises an exception if the execution fails or stop where it is + :param keep_tensor: keep the tensor in order to compute precise distances :return: iterator on ResultExecution """ for kind, name, value, op_type in self.enumerate_results( diff --git a/onnx_array_api/validation/docs.py b/onnx_array_api/validation/docs.py index d1a8422..c5f937f 100644 --- a/onnx_array_api/validation/docs.py +++ b/onnx_array_api/validation/docs.py @@ -30,7 +30,9 @@ def make_euclidean( n2 = oh.make_node("Pow", ["dxy", "two"], ["dxy2"]) n3 = oh.make_node("ReduceSum", ["dxy2"], [output_name]) graph = oh.make_graph([n1, n2, n3], "euclidian", [X, Y], [Z], [two]) - model = oh.make_model(graph, opset_imports=[oh.make_opsetid("", opset)]) + model = oh.make_model( + graph, opset_imports=[oh.make_opsetid("", opset)], ir_version=9 + ) return model