Skip to content

Commit 1ee0f4d

Browse files
committed
ENH(sol,plot,.TC): PLOTter solutions
1 parent a9f6940 commit 1ee0f4d

File tree

3 files changed

+40
-11
lines changed

3 files changed

+40
-11
lines changed

docs/source/plotting.rst

Lines changed: 11 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -25,10 +25,17 @@ solution of the last computation, calling methods with arguments like this::
2525

2626
The legend for all graphtik diagrams, generated by :func:`.legend()`.
2727

28-
The same :meth:`.Plotter.plot()` method applies for :class:`.NetworkOperation`,
29-
:class:`.Network` & :class:`.ExecutionPlan`, each one capable to produce diagrams
30-
with increasing complexity. Whenever possible, the top-level ``plot()`` methods
31-
delegates to the ones below.
28+
The same :meth:`.Plotter.plot()` method applies also for:
29+
30+
- :class:`.NetworkOperation`
31+
- :class:`.Network`
32+
- :class:`.ExecutionPlan`
33+
- :class:`~.network.Solution`
34+
35+
each one capable to producing diagrams with increasing complexity.
36+
Whenever possible, the top-level ``plot()`` methods will delegate to the ones below;
37+
specifically, the :term:`netop` keeps a transient reference to the last `plan`.
38+
BUT the `plan` does not hold such a reference, you have to plot the `solution`.
3239

3340
For instance, when a net-operation has just been composed, plotting it will
3441
come out bare bone, with just the 2 types of nodes (data & operations), their

graphtik/network.py

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -63,7 +63,7 @@ def is_skip_evictions():
6363
return _execution_configs.get()["skip_evictions"]
6464

6565

66-
class Solution(ChainMap):
66+
class Solution(ChainMap, Plotter):
6767
"""Collects outputs from operations, preserving :term:`overwrites`."""
6868

6969
def __init__(self, plan, *args, **kw):
@@ -110,6 +110,12 @@ def overwrites(self) -> Mapping[Any, List]:
110110

111111
return {k: v for k, v in dd.items() if len(v) > 1}
112112

113+
def _build_pydot(self, **kws):
114+
"""delegate to network"""
115+
kws.setdefault("solution", self)
116+
plotter = self.plan
117+
return plotter._build_pydot(**kws)
118+
113119

114120
class _DataNode(str):
115121
"""

test/test_plot.py

Lines changed: 22 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -110,16 +110,32 @@ def test_plotters_hierarchy(pipeline: NetworkOperation, inputs, outputs):
110110
solution = pipeline.compute(inputs, outputs)
111111

112112
# Plotting delegates to netwrok plan.
113-
plan_dot = str(pipeline.plot(inputs=inputs, outputs=outputs))
113+
netop_dot = str(pipeline.plot(inputs=inputs, outputs=outputs))
114+
assert netop_dot
115+
assert netop_dot != base_dot
116+
assert pipeline.name in str(netop_dot)
117+
118+
# Plotting plan alone has not label.
119+
plan_dot = str(pipeline.last_plan.plot(inputs=inputs, outputs=outputs))
114120
assert plan_dot
115121
assert plan_dot != base_dot
116-
assert pipeline.name in str(plan_dot)
122+
assert plan_dot != netop_dot
123+
assert pipeline.name not in str(plan_dot)
117124

118125
# Plot a plan + solution, which must be different from all before.
119-
sol_plan_dot = str(pipeline.plot(inputs=inputs, outputs=outputs, solution=solution))
120-
assert sol_plan_dot != base_dot
121-
assert sol_plan_dot != plan_dot
122-
assert pipeline.name in str(plan_dot)
126+
sol_netop_dot = str(
127+
pipeline.plot(inputs=inputs, outputs=outputs, solution=solution)
128+
)
129+
assert sol_netop_dot != base_dot
130+
assert sol_netop_dot != netop_dot
131+
assert sol_netop_dot != plan_dot
132+
assert pipeline.name in str(netop_dot)
133+
134+
# Plot a solution, which must equal plan + sol.
135+
sol_plan_dot = str(
136+
pipeline.last_plan.plot(inputs=inputs, outputs=outputs, solution=solution)
137+
)
138+
assert str(solution.plot(inputs=inputs, outputs=outputs)) == sol_plan_dot
123139

124140
plan = pipeline.last_plan
125141
pipeline.last_plan = None

0 commit comments

Comments
 (0)