EzDevInfo.com

sigma.js

A JavaScript library dedicated to graph drawing Sigma js

show edge label in sigma.js

I am trying to load a gexf file with sigInst.parseGexf('data/test.gexf').

To create an edge with label I have this line in gexf file:

<edge label="test" id="7" source="14" target="18" type="directed"/>

but seems that sigma.js ignore this label field.

How can I show edge labels in graph.

Thanks in advance.


Source: (StackOverflow)

Is there a perticular format for sigma.js compatible json file ?

Im trying to generate a json file which should be compatible with sigma.js to plot the graph ? can i know in what format it should be ? in C++.


Source: (StackOverflow)

Advertisements

Filtering Sigma.Js graph from external events

I have an instance of Sigma.Js 1.0.0 rendering a graph in my Canvas element. (The code is below, but you can simply scroll to Step 2 of Tutorial on the main sigmajs.org page.

As you can see from that code, when the node is clicked, clickNode event occurs, which then applies filtering to the graph, showing only the clicked node and its neighborhood and dimming the others. That's quite clear.

However, how would I make exactly the same thing happen from the outside? Suppose I have the graph rendered already and I have a Tag Cloud next to it. And I want that when I click on a #hashtag, only that node is shown in the graph and the rest are dimmed. How would I do that?

Thanks!

<div id="sigma-container"></div>
<script src="path/to/sigma.js"></script>
<script src="path/to/sigma.parsers.min.gexf.js"></script>
<script>
  // Add a method to the graph model that returns an
  // object with every neighbors of a node inside:
  sigma.classes.graph.addMethod('neighbors', function(nodeId) {
    var k,
        neighbors = {},
        index = this.allNeighborsIndex[nodeId] || {};

    for (k in index)
      neighbors[k] = this.nodesIndex[k];

    return neighbors;
  });

  sigma.parsers.gexf(
    'path/to/les-miserables.gexf',
    {
      container: 'sigma-container'
    },
    function(s) {
      // We first need to save the original colors of our
      // nodes and edges, like this:
      s.graph.nodes().forEach(function(n) {
        n.originalColor = n.color;
      });
      s.graph.edges().forEach(function(e) {
        e.originalColor = e.color;
      });

      // When a node is clicked, we check for each node
      // if it is a neighbor of the clicked one. If not,
      // we set its color as grey, and else, it takes its
      // original color.
      // We do the same for the edges, and we only keep
      // edges that have both extremities colored.
      s.bind('clickNode', function(e) {
        var nodeId = e.data.node.id,
            toKeep = s.graph.neighbors(nodeId);
        toKeep[nodeId] = e.data.node;

        s.graph.nodes().forEach(function(n) {
          if (toKeep[n.id])
            n.color = n.originalColor;
          else
            n.color = '#eee';
        });

        s.graph.edges().forEach(function(e) {
          if (toKeep[e.source] && toKeep[e.target])
            e.color = e.originalColor;
          else
            e.color = '#eee';
        });

        // Since the data has been modified, we need to
        // call the refresh method to make the colors
        // update effective.
        s.refresh();
      });

      // When the stage is clicked, we just color each
      // node and edge with its original color.
      s.bind('clickStage', function(e) {
        s.graph.nodes().forEach(function(n) {
          n.color = n.originalColor;
        });

        s.graph.edges().forEach(function(e) {
          e.color = e.originalColor;
        });

        // Same as in the previous event:
        s.refresh();
      });
    }
  );
</script>
<!-- [...] --> 

Source: (StackOverflow)

Drawing edges while graph is being laid out in sigma.js

The default behaviour in sigma is that while the graph is being laid out (i.e. the generator runs), edges are not drawn. Only after the layout finishes the edges are added, see here for an example of what I mean.

Is there any way to draw the edges while the graph is laid out and not just at the end? I've seen suggestions that sigInst.draw(2,2,2); should force the edges to be drawn synchronously, but this code doesn't change anything regardless of where I put it.


Source: (StackOverflow)

Load sigmajs through requirejs

I am trying the RequireJS AMD,

And would like to load - among others (jquery, bootstrap, d3, moment...) - the graph library sigmajs, But when I load it in a module, It is undefined... However it exists in the window object...

Is it a bad practice to require it in a module ? Should it require it in the global requirejs bootstrapping and use it from the window ?

Here is my application bootstrapping :

// My application root folder
index.html
build.js
assets/
    package.json
    bower.json
    gulpfile.js
    js/
        app.js
        modules/
            graph.js
        vendor/
            require-2.1.14.js
            jquery-2.1.1.min.js
            underscore-1.6.0.min.js
            d3-3.4.11.min.js
            moment-2.7.0.min.js
            sigma-1.0.2.min.js
            my-own-npm-module-1.0.0.min.js
    css/

My app.js file : requirejs bootstrapping, seems to work well

// /assets/js/app.js
requirejs.config({
    baseUrl: 'assets/js/vendor',
    paths: {
        'jquery': 'jquery-2.1.1.min',
        'bootstrap': 'bootstrap-3.2.0.min',
        'moment': 'moment-2.7.0.min',
        '_': 'underscore-1.6.0.min',
        'd3': 'd3-3.4.11.min',
        'sigma': 'sigma-1.0.2.min',
        'my-own-npm-module': 'my-own-npm-module-1.0.0.min',
        'app': '../modules'
    },
    shim: {
        'bootstrap': {
            deps: ['jquery'],
            exports: '$'
        }
    }
});

// App loading
requirejs([
    'jquery',
    'bootstrap',
    'app/graph'
], function ($, bootstrap, graph) {
    graph.initialize();
});

My graph.js file, requiring the unfortunately undefined sigmaJs

define(['sigma', 'd3', 'my-own-npm-module'], function (sigma, d3, MyOwnModule) {
    var initialize,
        graph;

    initialize = function () {
        console.log('init', d3, sigma, sigma === window.sigma, MyOwnModule);
        // Here, d3 is well loaded and even MyOwnModule.
        // But unfortunately, sigma is undefined even if window.sigma is loaded
        // And of course, sigma === window.sigma returns false.
        graph = new sigma('graph-container');
    }

    return {
        'initialize': initialize
    }
});

Source: (StackOverflow)

Layouts using neo4j and sigma.js

I am trying to learn how to use sigma.js with neo4j and would appreciate some help in getting the layout algorithms to work with sigma.neo4j.cypher. The sigma.layout.fruchtermanReingold.js layout does not work in the code below when used with sigma.neo4j.cypher. I am pretty confident that I have all sigma imports but can add those to the question if you feel the issue might be there.

Many thanks.

<div id="container">
    <style>
        #graph-container {
            top: 0;
            bottom: 0;
            left: 0;
            right: 0;
            position: absolute;
        }
    </style>
    <div id="graph-container"></div>
</div>
<script src="../plugins/sigma.layout.forceAtlas2/worker.js"></script>
<script src="../plugins/sigma.layout.forceAtlas2/supervisor.js"></script>
<script src="../plugins/sigma.plugins.animate/sigma.plugins.animate.js"></script>
<script src="../plugins/sigma.layout.fruchtermanReingold/sigma.layout.fruchtermanReingold.js"></script>
<script type="application/javascript">

    sigma.neo4j.cypher(
            { url: 'http://localhost:7474', user: 'neo4j', password: 'admin' },
            'MATCH (n) OPTIONAL MATCH (n)-[r]->(m) RETURN n,r,m LIMIT 100',
            { container: 'graph-container' } ,
            function(s) {
                console.log('Number of nodes :'+ s.graph.nodes().length);
                console.log('Number of edges :'+ s.graph.edges().length);
            }
    );

    // Configure the Fruchterman-Reingold algorithm:
    var frListener = sigma.layouts.fruchtermanReingold.configure(s, {
      maxIterations: 500,
      easing: 'quadraticInOut',
      duration: 800
    });

    // Bind the events:
    frListener.bind('start stop interpolate', function(e) {
      console.log(e.type);
    });

    // Start the Fruchterman-Reingold algorithm:
    sigma.layouts.fruchtermanReingold.start(s);


</script>

Source: (StackOverflow)

Graph visualization with Sigma.js: way over my head

I'm trying to visualize a big network and found sigma.js which looks fantastic. The problem is, my programming experience is poor, and is only with statistical programming languages.

I've tried to follow along with some examples, but can't get my network to display. I've lifted the code from the websites, trying to plug in my .gexf file, but nothing displays.

This is what I took from the sigma.js example

function init() {
  // Instanciate sigma.js and customize rendering :
  var sigInst = sigma.init(document.getElementById('sigma-example')).drawingProperties({
    defaultLabelColor: '#fff',
    defaultLabelSize: 14,
    defaultLabelBGColor: '#fff',
    defaultLabelHoverColor: '#000',
    labelThreshold: 6,
    defaultEdgeType: 'curve'
  }).graphProperties({
    minNodeSize: 0.5,
    maxNodeSize: 5,
    minEdgeSize: 1,
    maxEdgeSize: 1
  }).mouseProperties({
    maxRatio: 32
  });

  // Parse a GEXF encoded file to fill the graph
  // (requires "sigma.parseGexf.js" to be included)
  sigInst.parseGexf('donornet.gexf');

  // Draw the graph :
  sigInst.draw();
}

if (document.addEventListener) {
  document.addEventListener("DOMContentLoaded", init, false);
} else {
  window.onload = init;
}

I replaced the .gexf file with my own "donornet.gexf" and saved it as donornet.js

I then tried to display the webpage following this example from Max De Marzi where I right-clicked and hit "view page source" to get the following code, which I replaced with my donornet.js file:

<!DOCTYPE html>
<html>
  <head>
    <meta http-equiv="Content-type" content="text/html; charset=utf-8">
    <title>Donornet and Sigma.js Example</title>
    <script type="text/javascript" src="sigma.min.js"></script>
    <script type="text/javascript" src="sigma.parseGexf.js"></script>
    <script type="text/javascript" src="sigma.forceatlas2.js"></script>
    <link type="text/css" rel="stylesheet" rel='nofollow' href="neo_sigma.css"/>
  </head>
  <body>
    <h1>Donornet and Sigma.js Example</h1>
        <div class="buttons-container">
        <button class="btn" id="stop-layout">Stop Layout</button>
        <button class="btn" id="rescale-graph">Rescale Graph</button>
    </div>
        <div class="span12 sigma-parent" id="sigma-example-parent">
    <div class="sigma-expand" id="sigma-example"></div>
    </div>
    <script type="text/javascript" src="donornet.js"></script>
  </body>
</html>

All the files are in the same folder, and I have the parseGexf.js downloaded in the same file as donornet.js and donornet.gexf.

Any help would be greatly, greatly appreciated.

Thanks!


Source: (StackOverflow)

Adding sigma.js navigation buttons

I'm new to javascript and sigma.js, and I'm trying to get navigation buttons to scroll up/down/left/right in the canvas, much like what is found here

So far, I have a simple example that I'm trying to get working on jsfiddle: http://jsfiddle.net/dpmartin42/kSkkG/16/

I'm using the following line of code I found on GitHub and am trying to build off of it:

$('[data-action="up"]').bind('click', function(e) {

    // With "inst" our sigma instance:
    var newPos = inst.position();

    newPos.stageY += 80;
    inst.goTo(newPos.stageX, newPos.stageY);

    e.stopPropagation();
    return false;
});

I have been messing with it for awhile and I can't seem to get it to work. Problem is, I don't really know what is going wrong. Any help is appreciated!


Source: (StackOverflow)

Inserting elements to a div means Java Script sigma.js library

I'm testing a Java Script library for graphs visualization. Based on the introductory docs I tried to make a simple graph display on web page.

This is what docs say:

Easy to use
Here is the minimal code to create an instance:

var sigRoot = document.getElementById('sig');
var sigInst = sigma.init(sigRoot);
sigInst.addNode('hello',{
  label: 'Hello',
  color: '#ff0000'
}).addNode('world',{
  label: 'World !',
  color: '#00ff00'
}).addEdge('hello_world','hello','world').draw();

This is my HTML webpage:

<!DOCTYPE html>

<html>

<head>
    <title>Testing graphs</title>
    <script src="sigma.min.js"></script>
    <script src="jquery1102.js"></script>
</head>

<body>

    <div id="sig"></div>

    <script type="text/javascript">

    window.onload = loadGraph();

    function loadGraph () {

        var sigRoot = document.getElementById('sig');
        var sigInst = sigma.init(sigRoot);
        sigInst.addNode('hello',{
          label: 'Hello',
          color: '#ff0000'
        }).addNode('world',{
          label: 'World !',
          color: '#00ff00'
        }).addEdge('hello_world','hello','world').draw();
    }
    </script>

</body>
</html>

So, I'm assuming graph would display in some div area and executed once page has loaded. However nothing gets displayed on and console isn't claiming for any bug. Do I even need to use the HTML5 canvas?


Source: (StackOverflow)

Linkurious attributes don't work

I'm attempting to set "visual variables" but failing at it. the complete code is here: http://pastebin.com/j6i1B8ie

<script type="application/javascript">
    var neo = { 
        url: 'http://localhost:7474',
        user: 'neo4j',
        password: '***'
    };  
    function customiseGraph(s) {
        s.graph.nodes().forEach(function(n) {
            n.type = 'square';
            n.color = '#4444BB';
            n.labelAlignment = 'left';
            if (n.neo4j_labels[0] == 'DMSys') {
                n.label = n.neo4j_data.System;
            }   
            if (n.neo4j_labels[0] == 'DMFile') {
                n.label = n.neo4j_data.Name;
                n.color = '#BB4444';
            }   
        }); 
        s.refresh();
    }   

    sigma.neo4j.cypher(neo,
        'MATCH (n) OPTIONAL MATCH (n)-[r]->(m) RETURN n,r,m LIMIT 100',
        { container: 'graph', type: 'canvas' },
        customiseGraph
    );  
</script>

in the above, I'd expect that every node displayed gets rendered as a square, but it doesn't. mind you, the colours get set correctly but neither labelAlignment or type are respected.

can I not do it this way? or what am I missing?

* Update I *

function customiseGraph(s) {
    s.settings({
        labelAlignment: 'inside',
        edgeColor: 'default',
        defaultEdgeColor: '#ff0000'
    }); 
    s.graph.nodes().forEach(function(n) {
        n.color = '#4444BB';
        if (n.neo4j_labels[0] == 'DMSys') {
            n.label = n.neo4j_data.System;
        }   
        if (n.neo4j_labels[0] == 'DMFile') {
            n.label = n.neo4j_data.Name;
            n.color = '#BB4444';
        }   
    }); 
    s.refresh();
}

which I would expect to produce red edges and the labels inside the nodes but does neither. what else do I need?


Source: (StackOverflow)

Sigma JS - show edge labels

How can we show edge labels on Sigma.js? I am aware of show edge label in sigma.js. But the code isn't merged yet with the trunk version.


Source: (StackOverflow)

Looking for a layout algorithm

I'm working with the sigma.parsers.cypher.js plugin for Linkurious, which seems to lay nodes out on the viewport by rather unimaginatively assigning the x and y coordinates random values which, with enough nodes basically creates an unreadable mess - the graph generation built into the Neo server does a much better job.

in thinking about it, an algorithm to lay stuff out better could work like this:

  1. select the first node in the graph and position it at (0,0)
  2. select all directly related nodes and position them a {minimum distance} away from the parent node
  3. if any two siblings are closer than {minimum distance}, increase the distance from the parent until the siblings can be sufficiently separated
  4. for each sibling perform steps 2 & 3 above

but I'm wondering is there anything out there I could leverage so I don't have to write the functionality from scratch?

* Update I *

maybe 2) select all (childless) directly related nodes ... and then 2a) child nodes with children should be positioned at twice the distance + the diameter of the node of siblings (this gives room for its children)

* Update II *

if the radius of the circle is {minimum distance} and there are more childless nodes than will fit, we can either: 1) increase the radius until all the nodes fit, or 2) create a second layer


Source: (StackOverflow)

Delayed execution of a function in Javascript

I'm using Sigma.Js library and want to make the graph rotate around its axis for the first 10 seconds after the page loads. I wrote the following code for it, but it doesn't work. Any idea why?

 for (i = 0; i < 101; i++) {

    var angle = i / 100;
    s.cameras[0].angle = angle;

    setTimeout(function() {
       s.refresh();
    },100);

 }

FYI s refers to the graph initialized, s.cameras[0].angle sets the angle of the view (referring to it through console works, so that's correct), s.refresh reloads the graph.

I guess it has something to do with async (the cycle gets executed bypassing timeout?), but can't figure it out myself...

Thank you for your help!


Source: (StackOverflow)

Load Entire Neo4j Database into Linkurious's SigmaJS

How can I load an entire Neo4j database into Linkurious's SigmaJS Graph API? On that page, I don't see any methods that describe how to import a database in its entirety -- only how to build out a graph manually by adding nodes and edges. I suspect that the read() function almost does what I want (reading in an object), but it is unclear in what format I must supply this object in.

It would be great to be able to simply pass in the graph.db folder within my Neo4j folder.


Source: (StackOverflow)

Chrome freeze when refreshing graph with sigma.js

I can't understand what is going wrong, sometimes, when i try to render the graph by clicking the "Generate Random Graph" button, my browser CPU jumps to 17% and the browser freezes.

This is the webpage: http://summarify.com/randomideagenerator/ You can find all the source here: https://github.com/alessiop86/display-random-concepts

This is the javascript:

      // Self-executing wrapper
(function ($) {

    Backbone.sync = function (method, model, success, error) {
        success();
    }

    /* Model */
    var Item = Backbone.Model.extend({
        defaults: {
            concept: 'description',
            displayChoice: 'random'
        }
    });

    var List = Backbone.Collection.extend({
        model: Item
    });

    /* End of model */

    /* Views */

    var ItemView = Backbone.View.extend({

        tagName: 'tr',

        events: {
            'click button.delete': 'remove',
            'change input[type=text]': 'conceptChanged',
            'click input[type=radio]': 'displayChoiceChanged'
        },

        initialize: function () {
            _.bindAll(this, 'render', 'unrender', 'remove','conceptChanged','displayChoiceChanged'); 
            this.model.bind('remove', this.unrender);            
        },
        conceptChanged:function(evt) {

           var value = $(evt.currentTarget).val();
            this.model.set('concept',value)

        },

        displayChoiceChanged:function(evt) {
            var value = $(evt.currentTarget).val();
            this.model.set('displayChoice',value)
        },

        render: function () {

            //workaround to access @ this.model from the anonymous inner function
            //making it a closure for the free variable model
            var model = this.model

            //workaround because .html() is not working with <tr>
            $(this.el).each(function(){                    

              jQuery(this)[0].innerHTML = '<tr><td>' + '<div class="form-group">' + '<div class="form-control-wrapper"><input value="' + model.get('concept') + '" class="form-control concept"  type="text"><span class="material-input"></span></div>' + '</div>' + '</td>' + '<td>' + '<div class="radio radio-primary">' + '<label>' + '<input type="radio" value="mandatory">' + '<span class="circle"></span><span class="check"></span>' + '</label>' + '</div>' + '</td>' + '<td>' + '<div class="radio radio-primary">' + '<label>' + '<input type="radio" value="random" checked="checked">' + '<span class="circle"></span><span class="check"></span>' + '</label>' + '</div>' + '</td>' + '<td>' + '<div class="radio radio-primary">' + '<label>' + '<input type="radio" value="disabled" >' + '<span class="circle"></span><span class="check"></span>' + '</label>' + '</div>' + '</td>' + '<td>' + '<button class="btn btn-primary delete" type="button">Remove</button>' + '</td></tr>';
    });
            return this; 
        },

        unrender: function () {
            $(this.el).remove();
        },

        remove: function () {
            this.model.destroy();
        }
    });

    /*Main view (List) */
    var ListView = Backbone.View.extend({

        el: $('div#left'), 

        initialize: function () {
            _.bindAll(this, 'render', 'addItem', 'appendItem'); 

            this.collection = new List();
            this.collection.bind('add', this.appendItem);


            /* Remove this block below, just for showcase purpose */
            var testModel = getTestModel();
            for (var i=0;i<testModel.length;i++) {                
                var item = new Item();
                item.set(testModel[i]);
                this.collection.add(item);
            }
            /* End of test showcase block */


            this.render(); //self-rendering view
        },

        events: {
            'click button#add': 'addItem',
            'click button#random': 'displayRandom'
        },

        appendItem: function (item) {
            var itemView = new ItemView({
                model: item
            });
            $('tbody', this.el).append(itemView.render().el);
        },

        render: function () {

            var self = this;

            $(this.el).append("<button id='add'>Add item</button>");

            $(this.el).append("&nbsp;<button id='random'>Generate random graph</button>");

            $(this.el).append("<table class=\"table table-striped table-hover \">" 
                                + "<thead>"
                                + "<tr>" 
                                + "<th>Concept</th>" 
                                + "<th>Mandatory</th>" 
                                + "<th>Random</th>"
                                + "<th>Disabled</th>" 
                                + "<th>Remove</th>"
                                + "</tr>"
                                + "</thead>"
                                +"<tbody></tbody>"
                                +"</table>");

            this.collection.each(function (item) { 
                self.appendItem(item);
            }, this);
        }


        ,
        addItem: function () {

            var item = new Item();
            item.set({
                concept: prompt("Write concept:"),
                displayChoice : "random",
            });
            this.collection.add(item);
        },




        displayRandom: function() {

            displayRandomGraph(this.collection.models);
        }


    });

    /* end of Views */

    //Instantiate main app view.
    var listView = new ListView();
})(jQuery);

/* End of Backbone.js app */

/* Start of Graph generation code */

var  g2 = {
  "nodes": [],
  "edges": []
};

var s2 =  new sigma(  {
      renderers: [ {
            container: document.getElementById('innerRightCanvas'),
            type:'canvas'   
        } ],
        settings: {
            sideMargin:80,
            labelThreshold:1,
            mouseEnabled:false,
            enableHovering: false,
            autoRescale: false,
            autoResize:false,
            rescaleIgnoreSize: false

        }, graph: g2

    });
//console.log(s2);

/**
Grap
*/
function displayRandomGraph(concepts) {

    //disable multiple clicks
    //$("#random").prop('disabled', true);
    //setTimeout(function() {  $("#random").prop('disabled', false); }, 500);

    s2.graph.clear();

    //nodes
    for (var i=0; i < concepts.length; i++) {                

        //Compute display choice
        if (concepts[i].get("displayChoice") == "disabled" || ( concepts[i].get("displayChoice") == "random" && Math.random() < 0.5) )
            continue;


        var id = "n" + s2.graph.nodes().length;
        var concept = { 
            "id" : id,
            "label" : concepts[i].get('concept'),
            "x" : Math.round(200 * (0.5 - Math.random())), 
            "y" : Math.round(200 * (0.5 - Math.random())), 
            'size': Math.round(Math.random() * 6) + 2,
            'color': 'rgb('+Math.round(Math.random()*256)+','+  Math.round(Math.random()*256)+','+ Math.round(Math.random()*256)+')'
            }

            s2.graph.addNode(concept)
    }

    //edges    
    for (var i=0; i < s2.graph.nodes().length; i++) {

        var edgesForCurrentNode = Math.round(Math.pow(Math.random(),2) * 3);

        for (var j=0; j<edgesForCurrentNode;j++) {

            var start = s2.graph.nodes()[i].id
            var end = start;

            //edges allowed only between different nodes
            while (end == start) {            
                end = "n" + Math.round(Math.random()*(s2.graph.nodes().length -1));
            }

            var edge = {
              "id": "e" + s2.graph.edges().length,
              "source": start,
              "target": end
            };


            s2.graph.addEdge(edge)
        }

    }

    //console.log("NODES");console.log(s2.graph.nodes());
    //console.log("EDGES");console.log(s2.graph.edges());
    s2.refresh()

}

/* End of Graph generation code */


/**
test showcase
*/
function getTestModel() {

   var testCollection = [];
   for (var i=0;i<5;i++) {
        var item = {
            concept: "Concept " + i,
            displayChoice: "random",
        };
        testCollection.push(item);
    }
    return testCollection;
}

Source: (StackOverflow)