Article
1 comment

Graph libraries – Cytoscape.js with Cola.js

Now it’s time for my favourite graph visualization framework. As an introduction I cite from the Cytoscape website:

Cytoscape is an open source software platform for visualizing molecular interaction networks and biological pathways and integrating these networks with annotations, gene expression profiles and other state data.

Cytoscape.js as a side project is a JavaScript library designed to build graph theory related data evaluation and visualization applications on the web. It comes with some layout renderers but is open to other visualization libraries such as Cola.js. Cola is a constraint based layout library with some very interesting features. In this context, we will use it only as a layout engine for the graph.

How does it look?

When playing around with this graph you will probably notice two things:

  1. When dragging around a single node all the other nodes of the graph remain calm and don’t wiggle around like in most physical based layouts.
  2. When reloading this page you will always see the same arrangement of nodes. The graph is stable to reloads.

These two feature result from the way Cola.js renders the graph and are very useful for real world applications. While it’s big fun wobbling and dragging around nodes in a real application you would always like to see the same graph when reloading the same data. And manipulating the arrangement should not affect nodes not touched. The complete source code can be found in the GitHub-Mark-32px GitHub repository.

How does it work?

Once again we start by including the stuff needed. And this are the two libraries and an adaptor to use Cola.js from within Cytoscape.js:

<script src="/graphs/common/cola.js"></script>
<script src="/graphs/common/cytoscape.js"></script>
<script src="/graphs/common/cytoscape-cola.js"></script>

The adaptor can also be found on GitHub.

The HTML body contains a div to render the graph into:

<div id="cy"></div>

The remainder of the index.html file consists of a script:

var elems = [
    {data: {id: '1', name: 'Node 1', nodecolor: '#88cc88'}},
    {data: {id: '2', name: 'Node 2', nodecolor: '#888888'}},
    {data: {id: '3', name: 'Node 3', nodecolor: '#888888'}},
    {data: {id: '4', name: 'Node 4', nodecolor: '#888888'}},
    {data: {id: '5', name: 'Node 5', nodecolor: '#888888'}},
    {data: {id: '6', name: 'Node 6', nodecolor: '#888888'}},
    {
        data: {
            id: '12',
            source: '1',
            target: '2',
            linkcolor: '#888888'
        },
    },
    {
        data: {
            id: '13',
            source: '1',
            target: '3',
            linkcolor: '#888888'
        },
    },
    {
        data: {
            id: '24',
            source: '2',
            target: '4',
            linkcolor: '#ff8888'
        },
    },
    {
        data: {
            id: '25',
            source: '2',
            target: '5',
            linkcolor: '#ff8888'
        },
    },
    {
        data: {
            id: '45',
            source: '4',
            target: '5',
            linkcolor: '#ff8888'
        }
    },
    {
        data: {
            id: '46',
            source: '4',
            target: '6',
            linkcolor: '#888888'
        }
    }];
var cy = cytoscape({
    container: document.getElementById('cy'),
    elements: elems,
    style: cytoscape.stylesheet()
            .selector('node').style({
                'background-color': 'data(nodecolor)',
                label: 'data(name)',
                width: 25,
                height: 25
            })
            .selector('edge').style({
                'line-color': 'data(linkcolor)',
                width: 3
            })
});
cy.layout({name: 'cola', padding: 10});

Lines 2 to 7 define the nodes with their name/caption and colour. Lines 8 to 54 define the edges in a similar way. Lines 56 to 70 define the Cytoscape container and attach dynamic properties to the nodes and edges. Line 71 finally kicks off the layout rendering. Note: up to that last line we specified exactly no rendering or geometry information! By changing the name of the renderer from cola  to one of the built-ins (circle  or cose  are fun to play with!) you can get a completely different outout.

As a last remark I strongly recommend to have a look at the graph theoretical and practical routines and algorithms the Cytoscape.js library has to offer.

Article
0 comment

Graph libraries – Arbor.js

Arbor.js is written by Christian Swineheart from Samizdat Drafting Co. The documentation is concise even though the main page navigation as animated tree layout always drives me crazy :) The example I present here only depends on arbor.js and jQuery. Graph definition is for shortness and clarity done by calls to addNode  and addEdge  methods of the ParticleSystem renderer.

How does it look?

As you can see, the physical simulation is much more fluid and undamped than with Alchemy.js. I’m pretty much shure this can be changed to some degree with a different initialization of the particle system as described in the reference documentation. Once again, the complete source code, in this case consisting only of an index.html file, can be found in the GitHub-Mark-32px GitHub repository.

How does it work?

Once again in the header we start by loading the stuff needed:

<script src="/graphs/common/jquery-2.1.3.js"></script>
<script src="/graphs/common/arbor.js"></script>
<script src="/graphs/common/arbor-tween.js"></script>

arbor-tween.js is not really needed for this example as it allows gradual transitions in the data object of nodes and edges. Arbor.js by default renders its graph in a HTML5 canvas, in the body we need to define this:

<canvas id="viewport" width="800" height="500"></canvas>

The remainder of the file consists of a function defining and binding the renderer object to the canvas and constructing the graph:

(function ($) {
        var Renderer = function (canvas) {
                var canvas = $(canvas).get(0);
                var ctx = canvas.getContext("2d");
                var particleSystem;
                var that = {
                        init: function (system) {
                                particleSystem = system;
                                particleSystem.screenSize(canvas.width, canvas.height);
                                particleSystem.screenPadding(100);
                                that.initMouseHandling()
                        },
                        redraw: function () {
                                ctx.fillStyle = "white";
                                ctx.fillRect(0, 0, canvas.width, canvas.height);
                                particleSystem.eachEdge(function (edge, pt1, pt2) {
                                        ctx.strokeStyle = edge.data.linkcolor;
                                        ctx.lineWidth = 3;
                                        ctx.beginPath();
                                        ctx.moveTo(pt1.x, pt1.y);
                                        ctx.lineTo(pt2.x, pt2.y);
                                        ctx.stroke();
                                });
                                particleSystem.eachNode(function (node, pt) {
                                        ctx.beginPath();
                                        ctx.arc(pt.x, pt.y, 15, 0, 2 * Math.PI);
                                        ctx.fillStyle = node.data.nodecolor;
                                        ctx.fill();
                                        ctx.font = "18px Arial";
                                        ctx.fillStyle = "#000000";
                                        ctx.fillText(node.data.name, pt.x + 20, pt.y + 5);
                                });
                        },
                        initMouseHandling: function () {
                                var dragged = null;
                                var handler = {
                                        clicked: function (e) {
                                                var pos = $(canvas).offset();
                                                _mouseP = arbor.Point(e.pageX - pos.left, e.pageY - pos.top);
                                                dragged = particleSystem.nearest(_mouseP);
                                                if (dragged && dragged.node !== null) {
                                                        dragged.node.fixed = true;
                                                }
                                                $(canvas).bind('mousemove', handler.dragged);
                                                $(window).bind('mouseup', handler.dropped);
                                                return false;
                                        },
                                        dragged: function (e) {
                                                var pos = $(canvas).offset();
                                                var s = arbor.Point(e.pageX - pos.left, e.pageY - pos.top);
                                                if (dragged && dragged.node !== null) {
                                                        var p = particleSystem.fromScreen(s);
                                                        dragged.node.p = p
                                                }
                                                return false;
                                        },
                                        dropped: function (e) {
                                                if (dragged === null || dragged.node === undefined) return;
                                                if (dragged.node !== null) dragged.node.fixed = false;
                                                dragged.node.tempMass = 1000;
                                                dragged = null;
                                                $(canvas).unbind('mousemove', handler.dragged);
                                                $(window).unbind('mouseup', handler.dropped);
                                                _mouseP = null;
                                                return false;
                                        }
                                };
                                $(canvas).mousedown(handler.clicked);
                        }
                }
                return that;
        }
        $(document).ready(function () {
                var sys = arbor.ParticleSystem(700, 700, 0.5);
                sys.renderer = Renderer("#viewport");
                sys.addNode('Node 1', {name: "Node 1", nodecolor: "#88cc88"});
                sys.addNode('Node 2', {name: "Node 2", nodecolor: "#888888"});
                sys.addNode('Node 3', {name: "Node 3", nodecolor: "#888888"});
                sys.addNode('Node 4', {name: "Node 4", nodecolor: "#888888"});
                sys.addNode('Node 5', {name: "Node 5", nodecolor: "#888888"});
                sys.addNode('Node 6', {name: "Node 6", nodecolor: "#888888"});
                sys.addEdge('Node 1', 'Node 3', {linkcolor: "#888888"});
                sys.addEdge('Node 1', 'Node 2', {linkcolor: "#888888"});
                sys.addEdge('Node 2', 'Node 5', {linkcolor: "#ff8888"});
                sys.addEdge('Node 2', 'Node 4', {linkcolor: "#ff8888"});
                sys.addEdge('Node 4', 'Node 5', {linkcolor: "#ff8888"});
                sys.addEdge('Node 5', 'Node 6', {linkcolor: "#888888"});
        })
})(this.jQuery);

Lines 2 to 73 define the Renderer, in detail:

  • get the HTML5 canvas (line 3)
  • grab its 2D context (line 4)
  • an init function for the particle system (lines 7 to 12)
  • a redraw function actually drawing the graph (lines 13 to 33) by iterating over all nodes and edges
  • defining a pretty basic mouse handling (lines 34 to 69)

In line 75 we get a particle system, set the rendering to the canvas in line 76 and define nodes (lines 76 to 81) and edges (lines 82 to 87). That’s pretty much all.

Article
3 comments

Graph libraries – Alchemy.js

Alchemy.js is a library developed by graphAlchemist (site defunct). The documentation could be better and more detailed but it works. Like many other libraries it leverages other libraries to do “the basic stuff”. In this case it is it depends on:

Alchemy uses GraphJSON (similar to GeoJSON) as input format, which is quite nice but undocumented since the website graphjson.io doesn’t exist any more. Looks as if support for it ceded with the graphAlchemist web site …

How does it look?

Like all demos I’ll show it’s a fully functional mini demo, so you can drag the nodes around. I’ll present excerpts of the code to explain. The complete code can be found in a GitHub-Mark-32px GitHub repository.

How does it work?

Our example consists of an index.html file, a GraphJSON data file and the library stuff. In the index.html we first load the stuff needed:

<link rel="stylesheet" href="/graphs/common/alchemy/alchemy.css"/>
<script src="/graphs/common/jquery-2.1.3.js"></script>
<script src="/graphs/common/d3.js"></script>
<script src="/graphs/common/lodash.js"></script>

The body contains a div to put the graph in and the include for the base library itself:

<div class="alchemy" id="alchemy"></div>
<script src="/graphs/common/alchemy/alchemy.js"></script>

Finally there’s the code producing the graph:

var config = {
    dataSource: '/graphs/alchemy/data/network.json',
    graphWidth: function() {return 800},
    graphHeight: function() {return 500},
    backgroundColor: "#ffffff",
    nodeCaptionsOnByDefault: true,
    caption: function(node){
        return node.caption;
    },
    nodeTypes: {
        "role": ["greyone", "greenone"]
    },
    edgeTypes: {
        "caption": ["greyone", "redone"]
    },
    nodeStyle: {
        "greyone": {
            color: "#888888",
            borderWidth: 0,
            radius: 15
        },
        "greenone": {
            color: "#88cc88",
            borderWidth: 0,
            radius: 15
        }
    },
    edgeStyle: {
        "greyone": {
            color: "#888888",
            width: 3
        },
        "redone": {
            color: "#ff8888",
            width: 3
        }
    }
};
alchemy = new Alchemy(config)

As you can see, nearly everything is done in a configuration object. Line 2 defines the source of the GraphJSON file, lines 3 & 4 set the dimensions of the SVG element. The setting of nodeCaptionsOnByDefault  in line 6 switches on the display of the node titles. Otherwise they would only show up when hovering with the mouse. Lines 7 to 9 define a callback function defining what to display as a caption / title. Lines 10 to 15 define valid values for grouping edges and nodes. Nodes are grouped by the role attribute, edges by caption. Lines 16 to 37 define how these groups of edges and nodes should be formatted. There are other, more direct ways to style a graph in Alchemy.js but I wanted to show the (for me) most elegant way. Finally line 39 kicks off the rendering of the graph with the given configuration.

Article
0 comment

Graph libraries – Introduction

This post starts a small series of articles, that will present some JavaScript graph plotting libraries and show how to draw more or less the same simple demo graph with these different libs.

What is a graph?

Graph theory is a mathematical discipline that studies networks of nodes and links or edges connecting them. Graphs are useful for many applications: social media networks, streets connecting cities, transfers connecting bank accounts or networks of people, addresses, bank accounts and cars connected via insurance claims and events. We’ll deal with some of those applications later on when discussing the application of network and graph paradigms to visualizing fraudulent actions.

Which libraries have I examined?

The internet is full, I mean literally FULL of libraries to display networked graphs. I had to choose some and discard others. First I decided to neglect commercial libraries that don’t have an open source edition. Then I stopped evaluating libs when I recognized that the documentation is too poor or functionality too limited to further investigate. So here is the list in alphabetical order:

Libraries I didn’t evaluate due to licensing constraints:

Libraries I gave up on:

  • Dracula Graph Library (Graph Dracula … you understand … haha)
    Needs a raphael.js renderer to display custom node shapes. Too much fuzz for a very short test.
  • sigma.js
    Poorly documented. Didn’t succeed to build a test candidate in short (!) time.

How did I test?

networkI always used the same test network. It consists of 6 nodes and 6 edges. Some edges are red and one node is green. The nodes are labelled “Node 1” to “Node 6”. Colouring and labelling is used to test how easy it is to insert some basic customization into the layout.

On the right side you can see a hand drawn (well not really handdrawn) picture of the demo network. The examples I present are fully functional, not screen shots and I will briefly go through the source code.

Update

The first part for Alchemy.js can be found here.

The second post on Arbor.js is here.

The third part with Cytoscape.js and Cola.js is here.

The fourth part with D3 is here.

Article
1 comment

Lean systems as reincarnation of large ones

Introduction

Washington SunglassesSome software systems are designed for massive amounts of data to be processed in a very short time. Banking systems, fraud detection, billing systems. Lets pick one, I worked on for a long time: billing systems (for telecom or internet providers for example).

Most of those systems are very large, mostly complex systems, designed to bill millions of customers per month. Some examples are Kenan Arbor (bought by Lucent) or Amdocs. Since these systems need to process vast amounts of data very fast, they are built using compiled sources / binaries. Binary software is not easily customizable. So most of these systems are widely customizable via configuration files. Taking in account all options possible in dynamic configurations results in even more compiled code. I think you got it.

What actually is a billing system?

To give an impression which steps are required in a typical billing scenario, here is a short non-exhaustive list:

  1. Preprocessing
    Collect billable items from external systems, translate or reformat the data and put it in a database.
    Additional for mobile telecom billing: import GSM TAP3 (Transferred Account Procedure version 3) roaming data.
  2. First step: Rating
    Put a “price tag” on every billable item for the billing period in question
  3. Second step: Billing
    Collect rated items as invoice items per customer.
  4. Third step: Invoicing
    Create invoices, on paper or digitally.
  5. Fourth step: Payment
    Withdraw money via saved payment option per customer.
    Alternatively: substract invoice total from prepaid deposit.

The problem

All of these steps could be “special” for any customers. Think of a subscribed service. Every customer pays $5 per month. But once the company had an introductory offer of 20% off for the first year. So not only are some customers paying only $4 but they are paying $5 after 12 months. Now take into account, that a typical mobile telecom company has something like 20-30 different contract types or rates. Wow, lots of options. Not a problem for a multi-million dollar company but for smaller companies with, let’s say, 100 to 100.000 customers.

A solution?

Now what if a billing system would be implemented in a scripting language? Admittedly it would be a bit slower (would it? I don’t really know) that a solution in C or C++. But it would be very fast and flexible customizable, if well documented (we developers love to write documentation, don’t we?). Also management summary dashboards would be much more flexible as prebuilt solutions like QlikView (which also would cost additional license fees).

I could visualize for example a solution in Python. This way it would be fast compared to some other scripting languages and could leverage the massive amount of financial and mathematical software components. Build an administration and dashboard component with Flask or Django and run Python scripts on a PostgreSQL database. If more speed is needed you could switch to an Apache Spark architecture, which would also be scriptable in Python via PySpark.

Start on a small budget but don’t let decisions limit your options!

Article
0 comment

Assholes and code of conduct manifests

Recently someone pointed out, that the perceived number of assholes is rising. This means, that anti-social behavior can be encountered more often. I responded that there seems to be some sort of sociological mechanism leading to anti-social behavior being more accepted than before.
Someone else asked what that mechanism might be, so here is my amateurish point of view.
Social interaction often is accomplished by communication. So examining forms of anti-social or disruptive communicational behavior might help to clarify some points. One form of disruptive communication is the so called “interactive vandalism” (Anthony Giddens, Sociology). Giddens points out, that effective communication or interaction is based on a cooperative behavior of the participants. If one party of an interaction deliberately behaves in a non-cooperative way, this often is encountered as a aggressive attitude by the other participants. But this is a stylistic device, not an explanation.
Another perspective is that of Erving Goffman‘s “The Presentation of Self in Everyday Life“: people behave as if they were acting. And like in a theater there is a stage and a backstage area. In the front region (stage) they act mostly according to common sense rules. In the back region (backstage) they can “give vent to feelings and styles of behavior they keep in check when on stage”. So acting more anti-social might mean transferring behavioral patterns from back to front.
In traditional social settings this would in general have been a completely unacceptable behavior, but why is it not judged that way now? There is a general process at work transferring the private into the public. Reality shows on TV, social media, liberalization of professional situations. Don’t get me wrong: I don’t judge those processes, but if not backed by a so called “good education” things can go wrong unnoticed. If this happens and some sort of “invisible control” doesn’t come into effect, openly visible regulation is a way to prevent unwanted situations.
An area where this currently happens are public conferences. More and more conference hosts issue code of conduct manifests. I got into some serious discussions because I objected that these rules are pretty obvious and stating them so explicitly might be sort of embarrassing for “well-behaved visitors”. Conference organizers assured me that these rules are not so obvious anymore. Maybe in the future we’ll see explicitly stated rules for human interaction more often. While being liberated from unnecessarily rigid forms of social behavior is a good thing, this feels like a cultural loss to me. But than again I just might be getting old.

Article
1 comment

Science and technology links [22-05-2016]

2652953996_76184c9ef4_z

Here are some interesting links connecting technology and science.

Open Scholar

Open Scholar is a open source content management system based on Drupal. This means it’s written in PHP. It is developed at Harvard University at the Institute of Quantitative Social Science.

Open Science Framework

OSF is a management system for scientific projects. It can be used as a hosted service right at the site or self-hosted. OSF is witten in Python and developed by the Center for Open Science.

The Dataverse Project

The Dataverse Project is a research data repository software. There are at the time of this writing 17 interconnected installations around the world. The software is written in Java and is developed by the aforementioned Institute of Quantitative Social Science at Harvard.

Figshare

Figshare is a repository for research output (mainly publications or papers). It’s a closed-source hosted service developed by Digital Science which also developed Overleaf. More on scientific writing solutions in a later post.

Article
0 comment

How to read in a statistic whatever you want

Professor at chalkboardIt’s a common place that you can read nearly any result you want from a statistic. You just have to optimize your mathematical model or cut short the reasoning about the data. There is currently a JAMA publication from the American Medical Society which is cited in many magazines and newspapers (even in German Spiegel) as “22% less risk of colorectal cancer for vegetarians”. No ordinary reader of these reviews will have a look at the original numbers in the publication since it is not freely available (yet another reason for open Publication …). But here they are:

  • Vegetarian participants: 40367
    Cancer cases: 252
  • Nonvegetarian participants: 37292
    Cancer cases: 238

This makes for the following relative case numbers:

  • Vegetarian: 0,624 / 100 participants
  • Nonvegetarian: 0,638 / 100 participants

Or a difference of 0,014 cases per 100 people. This means, if you eat meat your risk to come down with a form of colorectal cancer increases by 0,014 percent. This reads quite different, doesn’t it?

Article
0 comment

Changing filenames to camel case

Sometimes you’ll encounter the task to rename files named with snake_case to CamelCase. And sometimes there are a lot of those files. For example when porting a CakePHP 1 project to CakePHP 2 or 3. In CakePHP the upgrade console does a decent job renaming a lot of files for you. But in larger projects having subfolders you’re left with an awful lot of unrenamed scripts. This is where my Python 3 script comes in. It renames any filenames in the current directory given as parameters (thanks to Python 3 argparse you can use wildcards!) from snake_case to CamelCase filename. It preserves the extension if the filename has one. It also has a quiet mode (use -q) to suppress any output at the command line and a preview mode just like GNU make (use -n, supersedes -q), which doesn’t do anything but print out what it would have done.

(Picture by Startup Stock Photos CC 0, http://startupstockphotos.com/)

Article
0 comment

Knowledge series, Part 1 – Human capital vs. Human resources

2631466945_de1bbc2cfd_zThe term human capital was coined by american economist Theodore Schultz in his seminal paper “Investment in Human Capital” from 1961 [1]. He starts by discussing that often the consideration of human beings as a form of capital is seen as unethical. To count human beings as capital is justified by a rationale drawing on comparisons and discussions from the beginning of the 20th century, comparing e.g. this approach to sacrificing a hundred human beings in order to save a gun in war. Well, our views on war have changed since 1906. This might explain why today we tend to abhor counting humans as capital.

But there is a second approach originating in the theories of french sociologist Pierre Bourdieu readily summarized in 1986 [2]. He derives his concept of cultural capital from observations of french upper class children gaining substantial advantages in their life compared to working class children resulting from their education. He states that their parents invest economic capital (money) in the education of their children. They accumulate a certain amount of cultural capital which can later on be converted back to economic capital when the owners of the cultural capital get more profitable jobs because of their better education. This cultural capital is saved in what he calls the embodied form which means that the knowledge and education belongs naturally to the person acquiring it. It can not be sold like a physical item. When investing e.g. in a collection of paintings this capital can be seen as transformed into another form of economic capital since the paintings have a certain economic value. But the consumption and appreciation of art and its display at social events also counts as a form of cultural capital, this time in objectified state. When acquiring an academic title the title itself represents the embodied cultural capital of the title holder in a certain institutionalized state.

In contrast the term human resources is nowadays widely used to describe all that concerns staffing or personnel management. It was first used by american economist John Commons in 1893 [3] and was commonplace (please excuse the pun) in economic literature from the 1910s on. It represents the view of employees as assets to the firm. This interpretation is opposed by the preamble of the United Nations International Labour Organization including the principle “Labour is not a commodity“.

When forced to  choose one of the two terms I would opt for “human capital” since its philosophical and sociological implications put the human being at least a bit more in the focus of interest.

References

[1] Schultz, T. W.. (1961). Investment in Human Capital. The American Economic Review, 51(1), 1–17

[2] The Forms of Capital: English version published 1986 in J.G. Richardson’s Handbook for Theory and Research for the Sociology of Education, pp. 241–258.

[3] John R. Commons, The Distribution of Wealth, New York, 1893

(Picture by Ian Muttoo CC BY-ND 2.0, https://www.flickr.com/photos/imuttoo/2631466945/)