In the last week I spent some time preparing a presentation about Web 2.0, data mining, text analysis and related topics. Among these, I discussed a bit of graph theory and clustering. To show a good demo, I fired up Processing to demonstrate how clustering and graph theory work together to create a nice visualization of tag clouds.
I decided to use Processing for two reasons. First, it is the quickest way I know to create rich dynamic visualizations, without having to spend too much time learning a dedicated language to do so. Also, the language is simple enough to be accessible to the audience to which the end results would be demoed.
To get started, I prepared a text file with all the tags that currently appear on my website. Since Borg uses plain text files to store blog contents, this was a trivial task:
find your/borg/data/directory -name "*.html" | xargs grep "# tags" | sed -e "s/#tags.*://g"
I then went to OpenProcessing and started looking for a contributed visualization to fulfill my needs.
I ended up using Tag Clustering by Kyle McDonald . The visualization was mostly ok, I only had to tweak a bit the format of my text file.
By default, the original visualization continually rotates around the tag cluster on the vertical axis. I wanted to be able to navigate the cluster manually, so I tweaked the code the handle keyboard-based navigation.
The first thing to do is to add some handlers for key events, using the keyPressed callback :
void keyPressed() {
if (key == 'r') {
myZoom *= 1.1;
} else if (key == 'f') {
myZoom /= 1.1;
} else if (key == 'w') {
deltaY += 0.05;
} else if (key == 's') {
deltaY -= 0.05;
} else if (key == 'a') {
deltaX += 0.05;
} else if (key == 'd') {
deltaX -= 0.05;
} else if (key == 'q') {
rotationAngle += PI/40;
} else if (key == 'e') {
rotationAngle -= PI/40;
}
}
Then I had to tweak the rendering functions to react to my keypresses instead of continuously rotating the graph. For example I changed TagDirectedGraph.reposition() from:
translate(width/2 - centroid.x(), height/2 - centroid.y());
rotateY(frameCount * rotationSpeed);
scale(centroid.z());
to
float myX = width/2 + deltaX*width;
float myY = height/2 + deltaY*width;
translate(myX, myY);
rotateY(rotationAngle);
scale(myZoom);
Similar changes have been applied to Vertex.java and other parts. I saved my customizations in a zip file you can download and compare with the original code written by Kyle.
This picture shows the overall result.
If you download the code, use these keys to navigate the graph:
- w,s,a,d : move up,down,left,right
- q,e : rotate counterclockwise and clockwise
- r,f : zoom in, zoom out
You are here:
Tags