Skip to content

visualizer

Visualizer dataclass

Stores a rendered graphviz digraph. Has helper classmethods to use for construction, as well as methods for output as different useful formats.

Source code in lineapy/visualizer/__init__.py
 21
 22
 23
 24
 25
 26
 27
 28
 29
 30
 31
 32
 33
 34
 35
 36
 37
 38
 39
 40
 41
 42
 43
 44
 45
 46
 47
 48
 49
 50
 51
 52
 53
 54
 55
 56
 57
 58
 59
 60
 61
 62
 63
 64
 65
 66
 67
 68
 69
 70
 71
 72
 73
 74
 75
 76
 77
 78
 79
 80
 81
 82
 83
 84
 85
 86
 87
 88
 89
 90
 91
 92
 93
 94
 95
 96
 97
 98
 99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
@dataclass
class Visualizer:
    """
    Stores a rendered graphviz digraph. Has helper classmethods to use
    for construction, as well as methods for output as different useful
    formats.
    """

    options: InitVar[VisualGraphOptions]
    digraph: graphviz.Digraph = field(init=False)

    def __post_init__(self, options: VisualGraphOptions):
        self.digraph = to_graphviz(options)

    def render_pdf_file(self, filename: str = "tracer") -> None:
        """
        Renders a PDF file for the graph and tries to open it.
        """
        self.digraph.render(filename, view=True, format="pdf")

    def render_svg(self) -> str:
        return optimize_svg(self.digraph.pipe(format="svg").decode())

    def ipython_display_object(self) -> DisplayObject:
        svg_text = self.render_svg()
        # We emit this HTML to get a zoomable SVG
        # Copied from https://github.com/jupyterlab/jupyterlab/issues/7497#issuecomment-557334236
        # Which references https://github.com/pygraphkit/graphtik/blob/56a513c665e26e7bf3e81b6fb07d9475c5bf1614/graphtik/plot.py#L144-L183
        # Which uses this library: https://github.com/bumbu/svg-pan-zoom
        html_text = f"""
            <div class="svg_container">
                <style>
                    .svg_container SVG {{
                        width: 100%;
                        height: 100%;
                    }}
                </style>
                <script src="https://bumbu.me/svg-pan-zoom/dist/svg-pan-zoom.min.js"></script>
                <script type="text/javascript">
                    var scriptTag = document.scripts[document.scripts.length - 1];
                    var parentTag = scriptTag.parentNode;
                    var svg_el = parentTag.querySelector(".svg_container svg");
                    svgPanZoom(svg_el, {{
                        controlIconsEnabled: true,
                        fit: true,
                        zoomScaleSensitivity: 0.2,
                        minZoom: 0.1,
                        maxZoom: 10
                    }});
                </script>
                {svg_text}
            </div>
        """
        return HTML(html_text)

    @classmethod
    def for_test_snapshot(cls, tracer: Tracer) -> Visualizer:
        """
        Create a graph for saving as a snapshot, to help with visual diffs in PRs.
        """
        options = VisualGraphOptions(
            tracer.graph,
            tracer,
            highlight_node=None,
            # This is generally repetitive, and we can avoid it.
            show_implied_mutations=False,
            # Views are too verbose to show in the test output
            show_views=False,
            show_artifacts=True,
            show_variables=True,
        )
        return cls(options)

    @classmethod
    def for_test_cli(cls, tracer: Tracer) -> Visualizer:
        """
        Create a graph to use when visualizing after passing in `--visualize`
        during testing.

        Show as much as we can for debugging.
        """
        options = VisualGraphOptions(
            tracer.graph,
            tracer,
            highlight_node=None,
            show_implied_mutations=True,
            show_views=True,
            show_artifacts=True,
            show_variables=True,
        )
        return cls(options)

    @classmethod
    def for_public(cls, tracer: Tracer) -> Visualizer:
        """
        Create a graph for our public API, when showing the whole graph.
        """
        options = VisualGraphOptions(
            tracer.graph,
            tracer,
            highlight_node=None,
            show_implied_mutations=False,
            show_views=False,
            show_artifacts=True,
            show_variables=True,
        )
        return cls(options)

    @classmethod
    def for_public_node(cls, graph: Graph, node_id: str) -> Visualizer:
        """
        Create a graph for our public API, when showing a single node.

        ??? note

            The tracer won't be passed in this case, since it is happening
            inside the executor and we don't have access to the tracer.
        """
        options = VisualGraphOptions(
            graph,
            tracer=None,
            highlight_node=node_id,
            show_implied_mutations=False,
            show_views=False,
            show_artifacts=False,
            show_variables=False,
        )

        return cls(options)

for_public(tracer) classmethod

Create a graph for our public API, when showing the whole graph.

Source code in lineapy/visualizer/__init__.py
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
@classmethod
def for_public(cls, tracer: Tracer) -> Visualizer:
    """
    Create a graph for our public API, when showing the whole graph.
    """
    options = VisualGraphOptions(
        tracer.graph,
        tracer,
        highlight_node=None,
        show_implied_mutations=False,
        show_views=False,
        show_artifacts=True,
        show_variables=True,
    )
    return cls(options)

for_public_node(graph, node_id) classmethod

Create a graph for our public API, when showing a single node.

Note

The tracer won't be passed in this case, since it is happening inside the executor and we don't have access to the tracer.

Source code in lineapy/visualizer/__init__.py
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
@classmethod
def for_public_node(cls, graph: Graph, node_id: str) -> Visualizer:
    """
    Create a graph for our public API, when showing a single node.

    ??? note

        The tracer won't be passed in this case, since it is happening
        inside the executor and we don't have access to the tracer.
    """
    options = VisualGraphOptions(
        graph,
        tracer=None,
        highlight_node=node_id,
        show_implied_mutations=False,
        show_views=False,
        show_artifacts=False,
        show_variables=False,
    )

    return cls(options)

for_test_cli(tracer) classmethod

Create a graph to use when visualizing after passing in --visualize during testing.

Show as much as we can for debugging.

Source code in lineapy/visualizer/__init__.py
 94
 95
 96
 97
 98
 99
100
101
102
103
104
105
106
107
108
109
110
111
@classmethod
def for_test_cli(cls, tracer: Tracer) -> Visualizer:
    """
    Create a graph to use when visualizing after passing in `--visualize`
    during testing.

    Show as much as we can for debugging.
    """
    options = VisualGraphOptions(
        tracer.graph,
        tracer,
        highlight_node=None,
        show_implied_mutations=True,
        show_views=True,
        show_artifacts=True,
        show_variables=True,
    )
    return cls(options)

for_test_snapshot(tracer) classmethod

Create a graph for saving as a snapshot, to help with visual diffs in PRs.

Source code in lineapy/visualizer/__init__.py
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
@classmethod
def for_test_snapshot(cls, tracer: Tracer) -> Visualizer:
    """
    Create a graph for saving as a snapshot, to help with visual diffs in PRs.
    """
    options = VisualGraphOptions(
        tracer.graph,
        tracer,
        highlight_node=None,
        # This is generally repetitive, and we can avoid it.
        show_implied_mutations=False,
        # Views are too verbose to show in the test output
        show_views=False,
        show_artifacts=True,
        show_variables=True,
    )
    return cls(options)

render_pdf_file(filename='tracer')

Renders a PDF file for the graph and tries to open it.

Source code in lineapy/visualizer/__init__.py
35
36
37
38
39
def render_pdf_file(self, filename: str = "tracer") -> None:
    """
    Renders a PDF file for the graph and tries to open it.
    """
    self.digraph.render(filename, view=True, format="pdf")

Was this helpful?

Help us improve docs with your feedback!