Binding grammar
A binding connects a source to a visual channel. The workbench writes bindings
for you; this page is the wire format for authoring them directly - in a .gph
document, over the embed protocol, or from the Python and R packages. The
GPH schema constrains a binding’s shape, but not
whether a channel accepts a source. Garphield resolves that against the catalog
below, and the Python package raises BindingError at build time when a binding
does not resolve.
Bindings live in config.bindings as an array. Each entry is:
{ "channel": "color", "source": { "kind": "field", "id": "field:team" }, "resultType": "cat"}channel- the mark or layer the source drives (see Channels).source-{ "kind", "id", "params?", "target?" }(see Source kinds).resultType- what the source produces:num,cat, orset. It must be a type the channel accepts, and for analgorithmsource it must match what that algorithm produces.
Channels
Section titled “Channels”Channels are camelCase on the wire. The result types a channel accepts and its target (node or edge) are fixed. The Python and R packages also accept the snake_case alias in the last column as a keyword argument; both resolve to the same camelCase channel on the wire.
| Channel (wire) | Target | Accepts | Python / R alias |
|---|---|---|---|
size |
node | num |
node_size |
color |
node | cat, num, set |
node_color |
shape |
node | cat, num, set |
- |
image |
node | cat |
- |
nodeLabel |
node | cat, num |
node_label |
border |
node | cat, set |
- |
pieSlices |
node | cat, num |
- |
edgeColor |
edge | cat, num |
edge_color |
edgeWidth |
edge | num |
edge_width |
edgeStyle |
edge | cat |
- |
edgeLabel |
edge | cat, num |
- |
hull |
node | cat, set |
- |
contour |
node | cat, set |
- |
heatmap |
node | num |
- |
A source’s target must match the channel’s target: a node source cannot drive an
edge channel, and the reverse. A source’s result type must be in the channel’s
Accepts list - for example, size and edgeWidth take only num, so binding
a category to either does not resolve.
Result types
Section titled “Result types”num- a numeric value per node or edge. Drives size, edge width, heatmap, or any channel that listsnum.cat- a categorical value. Drives color, shape, labels, contours, and hulls.set- a membership set. Drives color, shape, borders, hulls, and contours.
Source kinds
Section titled “Source kinds”field- a value already on the graph. Theidisfield:<name>for a node attribute orefield:<name>for an edge attribute (see Field ids).algorithm- a value computed in the browser, such asdegreeorlouvain. Theidis the bare algorithm id; optionalparamstune it (for example{"resolution": 1.2}forlouvain). An algorithm’s own target and produced type are fixed - see Sources and algorithms for the catalog. Edge algorithms carry"target": "edge".transform- a graph transformation. These live inconfig.filterStack, not in a visual channel, and producetrf.set- a saved set. A set can anchor nodes or edges; itstargetis resolved from the channel it is dropped on.
Field ids
Section titled “Field ids”A field id names an attribute by its internal, on-the-wire name:
- Node attribute
teambecomesfield:team. - Edge attribute
weightbecomesefield:weight.
Most attribute names pass through unchanged. A few names are reserved because the
wire format uses them for structure: id on a node; source, target, and
key on an edge; and any name beginning with _gph: or @gf:. When your data
uses a reserved name, Garphield escapes it to @gf:attr:v1:<encoded> in the node
or edge row and records the original name in config.interop.attributeNames, so
the field id becomes field:@gf:attr:v1:<encoded>. You rarely write these by
hand: discover the exact ids with project.sources() (Python) instead of
guessing.
Authoring from Python
Section titled “Authoring from Python”Project.from_networkx() and Project.from_pandas() take the snake_case channel
keywords and write the bindings for you, so you do not hand-author the JSON:
import garphield as gph
project = gph.Project.from_networkx( graph, node_color="kind", # an existing attribute -> field:kind node_size=gph.algorithm("degree"), # a computed source layout="force",)from_networkx also accepts a mapping, a callable, or a partition (a list of node
sets) for a channel; it materializes those into a node field and binds it.
from_pandas binds by column name, an algorithm(...) spec, layout, or pos;
for a per-row value, add a column to the frame and bind it by name.
Discover the bindable ids and their types without opening a browser:
for source in project.sources(): print(source.id, source.kind, source.target, source.result_type)# field:kind field node cat# efield:weight field edge num# degree algorithm node num# ...Every binding is validated when the Project is built. An unknown channel, a
missing field, an unknown algorithm, or a result type the channel does not accept
raises BindingError in Python, instead of leaving a dead binding that renders
nothing in a browser you cannot see.
See Visual channels for what each channel is for, Sources and algorithms for the algorithm catalog, and The .gph document for the surrounding project shape.