Sigma.js Drop-in tool
Shared under MIT-license, developed at the KULeuven for DARIAH-BE Styling by Yanne Broux
NOTICE: draft version
Table of content
// will be made after the draft has been okayed.
Introduction
Dependencies
This tool is powered by the sigma.js library, as such it will require the sigma.js files. All relevant files need to be linked in the head
section of your HTML-page.
There's also a need for jQuery
Intended use
This tool is developed to be used as an alternative to gephi-files. It specifically targets websites that work with continuously growing databases and don't want to spend time on recreating a gephi-graph after each database-update or websites who wish to generate a network on the fly.
Data can be fed to the applet by PHP or HTML.
Implementation
- Download the necessary sigma.js files.
- Go to the sigma.js GitHub page.
- Download the library.
- Copy the following folders to your own project folder:
- plugins/sigma.layout.forceAtlas2
- plugins/sigma.renderers.edgeLabels
- plugins/sigma.renderers.edgeLabels
- plugins/sigma.plugins.dragNodes
- plugins/sigma.plugins.relativeSize
- plugins/sigma.layout.noverlap
- plugins/sigma.exporters.svg
- plugins/sigma.renderers.snapshot
- plugins/sigma.plugins.filter
- plugins/sigma.plugins.animate
- plugins/sigma.renderers.parallelEdges
- src/renderers/canvas
- src/middlewares
- Download FruchtermanReingold from linkurious.
- Go to the linkurious.js GitHub page
- Download the library
- Copy the following folder to your own project folder:
- plugins/sigma.layouts.fruchtermanReingold
- Create your HTML or PHP document
- In the
head
section you'll need to link all dependencies, which are the plugins you coppied and the minified version of sigma.js. The minified version should come before calling additional plugins. The example below references sigma.min.js in the same folder as you store your index.html file, however, it can be stored elsewhere if referrenced correctly.
<script src="sigma.min.js"></script>
<script src="plugins/sigma.layout.forceAtlas2/worker.js"></script>
<script src="plugins/sigma.layout.forceAtlas2/supervisor.js"></script>
<script src="plugins/sigma.renderers.edgeLabels/settings.js"></script>
<script src="plugins/sigma.renderers.edgeLabels/sigma.canvas.edges.labels.curve.js"></script>
<script src="plugins/sigma.plugins.animate/sigma.plugins.animate.js"></script>
<script src="plugins/sigma.renderers.edgeLabels/sigma.canvas.edges.labels.def.js"></script>
<script src="plugins/sigma.renderers.edgeLabels/sigma.canvas.edges.labels.curvedArrow.js"></script>
<script src="plugins/sigma.plugins.dragNodes/sigma.plugins.dragNodes.js"></script>
<script src="plugins/sigma.plugins.relativeSize/sigma.plugins.relativeSize.js"></script>
<script src="plugins/sigma.layout.noverlap/sigma.layout.noverlap.js"></script>
<script src="src/renderers/canvas/sigma.canvas.nodes.def.js"></script>
<script src="plugins/sigma.exporters.svg/sigma.exporters.svg.js"></script>
<script src="plugins/sigma.renderers.snapshot/sigma.renderers.snapshot.js"></script>
<script src="plugins/sigma.layouts.fruchtermanReingold/sigma.layout.fruchtermanReingold.js"></script>
<script src="plugins/sigma.plugins.filter/sigma.plugins.filter.js"></script>
<script src="src/middlewares/sigma.middlewares.rescale.js"></script>
<script src="plugins/sigma.renderers.parallelEdges/utils.js"></script>
<script src="plugins/sigma.renderers.parallelEdges/sigma.canvas.edges.labels.curve.js"></script>
<script src="plugins/sigma.renderers.parallelEdges/sigma.canvas.edges.curvedArrow.js"></script>
<script src="plugins/sigma.renderers.parallelEdges/sigma.canvas.edges.curve.js"></script>
<script src="plugins/sigma.renderers.parallelEdges/sigma.canvas.edgehovers.curvedArrow.js"></script>
<script src="plugins/sigma.renderers.parallelEdges/sigma.canvas.edgehovers.curve.js"></script>
<!-- JQUERY-->
<script src="https://ajax.googleapis.com/ajax/libs/jquery/3.2.1/jquery.min.js"></script>
<script src="https://code.jquery.com/jquery-1.12.4.js"></script>
<script src="https://code.jquery.com/ui/1.12.1/jquery-ui.js"></script>
<!-- JSOC -->
<link href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/4.7.0/css/font-awesome.min.css" rel='stylesheet' type='text/css'>
<script type="text/javascript" src="https://cdn.jsdelivr.net/jquery.jssocials/1.4.0/jssocials.min.js"></script>
<link type="text/css" rel="stylesheet" href="https://cdn.jsdelivr.net/jquery.jssocials/1.4.0/jssocials.css" />
<link type="text/css" rel="stylesheet" href="https://cdn.jsdelivr.net/jquery.jssocials/1.4.0/jssocials-theme-flat.css" />
<!-- custom dariah script -->
<script type="text/javascript" src="vis.js"></script>
<!-- custom styling -->
<link rel="stylesheet" type="text/css" href="http://ajax.googleapis.com/ajax/libs/jqueryui/1.8/themes/base/jquery-ui.css">
<link rel="stylesheet" href="style.css">
You can now close the head
tag
- Prepare the
body
tag.
-
Create a div with the id "blackboard"
<div id="blackboard"></div>
-
Open a
script
tag and call the function with two arguments.- The first argument is a JavaScript variable called data and needs to be initiated before you call the function. For static websites you can hardcode the JSON-structure in the HTML-document. If you're using PHP, you can use a MYSQL-query and format it before passing it down to the JavaScript function. Please take a look at the chapter formatting data
- The second argument is the method argument, this is a string that affects the appearance of the rendered graph. There are two arguments hardcoded in the script.
- "fast"
- Designed for large networks.
- No support for edgehovering (to increase performance)
- No labels (to increase performance)
- Batchedgesdrawing per 2000 (to increase performance)
- Hides edges on moving (to increase performance)
- Disabled Fruchterman-Reingold (there's no point in having this in large networks.)
- "precise"
- Designed for smaller networks.
- Edgehovering and edgeclick events are active
- With labels
- All edges are drawn at the same time
- Edges are visible at all time
- All layout functions are active
- "fast"
<script> create_spaghetti(data,method) </script> ```
After this first script
tag open a second tag to enable JSocials integration; this will help users to share the link to your website/dataset.
<script>
// JSOC injection caller
$("#share").jsSocials({
shares: ["email", "twitter", "facebook", "googleplus"]
});
</script>
You can now close the body
tag.
Formatting Data
Unlike traditional JavaScript GEXF-viewers, this tool takes JSON as data-input. You'll need to properly format the edges and nodes for this to work. Read through this chapter before creating your PHP-script as it will save you a ton of time.
Edges
Edges are the lines that describe a relation between two nodes. They have a source and a target, meaning they have a certain direction. Each edge is also unique, and indicated by an ID.
Required components:
- id: This has to be a unique identifier (integer). You cannot have more than one edge with the same id.
- target: This is the destination of an edge, it is a node-id. (integer)
- source: This is where an edge originates, it is a node-id (integer)
Optional components:
You can add any optional components you want, to describe the relation between to nodes. Use keys that do NOT match the required components. If you add more components, then you'll have to add these to the codebase. For this see the chapter code customization.
Nodes
Required components:
- id: This is a unique identifier (integer). You cannot have more than one node with the same id.
Not required, but advised:
- label: This can be the name for a node. It is displayed when it's hovered and used in the information panel at Node-information, incoming relations and outgoing relations.
Optional components:
These variables are not required by the JavaScript application, but if you have them, they'll give you more control over the end-result of the graph.
- x: The X-coordinate of a node; this positions the node on the canvas.
- See code customization ==> positioning
- y: The Y-coordinate of a node; this positions the node on the canvas.
- See code customization ==> positioning
- size: This determines how large a node must be.
- See code customization ==> sizing
- color:
- See code customization ==> color
Valid JSON data
introduction
JSON or JavaScript Object Notation is a lightweight way of transmitting data from a server to a web browser. The transmitted data consists of text-only (so if your graph contains images for each node, you can't send the image directly, but you can send the URI or URL as text and use it later.).
Constructing JSON data
First we'll give our JSON-data a name. This has to be done between <script>
tags.
So in your HTML or PHP script you'll have code like this:
<script>
var json_data = {};
// call the JavaScript function with this data:
create_spaghetti(json_data, "precise")
</script>
The above code will send an empty JSON-object to the JavaScript function. To render a graph and parse valid JSON, the variable json_data
will always need to contain two arrays. One array for the edges, a second array for the nodes.
Insert these arrays in json_data
<script>
var json_data =
{"edges":[],
"nodes":[]
};
// call the JavaScript function with this data:
create_spaghetti(json_data, "precise")
</script>
The code above calls the function, but has no valid edges or nodes. For this every edge needs to be inserted between the []
of the key edges
and every node needs to be inserted between the []
of the key nodes
.
We'll update the code above to reflect a network of four nodes and eight edges.
<script>
var json_data =
{"edges":[
{"source":"0","target":"1","id":"0"},
{"source":"0","target":"3","id":"1"},
{"source":"1","target":"2","id":"2"},
{"source":"1","target":"3","id":"3"},
{"source":"1","target":"0","id":"4"},
{"source":"2","target":"1","id":"5"},
{"source":"2","target":"3","id":"6"},
{"source":"3","target":"0","id":"7"}
],
"nodes":[
{"id":"0","label":"Zeus"},
{"id":"1","label":"Poseidon"},
{"id":"2","label":"Herakles"},
{"id":"3","label":"Persephone"}
]
};
// call the JavaScript function with this data:
create_spaghetti(json_data, "precise")
</script>
The code above is enough to render a network. You can add more components to edges or nodes. Every component consists of a key and a value. Both are enclosed by quotes and separated by a colon. Components are separated from each other by commas.
This tool is specifically targeted at situations where the graph-data is generated on the fly and/or updated continuously. i.e. for situations where data is queried by the user dynamically and/or where a research team keeps adding nodes/edges to a database. As such it makes little sense to call the JavaScript function with static data as in this example.
A better practice is to combine PHP and JavaScript by making the json_data
variable on the fly.
Helper tools
When working with JSON it's important that all brackets, braces, commas, colons and quotes are in their respective places. Misplacing one may lead to unreadable code. In situations where the graph isn't rendered, check the developer's console of your browser. If it says that there's a syntax error which originates in the html or php file, then chances are real you might have improperly formatted JSON.
Fortunately there are tools to detect this. A good online tool that seems to have little issues with larger JSON-objects is JSONlint. You can paste your JSON-code in there and click the Validate JSON button.
An alternative is to use a JSON validator plugin in your web browser. For Chromium based browsers you can use Json Borne. This tool will help you check if your JSON markup is valid (In some cases this tool might say that your markup is invalid, but the sigma libraries has built-in methods to handle this.).
Passing Node components from data to graph g.
Node components need to be pushed to the node array in var g
. This happens by a for loop
. This loops over all the data in graph.nodes
, takes specific keys from it, and pushes those keys in g.nodes
together with the corresponding value.
You'll need to set up this behavior by editing the code. In the main JavaScript file look for a comment //customize this code to push components from your data to g.nodes
The for loop
below that comment consists of two major parts. The first part creates variables and assigns a value to this.
Example: var id = graph.nodes[i]["id"];
The [i]
is used to iterate over graph.nodes and can be read as the ith element. Te string inside the second set of brackets, in this case ["id"]
relates to the keys in the JSON-data. It says that the variable id is value related to that "id"
key for the nth
element of graph.nodes.
This has to be done for all components you want to push to g.nodes, make sure that every added component ends with a semicolon ;
An alternative to retrieving the value for a variable from graph.nodes
is to determine it on the fly. This is done by relying on functions. These functions are created specifically for one type of variable, i.e. the position, color or size variables which are determined by positioner(coord, i)
function, determincolor()
and the determinesize(i)
function.
positioner()
The positioner function takes in two arguments, a string, "x" or "y" and the iterator i
. It will return the desired position for the x and y coordinates.
Depending on the configuration of the code (see: code customization ==> positioning), it will either return a calculated position, or extract the position from graph.nodes
determinecolor()
This function dynamically assigns colors to nodes it takes one argument which can be chosen by you. In the provided JavaScript code, it assigns colors based on the variable typology
, which was extracted from graph.nodes
earlier. As an alternative the nationality could also be used. If you add other variables (for instance: gender, profession, ...) that can be color-coded, you'll need to keep the following in mind:
- Don't overdo it with colors, stick to a maximum of seven discernible colors.
- The argument used by the function must be extracted from
graph.nodes
before passing it to the function. - You'd need to update the function called determinecolor(). (See: code customization ==> color)
By using the canvas-engine in sigma.js, the following ways of denoting colors are recommended:
- HEX values: string e.g.: "#ffffff" (values between 0 and f)
- RGB values: string e.g.: "rgb(125,210,65)" (comma separated values between 0 and 255)
- RGBA values: string e.g.: "rgba(125,210,65,0.3)" (first three values are comma separated between 0 and 255. The 'a' value is a float between 0 and 1, indicating the transparency).
determinesize()
This function takes in one argument, the iterator i
. Based on how the script is configured it will return a fixed size, which is later overwritten by a part of the sigma.js library or it will extract the size from graph.nodes
. (See: Code customization ==> sizing
Adding a new component to your nodes.
In this section you'll learn how to add new components to each node. A component is used by the filter and gets automatically displayed in the information-pane on the left side of the screen.
Adding components consists of two steps (in some cases it can be done in one step, but to prevent confusion this documentation will only discuss the two-step method as it will work in all cases).
In the first step create a new variable and give it a descriptive name without spaces. Then set it equal to a certain key in graph.nodes
. Since we want to do this for every note, we need to include the iterator i
and the source graph.nodes
. To conclude this first step, we'll need to call a key for the sake of this document, we'll call the key day_of_birth
. Since this is pure JavaScript, you'll need to end each variable declaration by a semicolon ;
. A valid declaration looks like this:
var my_component = graph.nodes[i]["day_of_birth"];
If we make it more abstract you write the code like this:
var name = source[iterator]["key"];
In the second step you'd need to push the declared variable to g.nodes
. This happens in this code section:
g.nodes.push({
component: variable_name,
component2: other_variable,
...
})
This code section consists of a key, a colon and a value. At this stage it is important to use keys that are self-explanatory as these keys are displayed in the filter and the information pane.
A key can be written down as a string by the help of "
, this is needed if the key contains a space. If your key does not contain a space, it can be written down without "
. You can not use the same key twice!
There are some keys, which must remain in the push-section, if absent the graph won't render. These are:
- id
- x
- y
Some other keys are of great importance to the functionality of this JavaScript application.
- label: is used to display node information in the information pane and to show connected nodes.
All other keys can be discarded or replaced by your own, however some keys hold special meaning to sigma:
- color: is used to color a graph (if absent all nodes will render white)
- size: is used to determine the size of a graph. If absent Sigma will auto-determine the size unless
size_is_known=true
(see: code customization ==> sizing).
Pushing the variable you declared in step one happens like this:
Birthmonth: my_component,
If we make it more abstract you write the code like this:
key: variable_from_step_1,
Alternatively, you can have more complex names for the key, in that case you need to write the key as a string. This is done with the help of quotes.
"Month of birth": my_component,
If we make it more abstract you write the code like this:
"key as a string": variable_from_step_1,
Note that every key:value pair is separated by a comma ,
.
Passing Edge components from data to graph g.
Edges can be configured in a manner similar to the nodes. However, note that edge-hovering can be disabled. If it is disabled, less data is accessible in the graph itself. To make up for this, edge-information can be displayed in the information pane if it's explicitly asked by clicking on the E? next to each incoming or outgoing relation.
Editing edges-components happens in a way similar to adding nodes-components. The section responsible for this is indicated by a comment: // Customize this code to push components from your data to g.edges.
Edges can contain information on the type of relation that exists between two nodes. (e.g. family, author_of, inhabitant, etc...).
There are some keys which must remain in the push-section. These are:
- id
- source
- target
Other keys are optional, if absent, the sigma library will resort to its default values:
- color: takes the color of the source-node.
- type: becomes a straight line.
- size: becomes a small line.
The same logic applies to pushing components to edges as to nodes. However, it's worth the time to take a closer look at how edges are pushed
for (var i = 0; i < graph.edges.length; i++){
// new variables go here.
g.edges.push({
id: graph.edges[i]["id"],
source: graph.edges[i]["source"],
target: graph.edges[i]["target"],
color: edgescol,
size: 1,
type:"line",
});
};
As can be seen, the same construction is set-up, a for loop with an iterator i
loops over graph.edges
.
At every iteration it pushes the ith
item to g.edges
When pushing to g.edges
, the program assumes that the data you sent it, uses "id", "source" and "target" as keys in graph.edges
. If you use other keys, change it here, otherwise your edges are undefined
.
Adding a new component to your edges.
For the sake of giving an example we'll push the type of relation that exists between family-members to the edges. For this we assume that the data that was passed to the script holds this type of information for every edge stored under the key fam_rel
.
We'll use the same two-step process, as before.
In the first step, look for //new variables go here.
inside the for-loop; there you need to declare a new variable and set it equal to the value in graph.edges
.
You code should look like this:
var type_of_relation = graph.edges[i]["fam_rel"];
If we make it more abstract the code works like this:
var name_of_variable = source[iterator]["key"];
Notice that every new var declaration has to end in a semicolon ;
In the second step edit the part that pushes key:value-pairs to g.edges
Just like before create a descriptive key-name for instance "Family relation" and assign the variable from step one as a value.
Since the key used in this example contains a space, you need to use quotes. Your code should look like this:
"Family relation": type_of_relation,
Notice that each key:value-pair is separated by a ,
.
If everything is done correctly, the entire for-loop should look like this:
for (var i = 0; i < graph.edges.length; i++){
// new variables go here.
var type_of_relation = graph.edges[i]["fam_rel"];
g.edges.push({
id: graph.edges[i]["id"],
source: graph.edges[i]["source"],
target: graph.edges[i]["target"],
color: edgescol,
size: 1,
type:"line",
"Family relation": type_of_relation,
});
};
Code customization
This visualization tool allows for some convenient modifications at the top of the script. It mostly consists of boolean values (true/false). All values are indicated by a small comment. In this section of the documentation you'll find a more detailed description.
color
The function determinecolor() is responsible for assigning colors; it gets called with one argument and returns a color value (valid color values are RGBA, RGB and HEX).
Colors and what determines them need to be hard-coded in the script. Let's look at the function and see how to modify it.
// Assigning colors to type
function determinecolor(type){
if (type==="author"){return "rgba(97,125,180,0.4)";}
else if (type==="mythological figure"){return "rgba(102,143,60,0.4)";}
else if (type==="transcriber"){return "rgba(0, 255, 0, 0.4)";}
else if (type==="bard"){return "rgba(255, 0, 255,0.4)";}
else if (type==="god"){return "rgba(94, 0, 163,0.4)";}
else if (type==="demi god"){return "rgba(0, 255, 255,0.4)";}
else{return"rgba(198,88,62,0.4)";}
};
This function checks if the argument matches a certain string, this happens in the if()
, else if()
and else
section of each line. If there's a match, it will return a certain color-code. In this case, it returns rgba-values.
So if the function gets called with "transcriber" as argument it'll iterate over the first and second if-statement without returning any color. When it reaches the third line, it will return "rgba(102,143,60,0.4)".
Modifying This function can easily be modified. Let's consider a situation where there are four possible types that determine the color of a node.
- dog
- cat
- horse
- cow
For each of the animals (types) above, we want a specific HEX-color:
- dog ==> "#42f48c"
- cat ==> "#417df4"
- horse ==> "#f141f4"
- cow ==> "#ce1818"
We'll also assume that, in the future, a fifth animal (type) may be present in the data or that some nodes may be invalid. For this we will use the else-case. The value relate to this else case will be returned if none of the if
and else if
statements were matched. Nodes like this will be color-coded as black ("#000000").
// Assigning colors to type
function determinecolor(type){
if (type==="dog"){return "#42f48c";}
else if (type==="cat"){return "#417df4";}
else if (type==="horse"){return "#f141f4";}
else if (type==="cow"){return "#ce1818";}
else{return"#000000";}
};
edgecolor
This tool enables one to use the same color for all edges, or to use the color from the source-node as color for the edge.
// Set Edgecolor same as Nodecolor? (use integers.)
// use 0, 1 or 2 (everything else is seen as 2)
// you MUST configure options for option1 in function edgecolor_assigner!
var edgecol_is_nodecol = 1;
//0 = edgecolor is determined by edgecol; all edges are the Same
//1 = edgecolor is customizable in the function edgecolor_assigner
//2 = all edgecolors are determined by the source-ID
var edgecol = "rgba(30,78,87,0.2)"; // if you set edgecol_is_nodecol = 0; this will be the default color of edges.
If edgecol_is_nodecol
= 0
all edges will have one default color, this default color is determined by the variable edgecol
below. This variable accepts: HEX, RGB and RGBA values.
By setting edgecol_is_nodecol
to 2
all edges will have the same color as the originating node.
By setting edgecol_is_nodecol
to 1
all edges can be manipulated by modifying the code in the function 'edgecol_assigner'. As it is, this function takes 5 arguments.
- State: this is the integer used in the configuration part.
- alt: the color used by default (== edgecol in configuration part)
- source: the node where the edge originates.
- target: the node where the edge links to.
- me: the ID of the edge itself; this ID can be used to access properties of the edge, we recommend to access these properties via the data_input and not use the
g.edges
object!
Source and target are the ID's of the nodes and can be used to access properties of those nodes. If you wish to use the nationality of the source node to determine the color, you write:
base = g.nodes[source]["nationality"];
if (base === "persian"){return "rgba(255,0,0,0.2)";}
else if (base === "greek") {return "rgba(0,200,200,0.2)";}
else if (base === "helenistic"){return "rgba(200,200,0,0.2)";}
else if (base === "egyptian"){return "rgba(100,255,20,0.2)";}
else if (base === "roman"){return null;}// Null will make the edgecolor render as SOURCEnode color.
else {return alt;} // if case isn't set, make alt!
the code snippet above assigns to the variable base the nationality of the source node of the current edge. Then multiple if and else if cases determine the color for a specific type of 'base'. If the program encounters a case that's not covered by any of the other cases, it will use the value stored in edgecol
to colorize that edge. You can make the snippet return null
, this will use the color of the originating node (source) as the color for the edge.
ignorelist
This list is used by the filtering-segment of the code to prevent certain components from being used as filters. There's for instance no point in allowing users to filter on the x or y, position of a node.
The ignorelist
is a JavaScript array and looks like this:
// Filter ignorelist.
var ignorelist = ["id", "x", "y", "size", "color", "label"];
The items in this list are enclosed by quotes, meaning that they are strings. Each item is separated by a comma.
If your nodes for instance have an attribute called "rank", and you don't want to provide this as a filter-option, you'll need to append it to ignorelist
. This can easily be done like this:
var ignorelist = ["id", "x", "y", "size", "color", "label", "rank"];
link_board
The link_board variable is a boolean, meaning it takes true or false as accepted values.
The code relating to this functionality looks like this:
// link graphboard to left side information panel. (This will link clickevents between the two information panel and graph visualization.)
var link_board = true; // true or false
true when set to true
the information pane on the left-side of the screen can be used to control the appearance of the graph. Every time a node is clicked in the side panel, it will look for the corresponding node in the graph, and use that node to create an ego-network (i.e. displaying only the nodes that have a direct relation with the clicked node.
false when set to false
the information pane on the left-side can be navigated without altering the appearance of the graph.
node_ignore
node_ignore
uses the same principles as ignorelist
but affects another part of program-functionality.
This list is used by the information-displaying segment of the code to prevent certain node attributes from being shown to the user of the JavaScript application. There's for instance no point in showing users the rendered size of a node.
node_ignore
is a JavaScript array and looks like this:
// Hides these attributes from the nodes in the onclick event:
var node_ignore = ["x", "y", "size", "color", "id", "hidden", "read_cam0:size", "read_cam0:x", "read_cam0:y", "renderer1:x", "renderer1:y", "renderer1:size", "dn_x", "dn_y", "dn_size", "dn"];
The items in this list are enclosed by quotes, meaning that they are strings. Each item is separated by a comma.
If your nodes for instance have an attribute called "rank", and you don't want to display this information, you'll need to append it to node_ignore
. This can easily be done like this:
var node_ignore = ["x", "y", "size", "color", "id", "hidden", "read_cam0:size", "read_cam0:x", "read_cam0:y", "renderer1:x", "renderer1:y", "renderer1:size", "dn_x", "dn_y", "dn_size", "dn", "rank"];
edge_ignore
edge_ignore
uses the exact same principles as node_ignore
affecting the displayed information.
This list is used by the information-displaying segment of the code to prevent certain edge attributes from being shown to the user of the JavaScript application. There's for instance no point in showing users the id of an edge.
The script doesn't need to display the source and target of edges, in stead it looks up what node corresponds to that id; this is the //notice
comment.
// hides these attributes form the edges in the onclick event:
// NOTICE ==> source and target are not used directly; they are replaced by the correlating node-labels
var edge_ignore = ["color", "size", "id", "type", "hidden", "read_cam0:size", "renderer1:size", "source", "target"];
filename
This JavaScript application enables users to export the rendered graph in jpg, png and svg. This section of the code allows you to set a name used by the export-functions of the code.
// Filename Export Change this to alter the name of exported files.
var filename = "Trismegistos-Graph-Export";
var svg_size = 1920;
The variable filename
is a string and serves as the base for every exported graph. Users who download the jpg, png or svg to their computer will have a file that uses this string as a name. It is advised to choose something that allows users to recall where they got the image, making it easier to annotate or credit your site.
The variable svg_size
is an integer (a whole number) and is used by the SVG-export-function to determine how large an exported graph has to be.
max_interactive_density
Size matters.... and it's not different for graphs. Certain layout-optimizers make no sense to apply to large networks due to performance restrictions. To prevent users from clicking a button that would otherwise slow down their computer, leading to a bad user-experience of your site, a max_interactive_density
variable was introduced. This variable is an integer (a whole number).
//This value will disable certain elements if there are more than x-nodes in your graph. This is useful to prevent
//visitors from applying algorithms that are not suitable for large networks.
var max_interactive_density = 750; // Integer value
In this case, the maximum density is set to 750 nodes. If your graph exceeds this, then the code will alter it's execution by disabling:
- The Fruchterman-Reingold-layout-algorithm.
- The Noverlap-layout-algorithm.
In both cases the user will receive a tooltip when hovering the corresponding button saying that this functionality is "Disabled due to too large network."
You can always alter this value yourself by assigning a new integer value to it.
positioning
This JavaScript application supports data where the coordinates are unknown, by calculating a square layout on the fly. It will however allow you to work with data where the coordinates are known. For this it uses three variables.
//Positioning of nodes.
var positions_are_known = false; // use true or false
var use_as_x = "your_x_coordinate"; // in your data, what key is used to denote the X-position of a node? (string)
var use_as_y = "your_y_coordinate"; // in your data, what key is used to denote the Y-position of a node? (string)
The variable positions_are_known
is a boolean. It'll accept true or false.
false If set to false
the script will calculate the positions on the fly; resulting in a square layout.
true if set to true
the script will rely on the two other variables to extract the x and y coordinates from the data sent to the JavaScript application.
The variable use_as_x
is a string. You'll need to provide the name of the key that is used in your data to indicate the x-position for each node.
The variable use_as_y
is a string. You'll need to provide the name of the key that is used in your data to indicate the y-position for each node.
So in a situation where the coordinates are known, the x is indicated by a key called "here_is_x" and y is indicated by a key called "y_is_here". You'll need to update the code like this:
//Positioning of nodes.
var positions_are_known = true; // use true or false
var use_as_x = "here_is_x"; // in your data, what key is used to denote the X-position of a node? (string)
var use_as_y = "y_is_here"; // in your data, what key is used to denote the Y-position of a node? (string)
sizing
The JavaScript application supports cases where the size is unknown by using the built-in relativesize library from sigma.js. However, if the size is known and needs to be used, then you can override this behaviour.
//Do you have a fixed size in your argument for each node? If set to true, the program shall not overwrite this size.
var fixedsize = false; // use true or false.
var nameforsize = "your_size_key"; // In your data, what key is used to denote the size of a node? (string)
The variable fixedsize
is a boolean (takes true or false).
false: If set to false
, the program will auto-calculate the size of each node.
true: If set to true
, the program relies on a second variable to extract the correct value for each node from the data sent to the JavaScript application.
The variable nameforsize
is a string. You'll need to provide the name of the key that is used in your data to indication the size of each node.
So in a situation where the size is known and is indicated by a key called "diameter", you'll need to update the code like this:
//Do you have a fixed size in your argument for each node? If set to true, the program shall not overwrite this size.
var fixedsize = true; // use true or false.
var nameforsize = "diameter"; // In your data, what key is used to denote the size of a node? (string)
By doing so the s.relativesize method won't be called in a later stage of the script; however, the size remains relative to the amount of nodes on the screen. I.e. a node with size 50 will be bigger when there are only 30 nodes in your network than when there are 3000 nodes in the network. This 'scale' is equally applied to all nodes. So a node A with size 10 and a node B with size 50 will hold their 1-to-5-ratio independently from the amount of nodes in the network.
Undirected or directed network
Since march 2nd this tool will make a visual distinction in it's information representation if a network is undirected. For this we introduced a new configuration variable which controls multiple parts of the code called directed.
//Is the network directed or undirected? A network is undirected if a relation does not have an explicit direction. Note however that sigma still needs the explicit source/target in the JSON-data. So there's no difference in feeding data to the tool.
var directed = false; // use true or false
The variable directed
is a boolean (takes true or false).
false: If set to false
the network is considered as undirected. Meaning that the information pane will now show all connections grouped together and considers both nodes connected by the edge as peers rather than source / target.
true: If set to true
the network is considered as directed. Meaning that the information pane will now distinguish ingoing and outgoing relations. When clicking on edges, it will not consider both nodes as peers, but make explicit who the source is and who the target is of said edge.
Edgetype controller
You can control which type of edges to use. Sigma.js Supports the following edgetypes:
- arrow: straight line from target to source with an arrow (best used for directed graphs)
- curvedArrow: curve from target to source with an arrow (best used for directed graphs with overlapping edges.)
- line: straight line without arrow (best used for undirected graphs)
- curve: curve without arrow (best used for undirected graphs with overlapping edges)
by setting var choose_this_edgetype = x;
to an integer value between ranging from 1 to 4 you can determine the look of the interface.
- use 1 for arrow type edges
- use 2 for curvedArrow type edges
- use 3 for line type edges
- use 4 for curve type edges
NOTICE invalid values are defaulted to 4.
Questions?
Prof. Dr. M Depauw: Mark.Depauw@kuleuven.be