Skip to main content

module vis::Graphs

rascal-Not specified

Simple data visualization using graphs; based on cytoscape.js

Usage​

import vis::Graphs;

Dependencies​

import Content;
import IO;
import Set;
import ValueIO;
import lang::html::AST;
import lang::html::IO;
import util::IDEServices;

Description​

This modules provides a simple API to create graph visuals for Rascal (relational) data, based on Cytoscape.js.

This module is quite new and may undergo some tweaks in the coming time.

Benefits​

  • Easy to use for basic graph layouts.

data CytoGraphConfig​

Optional configuration attributes for graph style and graph layout

data CytoGraphConfig  
= cytoGraphConfig(
str title="Graph",

NodeLinker[&T] nodeLinker = defaultNodeLinker,
NodeLabeler[&T] nodeLabeler = defaultNodeLabeler,
NodeTipper[&T] nodeTipper = defaultNodeTipper,
NodeClassifier[&T] nodeClassifier = defaultNodeClassifier,

EdgeLabeler[&T] edgeLabeler = defaultEdgeLabeler,
EdgeTipper[&T] edgeTipper = defaultEdgeTipper,
EdgeClassifier[&T] edgeClassifier = defaultEdgeClassifier,
EdgeWeigher[&T] edgeWeigher = defaultEdgeWeigher,

CytoLayout \layout = defaultCoseLayout(),

CytoStyle nodeStyle = defaultNodeStyle(),
CytoStyle edgeStyle = defaultEdgeStyle(),
list[CytoStyleOf] styles = [],
list[HTMLElement] header = [tooltipCSS()],
list[HTMLElement] footer = [toEditorClick(), hoverListeners(), tooltipListeners()]
)
;

These configuration options are used to map input graph data to layout properties and style properties.

  • title - does what it says
  • nodeLinker - makes nodes clickable by providing an editor location
  • nodeLabeler - allows simplification or elaboration on node labels beyond their identity string
  • nodeTipper - allows tagging additional information to be showed on demand for a node
  • edgeTipper - allows tagging additonal informaiton to be showed on demand for an edge
  • nodeClassifier - labels nodes with classes in order to later select them for specific styling
  • edgeLabeler - allows simplification or elaboration on edge labels
  • layout - defines and configured the graph layout algorithm
  • nodeStyle - defines the default style for all nodes
  • edgeStyle - defines the default style for all edges
  • edgeWeigher - defines a function to weigh every edge
  • style - collects specific styles for specific Cyto Selector edge/node selectors using Cyto Style Of tuples.

Typically the functions passed into this configuration are closures that capture and use the original input data to find out about where to link and how to classify. The &T parameter reflects the type of the original input Graph[&T]; so that is the type of the nodes. Often this would be loc or str.

Examples​

Let's experiment with a number of styling parameters based on the shape of a graph:

rascal>import vis::Graphs;
ok

let's play with the genealogy of the "Simpsons"

rascal>g = {
|1 >>>> <"Abraham Simpson", "Homer Simpson">,
|2 >>>> <"Mona Simpson", "Homer Simpson">,
|3 >>>> <"Homer Simpson", "Bart Simpson">,
|4 >>>> <"Homer Simpson", "Lisa Simpson">,
|5 >>>> <"Homer Simpson", "Maggie Simpson">,
|6 >>>> <"Marge Simpson", "Bart Simpson">,
|7 >>>> <"Marge Simpson", "Lisa Simpson">,
|8 >>>> <"Marge Simpson", "Maggie Simpson">,
|9 >>>> <"Bart Simpson", "Rod Flanders">,
|10 >>>> <"Bart Simpson", "Todd Flanders">,
|11 >>> <"Lisa Simpson", "Bart Simpson">,
|12 >>> <"Abraham Simpson", "Patty Bouvier">,
|13 >>> <"Abraham Simpson", "Selma Bouvier">,
|14 >>> <"Mona Simpson", "Patty Bouvier">,
|15 >>> <"Mona Simpson", "Selma Bouvier">
|16 >>>};
rel[str,str]: {
<"Lisa Simpson","Bart Simpson">,
<"Homer Simpson","Lisa Simpson">,
<"Homer Simpson","Maggie Simpson">,
<"Homer Simpson","Bart Simpson">,
<"Mona Simpson","Homer Simpson">,
<"Mona Simpson","Patty Bouvier">,
<"Mona Simpson","Selma Bouvier">,
<"Marge Simpson","Lisa Simpson">,
<"Marge Simpson","Maggie Simpson">,
<"Marge Simpson","Bart Simpson">,
<"Bart Simpson","Rod Flanders">,
<"Bart Simpson","Todd Flanders">,
<"Abraham Simpson","Homer Simpson">,
<"Abraham Simpson","Patty Bouvier">,
<"Abraham Simpson","Selma Bouvier">
}

visualizing this without styling:

rascal>graph(g);

image to style nodes, let's select some special nodes and "classify" them first. We reuse some generic graph analysis tools.

rascal>import analysis::graphs::Graph;
ok
rascal>list[str] nodeClassifier(str simpson) = [
|1 >>>> *["top" | simpson in top(g)],
|2 >>>> *["bottom" | simpson in bottom(g)]
|3 >>>>];
list[str] (str): function(|prompt:///|(0,113,<1,0>,<4,2>))

once classified, we can style each node according to their assigned classes. Nodes can be in more than one class.

rascal>styles = [
|1 >>>> cytoStyleOf(
|2 >>>> selector=or([\node(className("top")),\node(className("bottom"))]),
|3 >>>> style=cytoNodeStyle(shape=CytoNodeShape::diamond())
|4 >>>> ),
|5 >>>> cytoStyleOf(
|6 >>>> selector=\node(className("bottom")),
|7 >>>> style=cytoNodeStyle(\background-color="yellow", color="black")
|8 >>>> ),
|9 >>>> cytoStyleOf(
|10 >>>> selector=\node(className("top")),
|11 >>> style=cytoNodeStyle(\background-color="orange")
|12 >>> )
|13 >>>];
list[CytoStyleOf]: [
cytoStyleOf(
style=cytoNodeStyle(shape=diamond()),
selector=or([
and([
node(),
className("top")
]),
and([
node(),
className("bottom")
])
])),
cytoStyleOf(
style=cytoNodeStyle(color="black",background-color="yellow"),
selector=and([
node(),
className("bottom")
])),
cytoStyleOf(
style=cytoNodeStyle(background-color="orange"),
selector=and([
node(),
className("top")
]))
]

we pick a sensible layout

rascal>lyt = defaultDagreLayout();
CytoLayout: dagreLayout(
animate=false,
automaticDagreEdgeStyle=true,
name=dagre(),
useDagreEdgeControlPoints=true,
spacingFactor=1,
ranker=\network-simplex())

we wrap the styling information into a configuration wrapper:

rascal>cfg = cytoGraphConfig(nodeClassifier=nodeClassifier, styles=styles, \layout=lyt);
CytoGraphConfig: cytoGraphConfig(
styles=[
cytoStyleOf(
style=cytoNodeStyle(shape=diamond()),
selector=or([
and([
node(),
className("top")
]),
and([
node(),
className("bottom")
])
])),
cytoStyleOf(
style=cytoNodeStyle(color="black",background-color="yellow"),
selector=and([
node(),
className("bottom")
])),
cytoStyleOf(
style=cytoNodeStyle(background-color="orange"),
selector=and([
node(),
className("top")
]))
],
nodeClassifier=function(|prompt:///|(0,113,<1,0>,<4,2>)),
layout=dagreLayout(
animate=false,
automaticDagreEdgeStyle=true,
name=dagre(),
useDagreEdgeControlPoints=true,
spacingFactor=1,
ranker=\network-simplex()))

and now we see the effect:

rascal>graph(g, cfg=cfg)

image now let's style some edges:

rascal>list[str] edgeClassifier(str from, str to) = ["grandparent" | <from, to > in g o g];
list[str] (str, str): function(|prompt:///|(0,84,<1,0>,<1,84>))

add another styling element

rascal>styles += [
|1 >>>> cytoStyleOf(
|2 >>>> selector=edge(className("grandparent")),
|3 >>>> style=defaultEdgeStyle()[\line-style="dashed"]
|4 >>>> )
|5 >>>>];
list[CytoStyleOf]: [
cytoStyleOf(
style=cytoNodeStyle(shape=diamond()),
selector=or([
and([
node(),
className("top")
]),
and([
node(),
className("bottom")
])
])),
cytoStyleOf(
style=cytoNodeStyle(color="black",background-color="yellow"),
selector=and([
node(),
className("bottom")
])),
cytoStyleOf(
style=cytoNodeStyle(background-color="orange"),
selector=and([
node(),
className("top")
])),
cytoStyleOf(
style=cytoEdgeStyle(
target-arrow-shape=triangle(),
width=3,
line-color="black",
source-arrow-color="black",
curve-style=\unbundled-bezier(),
label="data(label)",
line-style="dashed",
target-arrow-color="black",
color="red",
opacity="1",
source-arrow-shape=none(),
visibility="visible",
line-opacity="1"),
selector=and([
edge(),
className("grandparent")
]))
]

and draw again (while adding the grandparent edges too)

rascal>graph(g + (g o g), cfg=cytoGraphConfig(nodeClassifier=nodeClassifier, edgeClassifier=edgeClassifier, styles=styles, \layout=lyt))

image

alias NodeLinker​

A NodeLinker maps node identities to a source location to link to

loc (&T _id1)

function defaultNodeLinker​

The default node linker assumes any loc found in the node identity is a proper link.

loc defaultNodeLinker(/loc l)

default loc defaultNodeLinker(&T _)

alias NodeLabeler​

A NodeLabeler maps node identities to descriptive node labels

str (&T _id2)

alias NodeTipper​

A NodeTipper maps node identities to extended information about a node which is shown on demand

str (&T _id2)

function defaultNodeLabeler​

The default node labeler searches for any str`` in the identity, or otherwise a file name of a loc`

str defaultNodeLabeler(/str s)

str defaultNodeLabeler(loc l)

default str defaultNodeLabeler(&T v)

function defaultNodeTipper​

The default node tipper does nothing

default str defaultNodeTipper(&T _v)

alias NodeClassifier​

A NodeClassifier maps node identities to classes that are used later to select specific layout and coloring options.

list[str] (&T _id3)

function defaultNodeClassifier​

The default classifier produces no classes

list[str] defaultNodeClassifier(&T _)

alias EdgeClassifier​

An EdgeClassifier maps edge identities to classes that are used later to select specific layout and coloring options.

list[str] (&T _from, &T _to)

function defaultEdgeClassifier​

The default edge classifier produces no classes

list[str] defaultEdgeClassifier(&T _, &T _)

alias EdgeLabeler​

An EdgeLabeler maps edge identities to descriptive edge labels.

str (&T _source, &T _target)

function defaultEdgeLabeler​

The default edge labeler returns the empty label for all edges.

str defaultEdgeLabeler(&T _source, &T _target)

alias EdgeTipper​

An EdgeTipper maps edge identities to extended information about a node which is shown on demand

str (&T _from, &T _to)

function defaultEdgeTipper​

The default edge tipper does nothing

default str defaultEdgeTipper(&T _from, &T _to)

alias EdgeWeigher​

An EdgeWeigher decides for each individual edge how important it is to optimize its length (shorten it) with respect to the other edges.

int(&T _source, &T _target)

function defaultEdgeWeigher​

The default edge weigher returns 1 for all edges, so that each edge has the same importance in the optimization criterion.

int defaultEdgeWeigher(&T _source, &T _target)

function graph​

A graph plot from a binary list relation.

Content graph(lrel[&T x, &T y] v, CytoGraphConfig cfg = cytoGraphConfig())

Examples​

rascal>import vis::Graphs;
ok
rascal>graph([<x,x+1> | x <- [1..100]] + [<100,1>])

image

rascal>graph([<x,x+1> | x <- [1..100]] + [<100,1>], cfg=cytoGraphConfig(\layout=\defaultCircleLayout()))

image

Providing locations as node identities automatically transforms them to node links:

rascal>import vis::Graphs;
ok
rascal>import IO;
ok
rascal>d = [<|project://rascal/src/org/rascalmpl/library/|, e> | e <- |project://rascal/src/org/rascalmpl/library/|.ls];
lrel[loc,loc]: [
<|project://rascal/src/org/rascalmpl/library/|,|project://rascal/src/org/rascalmpl/library/Message.rsc|>,
<|project://rascal/src/org/rascalmpl/library/|,|project://rascal/src/org/rascalmpl/library/vis|>,
<|project://rascal/src/org/rascalmpl/library/|,|project://rascal/src/org/rascalmpl/library/ListRelation.rsc|>,
<|project://rascal/src/org/rascalmpl/library/|,|project://rascal/src/org/rascalmpl/library/List.rsc|>,
<|project://rascal/src/org/rascalmpl/library/|,|project://rascal/src/org/rascalmpl/library/Prelude.java|>,
<|project://rascal/src/org/rascalmpl/library/|,|project://rascal/src/org/rascalmpl/library/Exception.rsc|>,
<|project://rascal/src/org/rascalmpl/library/|,|project://rascal/src/org/rascalmpl/library/Map.rsc|>,
<|project://rascal/src/org/rascalmpl/library/|,|project://rascal/src/org/rascalmpl/library/Type.rsc|>,
<|project://rascal/src/org/rascalmpl/library/|,|project://rascal/src/org/rascalmpl/library/lang|>,
<|project://rascal/src/org/rascalmpl/library/|,|project://rascal/src/org/rascalmpl/library/Type.java|>,
<|project://rascal/src/org/rascalmpl/library/|,|project://rascal/src/org/rascalmpl/library/Content.rsc|>,
<|project://rascal/src/org/rascalmpl/library/|,|project://rascal/src/org/rascalmpl/library/ValueIO.rsc|>,
<|project://rascal/src/org/rascalmpl/library/|,|project://rascal/src/org/rascalmpl/library/String.rsc|>,
<|project://rascal/src/org/rascalmpl/library/|,|project://rascal/src/org/rascalmpl/library/Location.rsc|>,
<|project://rascal/src/org/rascalmpl/library/|,|project://rascal/src/org/rascalmpl/library/util|>,
<|project://rascal/src/org/rascalmpl/library/|,|project://rascal/src/org/rascalmpl/library/Grammar.rsc|>,
<|project://rascal/src/org/rascalmpl/library/|,|project://rascal/src/org/rascalmpl/library/Messages.java|>,
<|project://rascal/src/org/rascalmpl/library/|,|project://rascal/src/org/rascalmpl/library/Boolean.rsc|>,
<|project://rascal/src/org/rascalmpl/library/|,|project://rascal/src/org/rascalmpl/library/Relation.rsc|>,
<|project://rascal/src/org/rascalmpl/library/|,|project://rascal/src/org/rascalmpl/library/Node.rsc|>,
<|project://rascal/src/org/rascalmpl/library/|,|project://rascal/src/org/rascalmpl/library/analysis|>,
<|project://rascal/src/org/rascalmpl/library/|,|project://rascal/src/org/rascalmpl/library/Prelude.rsc|>,
<|project://rascal/src/org/rascalmpl/library/|,|project://rascal/src/org/rascalmpl/library/Set.rsc|>,
<|project://rascal/src/org/rascalmpl/library/|,|project://rascal/src/org/rascalmpl/library/IO.rsc|>,
<|project://rascal/src/org/rascalmpl/library/|,|project://rascal/src/org/rascalmpl/library/resource|>,
<|project://rascal/src/org/rascalmpl/library/|,|project://rascal/src/org/rascalmpl/library/index.md|>,
<|project://rascal/src/org/rascalmpl/library/|,|project://rascal/src/org/rascalmpl/library/ParseTree.rsc|>,
<|project://rascal/src/org/rascalmpl/library/|,|project://rascal/src/org/rascalmpl/library/DateTime.rsc|>
]
rascal>d += [<e,f> | <_, e> <- d, isDirectory(e), f <- e.ls];
lrel[loc,loc]: [
<|project://rascal/src/org/rascalmpl/library/|,|project://rascal/src/org/rascalmpl/library/Message.rsc|>,
<|project://rascal/src/org/rascalmpl/library/|,|project://rascal/src/org/rascalmpl/library/vis|>,
<|project://rascal/src/org/rascalmpl/library/|,|project://rascal/src/org/rascalmpl/library/ListRelation.rsc|>,
<|project://rascal/src/org/rascalmpl/library/|,|project://rascal/src/org/rascalmpl/library/List.rsc|>,
<|project://rascal/src/org/rascalmpl/library/|,|project://rascal/src/org/rascalmpl/library/Prelude.java|>,
<|project://rascal/src/org/rascalmpl/library/|,|project://rascal/src/org/rascalmpl/library/Exception.rsc|>,
<|project://rascal/src/org/rascalmpl/library/|,|project://rascal/src/org/rascalmpl/library/Map.rsc|>,
<|project://rascal/src/org/rascalmpl/library/|,|project://rascal/src/org/rascalmpl/library/Type.rsc|>,
<|project://rascal/src/org/rascalmpl/library/|,|project://rascal/src/org/rascalmpl/library/lang|>,
<|project://rascal/src/org/rascalmpl/library/|,|project://rascal/src/org/rascalmpl/library/Type.java|>,
<|project://rascal/src/org/rascalmpl/library/|,|project://rascal/src/org/rascalmpl/library/Content.rsc|>,
<|project://rascal/src/org/rascalmpl/library/|,|project://rascal/src/org/rascalmpl/library/ValueIO.rsc|>,
<|project://rascal/src/org/rascalmpl/library/|,|project://rascal/src/org/rascalmpl/library/String.rsc|>,
<|project://rascal/src/org/rascalmpl/library/|,|project://rascal/src/org/rascalmpl/library/Location.rsc|>,
<|project://rascal/src/org/rascalmpl/library/|,|project://rascal/src/org/rascalmpl/library/util|>,
<|project://rascal/src/org/rascalmpl/library/|,|project://rascal/src/org/rascalmpl/library/Grammar.rsc|>,
<|project://rascal/src/org/rascalmpl/library/|,|project://rascal/src/org/rascalmpl/library/Messages.java|>,
<|project://rascal/src/org/rascalmpl/library/|,|project://rascal/src/org/rascalmpl/library/Boolean.rsc|>,
<|project://rascal/src/org/rascalmpl/library/|,|project://rascal/src/org/rascalmpl/library/Relation.rsc|>,
<|project://rascal/src/org/rascalmpl/library/|,|project://rascal/src/org/rascalmpl/library/Node.rsc|>,
<|project://rascal/src/org/rascalmpl/library/|,|project://rascal/src/org/rascalmpl/library/analysis|>,
<|project://rascal/src/org/rascalmpl/library/|,|project://rascal/src/org/rascalmpl/library/Prelude.rsc|>,
<|project://rascal/src/org/rascalmpl/library/|,|project://rascal/src/org/rascalmpl/library/Set.rsc|>,
<|project://rascal/src/org/rascalmpl/library/|,|project://rascal/src/org/rascalmpl/library/IO.rsc|>,
<|project://rascal/src/org/rascalmpl/library/|,|project://rascal/src/org/rascalmpl/library/resource|>,
<|project://rascal/src/org/rascalmpl/library/|,|project://rascal/src/org/rascalmpl/library/index.md|>,
<|project://rascal/src/org/rascalmpl/library/|,|project://rascal/src/org/rascalmpl/library/ParseTree.rsc|>,
<|project://rascal/src/org/rascalmpl/library/|,|project://rascal/src/org/rascalmpl/library/DateTime.rsc|>,
<|project://rascal/src/org/rascalmpl/library/vis|,|project://rascal/src/org/rascalmpl/library/vis/Basic.rsc|>,
<|project://rascal/src/org/rascalmpl/library/vis|,|project://rascal/src/org/rascalmpl/library/vis/Graphs.rsc|>,
<|project://rascal/src/org/rascalmpl/library/vis|,|project://rascal/src/org/rascalmpl/library/vis/Charts.rsc|>,
<|project://rascal/src/org/rascalmpl/library/vis|,|project://rascal/src/org/rascalmpl/library/vis/Text.rsc|>,
<|project://rascal/src/org/rascalmpl/library/lang|,|project://rascal/src/org/rascalmpl/library/lang/java|>,
<|project://rascal/src/org/rascalmpl/library/lang|,|project://rascal/src/org/rascalmpl/library/lang/diff|>,
<|project://rascal/src/org/rascalmpl/library/lang|,|project://rascal/src/org/rascalmpl/library/lang/c90|>,
<|project://rascal/src/org/rascalmpl/library/lang|,|project://rascal/src/org/rascalmpl/library/lang/pico|>,
<|project://rascal/src/org/rascalmpl/library/lang|,|project://rascal/src/org/rascalmpl/library/lang/xforms|>,
<|project://rascal/src/org/rascalmpl/library/lang...
rascal>graph(d, \layout=defaultDagreLayout());

image here we adapt the node labeler to show only the last file name in the path of the location:

rascal>graph(d, \layout=defaultDagreLayout(), cfg=cytoGraphConfig(nodeLabeler=str (loc l) { return l.file; }));

image

function graph​

A graph plot from a ternary list relation where the middle column is the edge label.

Content graph(lrel[&T x, &L edge, &T y] v, CytoGraphConfig cfg=cytoGraphConfig())

Examples​

rascal>import vis::Graphs;
ok
rascal>graph([<x,2*x+1,x+1> | x <- [1..100]] + [<100,101,1>])

image

function graph​

A graph plot from a binary relation.

Content graph(rel[&T x, &T y] v, CytoGraphConfig cfg=cytoGraphConfig())

Examples​

rascal>import vis::Graphs;
ok
rascal>graph({<x,x+1> | x <- [1..100]} + {<100,1>})

image

function graph​

A graph plot from a ternary relation where the middle column is the edge label.

Content graph(rel[&T x, &L edge, &T y] v, CytoGraphConfig cfg=cytoGraphConfig())

Examples​

rascal>import vis::Graphs;
ok
rascal>graph({<x,2*x+1,x+1> | x <- [1..100]} + {<100,101,1>})

image

function cytoscape​

This core workhorse mixes the graph data with the configuration to obtain a visualizable CytoScape.js data-structure.

Produces an overall cytoscape.js wrapper which is sent as JSON to the client side.

Cytoscape cytoscape(list[CytoData] \data, CytoGraphConfig cfg=cytoGraphConfig())

This data-structure is serialized to JSON and communicated directly to initialize cytoscape.js. The serialization is done by the generic IO library under the hood of a Webserver.

function graphData​

Turns a rel[loc from, loc to] into a graph

list[CytoData] graphData(rel[loc x, loc y] v, CytoGraphConfig cfg=cytoGraphConfig())

function graphData​

Turns any rel[&T from, &T to] into a graph

default list[CytoData] graphData(rel[&T x, &T y] v, CytoGraphConfig cfg=cytoGraphConfig())

function graphData​

Turns any lrel[loc from, &L edge, loc to] into a graph

list[CytoData] graphData(lrel[loc x, &L edge, loc y] v, CytoGraphConfig cfg=cytoGraphConfig())

function graphData​

Turns any lrel[&T from, &L edge, &T to] into a graph

default list[CytoData] graphData(lrel[&T x, &L edge, &T y] v, CytoGraphConfig cfg=cytoGraphConfig())

function graphData​

Turns any lrel[loc from, loc to] into a graph

list[CytoData] graphData(lrel[loc x, loc y] v, CytoGraphConfig cfg=cytoGraphConfig())

function graphData​

Turns any lrel[&T from, &T to] into a graph

default list[CytoData] graphData(lrel[&T x, &T y] v, CytoGraphConfig cfg=cytoGraphConfig())

function graphData​

Turns any rel[loc from, &L edge, loc to] into a graph

list[CytoData] graphData(rel[loc x, &L edge, loc y] v, CytoGraphConfig cfg=cytoGraphConfig())

function graphData​

Turns any rel[&T from, &L edge, &T to] into a graph

default list[CytoData] graphData(rel[&T x, &L edge, &T y] v, CytoGraphConfig cfg=cytoGraphConfig())

data CytoNodeShape​

data CytoNodeShape  
= \ellipse()
| \triangle()
| \round-triangle()
| \rectangle()
| \round-rectangle()
| \bottom-round-rectangle()
| \cut-rectangle()
| \barrel()
| \rhomboid()
| \diamond()
| \round-diamond()
| \pentagon()
| \round-pentagon()
| \hexagon()
| \round-hexagon()
| \concave-hexagon()
| \heptagon()
| \round-heptagon()
| \octagon()
| \round-octagon()
| \star()
| \tag()
| \round-tag()
| \vee()
| \polygon()
;

data Cytoscape​

Overall cytoscape.js object for sending to the client side.

data Cytoscape  
= cytoscape(
list[CytoData] elements = [],
list[CytoStyleOf] style=[],
CytoLayout \layout = cytolayout(),
list[HTMLElement] header = [],
list[HTMLElement] footer = []
)
;

data CytoData​

data CytoData  
= cytodata(CytoElement \data, str classes="")
;

data CytoElement​

data CytoElement  
= \node(str id, str label=id, str tip = "", str editor="|none:///|")
| \edge(str source, str target, str id="<source>-<target>", str label="", str tip = "", int weight = 1)
;

data CytoHorizontalAlign​

data CytoHorizontalAlign  
= left()
| center()
| right()
| auto()
;

data CytoVerticalAlign​

data CytoVerticalAlign  
= top()
| center()
| bottom()
| auto()
;

data CytoArrowHeadStyle​

data CytoArrowHeadStyle  
= triangle()
| \triangle-tee()
| \circle-triangle()
| \triangle-cross()
| \triangle-backcurve()
| vee()
| tee()
| square()
| circle()
| diamond()
| chevron()
| none()
;

data CytoTextWrap​

data CytoTextWrap  
= none()
| wrap()
| ellipses()
;

data CytoCurveStyle​

data CytoCurveStyle  
= bezier()
| \unbundled-bezier()
| straight()
| segments()
| \straight-triangle()
| taxi()
| haystack()
;

data CytoStyleOf​

data CytoStyleOf  
= cytoStyleOf(
CytoSelector selector = \node(),
CytoStyle style = cytoNodeStyle()
)
;

function cytoNodeStyleOf​

CytoStyleOf cytoNodeStyleOf(CytoStyle style)

function cytoEdgeStyleOf​

CytoStyleOf cytoEdgeStyleOf(CytoStyle style)

function flattenClasses​

flattens a list of classes to a single string

str flattenClasses(list[str] classes)

function defaultNodeStyle​

Instantiates a default node style

CytoStyle defaultNodeStyle()

Because the JSON writer can not instantiate default values for keyword fields, we have to do it manually here.

function defaultEdgeStyle​

Instantiates a default edge style

CytoStyle defaultEdgeStyle()

Because the JSON writer can not instantiate default values for keyword fields we have to do it manually here.

data CytoFontWeight​

data CytoFontWeight  
= normal()
| lighter()
| bold()
| bolder()
;

data CytoStyle​

data CytoStyle  
= cytoNodeStyle(
str visibility = "visible", /* hidden, collapse */
str opacity = "1",
str width = "label",
str padding = "10pt",
str color = "white",
str \text-opacity = "1",
str \font-family = "",
str \font-size = "12pt",
str \font-style = "",
CytoFontWeight \font-weight = normal(),
str \background-color = "blue",
str label = "data(label)",
CytoNodeShape shape = CytoNodeShape::ellipse(),
CytoHorizontalAlign \text-halign = CytoHorizontalAlign::center(),
CytoVerticalAlign \text-valign = CytoVerticalAlign::\top(),
CytoTextWrap \text-wrap = CytoTextWrap::none(),
str \text-max-width = "100px",
CytoHorizontalAlign \text-justification = CytoHorizontalAlign::center(),
int \line-height = 1
)
| cytoEdgeStyle(
str visibility = "visible", /* hidden, collapse */
str opacity = "1",
str \line-opacity = "1",
int width = 3,
str \line-color = "black",
str \line-style = "solid", /* dotted, dashed */
str color = "red",
str \target-arrow-color = "black",
str \source-arrow-color = "black",
CytoArrowHeadStyle \target-arrow-shape = CytoArrowHeadStyle::triangle(),
CytoArrowHeadStyle \source-arrow-shape = CytoArrowHeadStyle::none(),
CytoCurveStyle \curve-style = CytoCurveStyle::\unbundled-bezier(),
int \source-text-offset = 1,
int \target-text-offset = 1,
str label = "data(label)"
)
;

data CytoSelector​

A combinator language that translates down to strings in JSON

data CytoSelector  
= \node()
| \edge()
| \id(str id)
| \not(CytoSelector sel)
| \and(list[CytoSelector] conjuncts)
| \or(list[CytoSelector] disjuncts)
| \equal(str field, str \value)
| \equal(str field, int limit)
| \greater(str field, int limit)
| \less(str field, int limit)
| \greaterEqual(str field, int limit)
| \lessEqual(str field, int limit)
| \className(str)
| \hover()
| \hover-in()
| \hover-out()
| \hover-source()
| \hover-target()
| animated()
| unanimate()
| selected()
| unselected()
| selectable()
| unselectable()
| locked()
| unlocked()
| visible()
| hidden()
| transparent()
| backgrounding()
| nonbackgrounding()
| grabbed()
| free()
| grabbable()
| ungrabbable()
| active()
| inactive()
| touch()
| removed()
| inside()
| parent()
| childless()
| child()
| nonorphan()
| compound()
| loop()
| simple()
;
  • For field names you can use the names, or the dot notation for array indices and fields of objects: "labels.0", "name.first".
  • node() selects all nodes
  • edge() selects all edges

Benefits​

  • Cyto Selector represents the full power of Cytoscape selector syntax
  • If multiple selectors apply to a node or an edge, the proposed styles are merged up to attribute name collisions. The last one in the list always wins in case of a collision. Merging helps in keeping CytoSelectors plain and simple.
  • Cyto Selector offers hover, hover-in and hover-out on top of the standard CytoScape selectors. These can be used to select styles for:
    1. hover: the node that is currently hovered.
    2. hover-in: edges coming into the hovered node and their source node.
    3. hover-out: edges going out of the hovered node and their target node.

Pitfalls​

  • not, and, and or can not be nested freely (as the grammar does suggest); this will lead to failure to select anything at all. The or must be outside and the and must be inside. You can nest one level of and under an outermost level of or. Illegal nesting will lead to an early runtime exception.

function hover​

Selects hovered nodes and edges

CytoSelector hover()

Nodes and edges which are "hovered" by the mouse pointer automatically receive this class on entering there respective boundaries, and automatically loose it again on leaving those boundaries.

function \hover-in​

Selectes incoming edges to a hovered node and their source nodes

CytoSelector \hover-in()

Edges for which the target nodes is "hovered" by the mouse pointer automatically receive this class on entering there respective boundaries of said node, and automatically loose it again on leaving those boundaries. Also the source nodes of these edges are tagged with the same class.

function \hover-out​

Selectes outgoing edges to a hovered node and their target nodes

CytoSelector \hover-out()

Edges for which the source nodes is "hovered" by the mouse pointer automatically receive this class on entering there respective boundaries of said node, and automatically loose it again on leaving those boundaries. Also the target nodes at the end of these edges are tagged with this class.

function \hover-source​

selects the source nodes of a hovered edge

CytoSelector \hover-source()

Nodes which are the source node of a "hovered" edge by the mouse pointer automatically receive this class on entering there respective boundaries of said edge, and automatically loose it again on leaving those boundaries.

function \hover-target​

Selects the target node of a hovered edge

CytoSelector \hover-target()

Nodes which are the target node of a "hovered" edge by the mouse pointer automatically receive this class on entering there respective boundaries of said edge, and automatically loose it again on leaving those boundaries.

function \node​

Short-hand for a node with a single condition

CytoSelector \node(CytoSelector condition)

function \edge​

Short-hand for a node with a single condition

CytoSelector \edge(CytoSelector condition)

function more​

Utility to generate class attributes with multiple names consistently.

str more(set[str] names)

function formatCytoSelector​

Serialize a ((CytoSelector)) to string for client side expression.

str formatCytoSelector(\node(), bool nested=false)

str formatCytoSelector(\edge(), bool nested=false)

str formatCytoSelector(\id(str i), bool nested=false)

str formatCytoSelector(\not(CytoSelector sel), bool nested=false)

str formatCytoSelector(and(list[CytoSelector] cjs), bool nested=false)

str formatCytoSelector(or(list[CytoSelector] cjs), bool nested=false)

str formatCytoSelector(className(str class), bool nested=false)

str formatCytoSelector(equal(str field, str val), bool nested=false)

str formatCytoSelector(equal(str field, int lim), bool nested=false)

str formatCytoSelector(greater(str field, int lim), bool nested=false)

str formatCytoSelector(greaterEqual(str field, int lim), bool nested=false)

str formatCytoSelector(lessEqual(str field, int lim), bool nested=false)

str formatCytoSelector(less(str field, int lim), bool nested=false)

str formatCytoSelector(animated(), bool nested=false)

str formatCytoSelector(unanimate(), bool nested=false)

str formatCytoSelector(selected(), bool nested=false)

str formatCytoSelector(unselected(), bool nested=false)

str formatCytoSelector(selectable(), bool nested=false)

str formatCytoSelector(unselectable(), bool nested=false)

str formatCytoSelector(locked(), bool nested=false)

str formatCytoSelector(unlocked(), bool nested=false)

str formatCytoSelector(visible(), bool nested=false)

str formatCytoSelector(hidden(), bool nested=false)

str formatCytoSelector(transparent(), bool nested=false)

str formatCytoSelector(backgrounding(), bool nested=false)

str formatCytoSelector(nonbackgrounding(), bool nested=false)

str formatCytoSelector(grabbed(), bool nested=false)

str formatCytoSelector(free(), bool nested=false)

str formatCytoSelector(grabbable(), bool nested=false)

str formatCytoSelector(ungrabbable(), bool nested=false)

str formatCytoSelector(active(), bool nested=false)

str formatCytoSelector(inactive(), bool nested=false)

str formatCytoSelector(touch(), bool nested=false)

str formatCytoSelector(removed(), bool nested=false)

str formatCytoSelector(inside(), bool nested=false)

str formatCytoSelector(parent(), bool nested=false)

str formatCytoSelector(childless(), bool nested=false)

str formatCytoSelector(child(), bool nested=false)

str formatCytoSelector(nonorphan(), bool nested=false)

str formatCytoSelector(compound(), bool nested=false)

str formatCytoSelector(loop(), bool nested=false)

str formatCytoSelector(simple(), bool nested=false)

data CytoLayoutName​

Choice of different node layout algorithms.

data CytoLayoutName  
= grid()
| circle()
| breadthfirst()
| cose()
| dagre()
;

The different algorithms use heuristics to find a layout that shows the structure of a graph best. Different types of graph data call for different algorithms:

  • grid is best when there are very few edges or when edges are not important. The edge relation is not used at all for deciding where each node will end up. Grid is typically used for an initial exploration of the graph. It is very fast.
  • circle puts all nodes on the edge of a circle and draws edges between them. The order on the circle is arbitrary. This layout fails on larger collections of nodes because the points on the circle will become really small and indistinguishable. However for graphs with less than 100 nodes it provides a quick and natural overview.
  • breadthfirst computes a breadth-first spanning tree, and uses path length to decide on which layer each node will reside. Cross-edges (between branches) and back-edges are allowed but if there are many the graph will be messy. So this layout is best when you have a mostly hierarchical graph. Examples are flow charts and dependency graphs.
  • cose is a so-called "force-directed" layout. The edges become springs that both push nodes apart as well as pull them together. Nodes drag on the surface but have an initial momentum such that they can find a spot on the plain. This layout is very natural for scale-free networks such as biological organisms, friends graphs and software ecosystems.

function hierarchical​

An alias for dagre layout for documentation purposes.

CytoLayoutName hierarchical()

Dagre is a hierarchical graph layout.

data CytoLayout​

data CytoLayout (CytoLayoutName name = dagre(), bool animate=false) 
= cytolayout()
| breadthfirstLayout(
CytoLayoutName name = CytoLayoutName::breadthfirst(),
num spacingFactor= 1,
list[str] roots = [],
bool circle=false,
bool grid=!circle,
bool directed=false
)
| gridLayout(
CytoLayoutName name = CytoLayoutName::grid(),
int rows=2,
int cols=2,
bool avoidOverlap=true,
num spacingFactor=.1
)
| circleLayout(
CytoLayoutName name = CytoLayoutName::circle(),
bool avoidOverlap=true,
num spacingFactor=.1
)
| coseLayout(
CytoLayoutName name = cose()
)
| dagreLayout(
CytoLayoutName name = dagre(),
int rankSep=-1,
int nodeSep=-1,
int edgeSep=-1,
int padding=-1,
bool useDagreEdgeControlPoints = true,
bool automaticDagreEdgeStyle = true,
num spacingFactor = .1,
DagreRanker ranker = \network-simplex() // network-simples tight-tree, or longest-path
)
;

data DagreRanker​

data DagreRanker  
= \network-simplex()
| \tight-tree()
| \longest-path()
;

function defaultCoseLayout​

CytoLayout defaultCoseLayout()

function defaultCircleLayout​

CytoLayout defaultCircleLayout(bool avoidOverlap=true, num spacingFactor=.1)

function defaultGridLayout​

CytoLayout defaultGridLayout(int rows=2, int cols=rows, bool avoidOverlap=true, num spacingFactor=.1)

function defaultBreadthfirstLayout​

CytoLayout defaultBreadthfirstLayout(num spacingFactor=.1, bool circle=false, bool grid=!circle, bool directed=false)

function defaultDagreLayout​

CytoLayout defaultDagreLayout(num spacingFactor=1)

function graphServer​

this is the main server generator for any graph value

Response (Request) graphServer(Cytoscape ch)

Given a Graph value this server captures the value and serves it as a JSON value to the HTML client generated by plotHTML.

function plotHTML​

default HTML wrapper for a cytoscape.js graph

HTMLElement plotHTML(list[HTMLElement] header = [], list[HTMLElement] footer = [])

This client features:

  • cytoscape.js loading with cytoscape-dagre and dagre present.
  • fetching of graph data via http://localhost/cytoscape URL
  • clickable links in every node that has an 'editor' data field that holds a loc, via the http://localhost/editor?src=loc URL
  • full screen graph view

This client mirrors the server defined by Graph Server.

function tooltipCSS​

HTMLElement tooltipCSS()

function hoverListeners​

HTMLElement hoverListeners()

function toEditorClick​

HTMLElement toEditorClick()

function tooltipListeners​

HTMLElement tooltipListeners()