gravis JSON Graph Format (gJGF)¶
Introduction¶
The package
gravis
uses a custom data format called gravis JSON Graph Format or short gJGF
to define a single graph with optional annotations or to define a collection of such graphs.
It is a text format that is human-readable and based on
JSON
as well as
JSON Graph Format (JGF).
Files that contain data in this format should end with the extension .gjgf
.
The following specification defines gJGF version 0.1 by extending JGF with custom metadata properties. These properties are recognized by gravis and they are translated into visual elements and their appearance in graph visualizations. For example, node shapes, sizes and colors can be influenced among many other options.
Motivation¶
JSON was chosen because it is a well-supported text format in Python and JavaScript, but also in many other programming languages. This means that it is easy to decode
JSON strings
intolanguage objects
or encodelanguage objects
intoJSON strings
with built-in functionality. For these purposes Python offers a json module that can be imported, while JavaScript provides a built-in JSON object available in its global scope. In contrast, other text formats not based on JSON would have required to write custom decoder and encoder functions (or parser and generator functions) in both languages, which can be a tedious and error-prone task.JSON Graph Format (JGF) was chosen because it is open to defining custom metadata, which is suitable for introducing specific graph annotations as required by this package. Beyond that, building on a well-defined existing format seemed more reasonable than inventing yet another completely custom one.
Specification¶
Part 1: Data types specified by JSON¶
JSON is specified in two compatible standards (RFC 8259, ECMA-404) that aim to define the same formal language with a JSON grammar written in two different formalisms (ABNF, EBNF). Here is a short summary of the main ingredients of the JSON language:
A
value
can be anobject
,array
,number
,string
or one of the literal namestrue
,false
, ornull
.An
object
structure is represented as a pair of curly brackets surrounding zero or more name/value pairs.An
array
structure is represented as a pair of square brackets surrounding zero or more values.A
number
is a sequence of decimal digits with no leading zero.A
string
is a sequence of Unicode code points wrapped with quotation marks.
These structures are defined in more detail in the official standards. In the following text, they will be referred to with their name prefixed by JSON. They have corresponding data types in Python and JavaScript:
Part 2: Graph structure specified by JGF¶
JSON Graph Format (JGF) is a specification for representing graph structures in JSON. The package gravis adheres to JGF Version 2 (precisely: commit ce5ed40 on February 1, 2021). Its ingredients are summarized in the following. Note that some elements are ignored by gravis, which is indicated below and means that they do not appear as elements in a graph visualization by default:
A
JGF
structure is aJSON object
, which can contain a single name/value pair from the following two options:Name
Value
Meaning
“graph”
graph
structure (see below)A single graph
“graphs”
graphs
structure (see below)A collection of graphs
A
graphs
structure is aJSON array
, which can contain zero or moregraph
structures (see below).A
graph
structure is aJSON object
, which can contain following name/value pairs:Name
Value
Meaning
Status
“id”
JSON string
An identifier for the graph
optional
“type”
JSON string
A classification for the graph
ignored
“label”
JSON string
A text label for the graph
optional
“directed”
JSON false
orJSON true
(default)Undirected or directed graph
optional
“nodes”
nodes
structure (see below)Nodes of the graph
optional
“edges”
edges
structure (see below)Edges of the graph
optional
“hyperedges”
JSON array
Hyperedges of a hypergraph
ignored
“metadata”
graph metadata
(see part 3)Custom graph annotations defined by gJGF
optional
A
nodes
structure is aJSON object
, which represents the nodes or vertices of a graph. It can contain zero or more name/value pairs of following form:Name
Value
Meaning
Status
node id
which is aJSON string
node
structure (see below)A node of the graph
optional
Note that a
node id
(and therefore a node) is necessarily unique, because it appears as name in aJSON object
. This allows edges to unambigously refer to a certain node as source or target by its uniquenode id
.An
edges
structure is aJSON array
, which represents the edges or links of a graph. It can contain zero or more values, where each value is anedge
structure (see below).Note that an edge may not be unique, because it can repeatedly appear as entry in a
JSON array
. This allows to define multiedges and thereby multigraphs.A
node
structure is aJSON object
, which represents a single node. It can contain following name/value pairs:Name
Value
Meaning
Status
“label”
JSON string
A text label for the node
optional
“metadata”
node metadata
(see part 3)Custom node annotations defined by gJGF
optional
An
edge
structure is aJSON object
, which represents a single edge. It can contain following name/value pairs, some of which are required:Name
Value
Meaning
Status
“source”
JSON string
Source node, needs to be a
node id
contained innodes
required
“target”
JSON string
Target node, needs to be a
node id
contained innodes
required
“relation”
JSON string
Interaction between source and target
ignored
“label”
JSON string
A text label for the edge
optional
“directed”
JSON true
orJSON false
Whether the edge is directed or undirected
ignored
“metadata”
edge metadata
(see part 3)Custom edge annotations defined by gJGF
optional
Note that “label” is missing in JGF Version 2, but was there in previous states and is still present in an example, therefore it was included here.
Caution
This package detects if an edge has a source or target that is not a node id. Such an edge is ignored as if it were not part of the given data. A message is written to the web console in the browser, which can be inspected by developers but will not be visible to regular users.
Part 3: Graph annotation specified by gJGF¶
JGF contains a graph
structure, a node
structure and an
edge
structure. Each of them is a JSON object
, where one of the allowed
name/value pairs is “metadata”/JSON object
. In the following, these objects
associated to the “metadata” name will be referred to as graph metadata
,
node metadata
and edge metadata
. They allow to add custom graph, node and
edge annotations, which can modify the appearance of the graph, its nodes and its
edges when visualized. gJGF specifies which annotations are recognized by gravis.
All values are defined as JSON string
or JSON number
as described below,
but for greater flexibility gravis also accepts JSON string
for numerical values
and auto-converts them to numbers.
A
graph metadata
structure is aJSON object
and can contain following name/value pairs:Name
Value
Meaning
“arrow_color”
JSON string
Color of arrows in directed graphs
“arrow_size”
JSON number
Size of arrows in directed graphs
“background_color”
JSON string
Background color of graph drawing area
“node_color”
JSON string
Fill color of nodes
“node_opacity”
JSON number
Opacity of nodes
“node_size”
JSON number
Size of nodes (both height and width)
“node_shape”
JSON string
Shape of nodes: “circle”, “rectangle” or “hexagon”
“node_border_color”
JSON string
Line color of node border
“node_border_size”
JSON number
Line width of node border
“node_label_color”
JSON string
Text color of node labels
“node_label_size”
JSON number
Text size of node labels
“node_hover”
JSON string
HTML text shown in a pop-up tooltip when hovering over a node
“node_click”
JSON string
HTML text shown in details area when clicking on a node
“node_image”
JSON string
Image shown inside nodes: a URL pointing to an image or a data URL
“node_x”
JSON number
x position to fix each node at, can be released in UI
“node_y”
JSON number
y position to fix each node at, can be released in UI
“node_z”
JSON number
z position to fix each node at, can be released in UI, ignored in 2D
“edge_color”
JSON string
Line color of edges
“edge_opacity”
JSON number
Opacity of edges
“edge_size”
JSON number
Line width of edges
“edge_label_color”
JSON string
Text color of edge labels
“edge_label_size”
JSON number
Text size of edge labels
“edge_hover”
JSON string
HTML text shown in a pop-up tooltip when hovering over an edge
“edge_click”
JSON string
HTML text shown in details area when clicking on an edge
A
node metadata
structure is aJSON object
and can contain following name/value pairs:Name
Value
Meaning
“color”
JSON string
Fill color of the node
“opacity”
JSON number
Opacity of the node
“size”
JSON number
Size of the node
“shape”
JSON string
Shape of the node: “circle”, “rectangle” or “hexagon”
“border_color”
JSON string
Line color of node border
“border_size”
JSON number
Line width of node border
“label_color”
JSON string
Text color of node label
“label_size”
JSON number
Text size of node label
“hover”
JSON string
HTML text shown in a pop-up tooltip when hovering over the node
“click”
JSON string
HTML text shown in details area when clicking on the node
“image”
JSON string
Image shown inside the node: a URL pointing to an image or a data URL
“x”
JSON number
x position to fix the node at, can be released in UI
“y”
JSON number
y position to fix the node at, can be released in UI
“z”
JSON number
z position to fix the node at, can be released in UI, ignored in 2D
An
edge metadata
structure is aJSON object
and can contain following name/value pairs:Name
Value
Meaning
“color”
JSON string
Line color of the edge
“opacity”
JSON number
Opacity of the edge
“size”
JSON number
Line width of the edge
“label_color”
JSON string
Text color of edge label
“label_size”
JSON number
Text size of edge label
“hover”
JSON string
HTML text shown in a pop-up tooltip when hovering over the edge
“click”
JSON string
HTML text shown in details area when clicking on the edge
Examples¶
A minimal graph as JSON text in gJGF:
{
"graph": {
"directed": false,
"nodes": {
"1": {},
"2": {},
"3": {}
},
"edges": [
{"source": 1, "target": 2},
{"source": 2, "target": 3}
]
}
}
The same graph as Python dict adhering to gJGF:
data = {
'graph': {
'directed': False,
'nodes': {
1: {},
2: {},
3: {},
},
'edges': [
{'source': 1, 'target': 2},
{'source': 2, 'target': 3},
]
}
}
Further gJGF examples can be found in a Jupyter notebook
Auto-conversion of external graph objects to gJGF¶
This package supports six popular Python graph libraries which are listed below.
More specifically, the plotting functions of this package accept the different
graph objects of these libraries directly as input.
Internally the plotting functions first convert the graph objects
into gJGF and then proceed as if gJGF data was provided by the user.
The responsible conversion functions are located in the
gravis.convert
module and
can also be accessed by the user, e.g. to inspect the resulting
gJGF object and check whether everything is converted as expected.
There are also two convenience functions that make conversions easier:
Single graph from any supported library:
gravis.convert.any_to_gjgf
List of multiple graphs from supported libraries:
gravis.convert.multiple_to_gjgf