Skip to content

Commit 87717f0

Browse files
That looked nice. I'm just gonna touch up
1 parent 2bbb123 commit 87717f0

File tree

1 file changed

+49
-59
lines changed

1 file changed

+49
-59
lines changed

tutorials/modules/ROOT/pages/graph-viz.adoc

Lines changed: 49 additions & 59 deletions
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,7 @@ This tutorial is based on a jupyter notebook. You can run it locally
77
This tutorial builds a simple python library for visualising TypeDB
88
results as graphs using the query representation returned by the analyze
99
endpoint, and optionally returned with a query when the
10-
`+include_query_structure+` `+QueryOption+` is set. We assume the user
10+
`include_query_structure` `QueryOption` is set. We assume the user
1111
is familiar with the TypeDB python driver
1212
(https://github.com/typedb/typedb-driver/tree/master/python#example-usage[tutorial]).
1313
It uses the python driver for interacting with TypeDB, networkx for
@@ -89,12 +89,12 @@ setup(driver, SCHEMA, DATA)
8989

9090
== Background: Analyzing queries and PipelineStructure
9191

92-
TypeDB 3.7.0 introduces the `+analyze+` operation. Analyzing a query
92+
TypeDB 3.7.0 introduces the `analyze` operation. Analyzing a query
9393
returns its pipeline structure, along with typing information for the
9494
variables in each pattern.
9595

96-
A pipeline is made up of `+PipelineStage+`s, some of which are made of
97-
`+Conjunction+`s.
96+
A pipeline is made up of `PipelineStage`s, some of which are made of
97+
`Conjunction`s.
9898

9999
[source,python]
100100
----
@@ -133,7 +133,7 @@ stages
133133
----
134134
====
135135

136-
A conjunction is a collection of `+Constraint+`s, which should be
136+
A conjunction is a collection of `Constraint`s, which should be
137137
familiar from the TypeQL statements:
138138

139139
[source,python]
@@ -156,8 +156,8 @@ class Has(Constraint, ABC):
156156
----
157157

158158
TypeQL statements can be seen as constraints between one or more
159-
`+ConstraintVertex+`es - These can be type `+Label+`s, `+Variable+`s or
160-
raw `+Value+`s.
159+
`ConstraintVertex`es - These can be type `Label`s, `Variable`s or
160+
raw `Value`s.
161161

162162

163163
[source, python]
@@ -185,8 +185,8 @@ constraints
185185

186186
Before we get to visualising the data returned by queries, We’ll turn
187187
the constraints in our query into a query-graph and visualise it. We’ll
188-
use a `+to_query_edge+` function to go from a Constraint to a labelled
189-
edge represented by the tuple `+(from, label, to)+`
188+
use a `to_query_edge` function to go from a Constraint to a labelled
189+
edge represented by the tuple `(from, label, to)`
190190

191191

192192
[source, python]
@@ -219,10 +219,7 @@ query_edges
219219
----
220220
====
221221

222-
We then use networkx and matplotlib to visualise the graph
223-
224-
225-
+*In[6]:*+
222+
We then use networkx and matplotlib to visualise the graph:
226223
[source, python]
227224
----
228225
import networkx
@@ -244,8 +241,8 @@ image:output_11_0.png[]
244241
== Better formatting
245242

246243
That’s the query graph, but it’s of little use to the viewer. We’ll
247-
create a `+node_style+` function which specifies some style attributes,
248-
and a `+draw+` function which uses these to draw the networkx graph
244+
create a `node_style` function which specifies some style attributes,
245+
and a `draw` function which uses these to draw the networkx graph
249246
using matplotlib.
250247

251248

@@ -296,9 +293,9 @@ image:output_13_0.png[]
296293

297294
== Visualising Data
298295

299-
TypeDB answers are `+ConceptRow+`s which map variables in the queries to
296+
TypeDB answers are `ConceptRow`s which map variables in the queries to
300297
concepts in the database. It has a similar interface to a python
301-
dictionary. If the `+include_query_structure+` `+QueryOption+` is set,
298+
dictionary. If the `include_query_structure` `QueryOption` is set,
302299
the pipeline structure will be returned and each row will have shared
303300
access to it.
304301

@@ -312,8 +309,7 @@ class ConceptRow:
312309
def query_structure(self) -> Optional["Pipeline"] # Shared access to the pipeline structure
313310
----
314311

315-
316-
+*In[8]:*+
312+
Run a query:
317313
[source, python]
318314
----
319315
with driver.transaction(DB_NAME, TransactionType.READ) as tx:
@@ -332,12 +328,12 @@ answers
332328
----
333329
====
334330

331+
Get the pipeline stages from it:
335332
[source, python]
336333
----
337334
# Every answer also has a reference to the pipeline structure
338335
list(answers[0].query_structure().stages())
339336
----
340-
341337
.Output
342338
[%collapsible]
343339
====
@@ -356,7 +352,7 @@ the query-graph and some subgraph in the database. An answer is thus the
356352
mapping between the two graphs. To construct the graph representing the
357353
answer, we simply have to substitute the concepts in the answers for the
358354
variables in the query-graph. Since there are multiple answers, we take
359-
the union of edges
355+
the union of edges.
360356

361357
[source, python]
362358
----
@@ -376,7 +372,6 @@ answers_as_data_edges = [
376372
]
377373
answers_as_data_edges
378374
----
379-
380375
.Output
381376
[%collapsible]
382377
====
@@ -400,10 +395,8 @@ answers_as_data_edges
400395
== Visualising
401396

402397
We’ll need a new node style since our vertices are now concepts rather
403-
than `+ConstraintVertex+`es
398+
than `ConstraintVertex`es.
404399

405-
406-
+*In[11]:*+
407400
[source, python]
408401
----
409402
# We need to update our node_style
@@ -435,12 +428,11 @@ node_styles = { n: data_node_style(n) for n in nodes}
435428
draw(data_edges, node_styles)
436429
437430
----
438-
439-
440-
+*Out[11]:*+
441-
----
442-
![png](output_20_0.png)
443-
----
431+
.Output
432+
[%collapsible]
433+
====
434+
image:output_20_0.png[]
435+
====
444436

445437
== Disjunctions and optionals
446438

@@ -477,8 +469,7 @@ answers
477469
====
478470

479471

480-
481-
We can get the constraints in the trunk:
472+
Get the constraints in the trunk:
482473
[source, python]
483474
----
484475
pipeline = answers[0].query_structure()
@@ -502,9 +493,9 @@ trunk = list(pipeline.conjunction(trunk_id).constraints())
502493
====
503494

504495

496+
Get the constraints by branch:
505497
[source, python]
506498
----
507-
## Get those as well:
508499
branches = { branch_id: list(pipeline.conjunction(branch_id).constraints()) for branch_id in trunk[1].as_or().branches() }
509500
branches
510501
----
@@ -528,8 +519,8 @@ branches
528519

529520
How do we know which of these branches were satisfied by each answer? If
530521
we were to naively draw the constraints from all branches, we’d have
531-
some absurd edges such as `+name:John isa age+`. Each `+ConceptRow+` has
532-
an `+involved_conjunctions+` method which tells us exactly this.
522+
some absurd edges such as `name:John isa age`. Each `ConceptRow` has
523+
an `involved_conjunctions` method which tells us exactly this.
533524

534525

535526
[source, python]
@@ -635,7 +626,7 @@ A query can contain function calls. Functions have arguments and return
635626
values - all of which are concepts. Unlike a relation, the function call
636627
itself is not a concept. We felt the cleanest way to visualise the
637628
many-to-many constraint between return values and arguments was to
638-
introduce a `+FunctionCall+` vertex for each call. Two function calls
629+
introduce a `FunctionCall` vertex for each call. Two function calls
639630
are the same vertex if they have the same (1) function name, (2) tuple
640631
of argument concepts, and (3) tuple of returned concepts.
641632

@@ -655,26 +646,27 @@ role serving as the label of the edge.
655646

656647
TypeDB allows the use of unscoped role names in links & relates
657648
constraints to specify the role. e.g. For the schema below, the query
658-
`+match $r relates subject;+` will return both `+sentence+` and
659-
`+email+` as answers for `+$r+`;
649+
`match $r relates subject;` will return both `sentence` and
650+
`email` as answers for `$r`;
660651

661-
....
652+
[source, typeql]
653+
----
662654
define
663655
relation sentence relates subject;
664656
relation email relates subject;
665-
....
657+
----
666658

667659
Internally, TypeDB introduces an internal variable and constrains it to
668660
be any of the role types with the specified name. In the structure
669-
returned by the `+analyze+` operation, these variables and their
670-
associated names are returned as `+NamedRole+` vertices. (Since the
661+
returned by the `analyze` operation, these variables and their
662+
associated names are returned as `NamedRole` vertices. (Since the
671663
variable introduced is anonymous, it is unavailable in the ConceptRow.
672664
Since it does not uniquely determine the type, it cannot be considered a
673665
label.)
674666

675667
=== Is & comparison constraints
676668

677-
Since `+is+` constraints are always a self-edge on a vertex, we choose
669+
Since `is` constraints are always a self-edge on a vertex, we choose
678670
not to visualise it. We also skip visualising comparison constraints to
679671
reduce the number of edges, though they can be useful in certain cases -
680672
the comparator symbol is available from the comparison constraint.
@@ -687,12 +679,12 @@ for TypeDB studio. The essence remains the same as what we’ve covered in
687679
the tutorial - Find the constraints "`involved`" in each answer, and
688680
substitute in the concepts for the variables. Instead of converting a
689681
constraint into query edges, and then applying the substitution to form
690-
data-edges, We directly apply the substitution on the `+Constraint+`s to
691-
obtain the corresponding `+DataConstraint+` - These constrain
692-
`+DataVertex+`es instead of `+ConstraintVertex+`es.
682+
data-edges, We directly apply the substitution on the `Constraint`s to
683+
obtain the corresponding `DataConstraint` - These constrain
684+
`DataVertex`es instead of `ConstraintVertex`es.
693685

694-
Here’s the signature of an `+Isa+` `+DataConstraint+` from the library,
695-
and the `+Isa+` `+Constraint+` from the driver API to compare against:
686+
Here’s the signature of an `Isa` `DataConstraint` from the library,
687+
and the `Isa` `Constraint` from the driver API to compare against:
696688

697689
[source,python]
698690
----
@@ -709,24 +701,22 @@ class Isa(Constraint, ABC):
709701
def exactness(self) -> ConstraintExactness # isa or isa!
710702
----
711703

712-
We introduce a `+TypeDBAnswerConverter[OutputType]+` abstract class,
713-
which defines methods the user has to implement - One `+add_+` method
714-
per data constraint (e.g. `+add_isa(self, isa: Isa)+`) and a
715-
`+finish(self) -> OutputType+` for whatever your final representation
704+
We introduce a `TypeDBAnswerConverter[OutputType]` abstract class,
705+
which defines methods the user has to implement - One `add_` method
706+
per data constraint (e.g. `add_isa(self, isa: Isa)`) and a
707+
`finish(self) -> OutputType` for whatever your final representation
716708
may be.
717709

718710
We provide a sample implementation -
719-
`+class NetworkXBuilder(TypeDBAnswerConverter[MultiDiGraph])+` - which
720-
builds a `+MultiDiGraph+` as in this tutorial. We also provide a basic
721-
`+matplotlib_visualizer+` for inspiration.
711+
`NetworkXBuilder` - which
712+
builds a `MultiDiGraph` as in this tutorial. We also provide a basic
713+
`MatplotlibVisualizer` for inspiration.
722714

723715
== Visualising using the library
724716

725717
We recreate the previous example by implementing the
726-
`+TypeDBAnswerConverter+` class provided by the library.
727-
718+
`TypeDBAnswerConverter` class provided by the library.
728719

729-
+*In[18]:*+
730720
[source, python]
731721
----
732722
from typedb_graph_utils import data_constraint, TypeDBAnswerConverter, MatplotlibVisualizer

0 commit comments

Comments
 (0)