module vis::Graphs
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);
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)
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))

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>])

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

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());
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; }));

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>])

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>})

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>})

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 nodesedge()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-inandhover-outon top of the standard CytoScape selectors. These can be used to select styles for:hover: the node that is currently hovered.hover-in: edges coming into the hovered node and their source node.hover-out: edges going out of the hovered node and their target node.
Pitfalls
not,and, andorcan 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 ofandunder an outermost level ofor. 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:
gridis 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.circleputs 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.breadthfirstcomputes 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.coseis 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/cytoscapeURL - clickable links in every node that has an 'editor' data field that holds a
loc, via thehttp://localhost/editor?src=locURL - 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()