Tag Archive for 'visualization'

Sunburst Visualization

In a previous post I showed the ForceDirected visualization I’m working on for version 1.2 of the JavaScript InfoVis Toolkit, today I’d like to talk about another visualization I’ve been working on, the Sunburst Visualization.

What’s the Sunburst Visualization?

I guess an example could help here:

A Sunburst visualization is a radial space-filling visualization technique for displaying tree like structures. There are other space-filling visualization methods that use other visual encodings for describing hierarchies. For example, the Treemap is a space-filling visualization that uses “containment” to show “parent-child” relationships.

There are a couple of subtle changes that can improve the way the information is communicated by this visualization.

  • The “classic” Sunburst visualization uses horizontal labels for node names. One problem with this is that as I mentioned in a previous post labels can be occluded. One solution for this is to rotate labels in a way that they’re not occluded.
  • A simple yet important thing to do when rotating labels is to rotate the labels in a way that they’re always facing up.

    In this example some labels are upside-down:

    A simple check could make labels more readable:

  • Another interesting thing that can be used with the Canvas Text API is the maxWidth parameter. This is an optional parameter that can be used to try to force the text to fit some width. I use this parameter when plotting the Sunburst visualization:

Node Styling and Behavior

The visualization also implements events for hovering and clicking nodes. You can also provide any number of styles to be smoothly updated when hovering and clicking nodes. There’s also onClick and onHover callbacks that are called when a node is clicked or hovered respectively.
For example, this is the configuration I used in the previous example:

        NodeStyles: {
          attachToDOM: false,
          attachToCanvas: true,
          stylesHover: {
            'color': '#d33'
          },
          stylesClick: {
            'color': '#3dd'
          },
          onClick: function(node) {
            //build right column relations list
            buildRightColumnRelationsList(node);

            //hide tip
            sb.tips.tip.style.display = 'none';

            //rotate
            sb.rotate(node, 'animate', {
              'duration': 1500,
              'transition': Trans.Quart.easeInOut
            });
          }
        },

You can also add tool-tips as I did in the example. The configuration I used was:

        Tips: {
          allow: true,
          attachToDOM: false,
          attachToCanvas: true,
          onShow: function(tip, node, elem) {
            tip.innerHTML = node.name;
          }
        },

Node styling and tool-tips can be attached to DOM elements (like HTML or SVG labels) or they can also be attached to the Canvas. The latter method uses an internal MouseEventManager to calculate the position of the mouse event and determine which node of the graph is being hovered or clicked.

Collapsing and Expanding Subtrees

I’ve been also implementing animations for collpasing/expanding subtrees:

The collapsing process reduces the angle span occupied by a parent node and sets its children alpha value to zero. There’s also a visual mark set for collapsed nodes.

I hope you like this visualization. There’s still much work to do, mostly regarding browser compatibility. I’ll keep you up to date with the progress of this visualization and the next visualization I’ll be implementing in the next post :)

Version 1.1.3

I just tagged the JavaScript InfoVis Toolkit with version 1.1.3. It’s been some time since the last release, and I wanted to use this post to make a summary of the changes and to describe some of the new features that have been added to the library.

I’ll start with the new features:

SpaceTree: SwitchAlignment

I added some new global configuration properties to the SpaceTree: align and indent.

Align sets the alignment of the tree to center, left and right:



The indent parameter sets an offset between a parent and its children when the alignment is left or right. You can also use the switchAlignment method for changing the alignment of the tree with an animation.

SpaceTree: Multiple nodes in path

I added two new methods to the SpaceTree: addNodeInPath and clearNodesInPath.
These two methods allow you to add a node to the “selected-nodes” path. When a node belongs to the “selected-nodes” path it remains always visible (as in always expanded).

I made this small video to show the feature:

SpaceTree: MultiTree

I added a SpaceTree configuration property called multitree.
If multitree=true, the visualization will search for the $orn data property in each node and display the subtrees according to their orientation.

In this example I set multitree=true and set $orn=’left’ for some nodes and $orn=’right’ for others. This way I create a partition of the tree:

I also use the setRoot method to set the clicked node as root for the visualization. This way the clicked node is centered and a centrifugal view from that node is drawn.

Bug Fixes

I’ve been fixing a couple of bugs also, most of them have to do with Treemaps:

I also want to thank Guido Schmidt for his interest in the library and work on the GWT JIT component.

There’s also been some JIT development for Grails done by Bertrand Goetzmann.

Anyway, things are looking good! :)

MultiTrees (Part 1)

I found this CHI 94′ visualization paper on MultiTrees in the internet and I’ve been trying to see what type of applications and ideas I could “borrow” for the JavaScript InfoVis Toolkit.

What are MultiTrees?

A MultiTree is a type of directed acyclic graph (DAG) where each node has a tree both as parent structure and as descendants.

For example, a MultiTree can be created by overlapping different tree structures on a set of nodes, as shown in the picture below:

As you can see MultiTrees can have cycles if they’re not directed.

Laying and Navigating MultiTrees

What’s interesting about this structure is that if we take two nodes x and y such that x <= y and the path connecting them, then we can form a topological tree by adding all descendants and ancestors of each node belonging to that path in the new graph.

Implementation

I recently pushed support for a small subset of MultiTrees: those where x = y.
This is just a centered node and its tree of descendants and ancestors.

The tree navigation is the same as the SpaceTree:

I also implemented a way of changing the current focused node, so that when the clicked node is centered a centrifugal view from that node is adopted.
This way the current selected node is set as root of the visualization.
Hopefully you’ll understand the difference between this navigation and the previous one.

Anyway, as soon as I get this feature fully functional I’ll make another post explaining how to use this stuff in the JavaScript InfoVis Toolkit.

Outside In

While taking a look at some of the talks by Tamara Munzner I found this video/documentary about turning a sphere inside out.
I’ve found this to be very impressive (and pedagogic). The style of the video reminds me the Moebius Transformation video I posted last year.

For those who don’t know Tamara Munzner she’s like a big reference in all InfoVis-related stuff. One of the most inspiring InfoVis talks I’ve found was done by her and can be seen here. This is the talk that started my interest in InfoVis and the making of the JavaScript InfoVis Toolkit.

The JavaScript InfoVis Toolkit 1.1 is Out!

After several months of hard work I can finally announce version 1.1 of the JavaScript InfoVis Toolkit.

What’s the JavaScript InfoVis Toolkit?

The JavaScript InfoVis Toolkit provides tools for creating Interactive Data Visualizations for the Web.

What’s new in this version?

Code-Related

  • The library has been split into modules for code reuse.
  • All visualizations are packaged in the same file. You can create multiple instances of any visualization. Moreover, you can combine and compose visualizations. If you want to know more take a look at the Advanced Demos.
  • This Toolkit is library agnostic. This means that you can combine this toolkit with your favorite DOM/Events/Ajax framework such as Prototype, MooTools, ExtJS, YUI, JQuery, etc.
  • You can extend this library in many ways by adding or overriding class methods. The JavaScript InfoVis Toolkit has a robust (and private) class system, heavily inspired by MooTools’, that allows you to implement new methods in the same class without having to define any new Class extension. By creating mutable classes you can add new custom Node and Edge rendering functions pretty easily.
  • Custom visualizations are created by adding or changing Node/Edge colors, shapes, rendering functions, etc. You can also implement many controller methods that are triggered at different stages of the animation, like onBefore/AfterPlotLine, onBefore/AfterCompute, onBefore/AfterPlotNode, request, etc.
    You can also add new Animation transitions like Elastic or Back with easeIn/Out transitions.
    If you want to know more about these features please take a look at the Demos code.

As you can see, this new version has been built with four concepts/goals in mind: Modularity, Customization, Composition and Extensibility. I already explained some of these things in the previous post.

Hope you enjoy it.

More about the JavaScript InfoVis Toolkit 1.1

I’ve been putting a lot of effort in the upcoming version of the JavaScript InfoVis Toolkit lately, and I though it would be a good idea to show some of the new features I came up with.

The new version isn’t finished yet, but I’ve come pretty far and wanted to make a sort of checkpoint for the things I’ve done, the things I’ll be doing and the things I’m thinking about doing.

So what have I been working on?

  • A new project page design.
  • A complete documentation. I made an API documentation that is also mixed with some narrative documentation for each Class, so you can learn how the visualizations are implemented and how to use them.
  • Packaging All visualizations will be packaged in the same file, and you’ll be able to make your own build based on what you’re going to use (Treemaps, Hypertrees, RGraphs, Spacetrees or any combination of those). This is a cool aspect of making modular code.
    The other good thing about modular code is that the size of the full package will drop in ~30% compared to version 1.0.8a
  • Examples I’ve been coding some new visualization examples that will be packaged with the library. Some of them are very similar to the ones found in 1.0.8a, but adapted for version 1.1. Other examples show some of the new features of the library, and others try to expose some features of version 1.0.8a that were not properly documented.

Library features

I’ve been building this library with four things in mind:

  • Extensibility The library has multiple access points where it can be extended in different ways. For example, all main Classes are mutable objects, so you can extend or implement any method of any class in-place, like for example re-implement the nodes coloring method in the Squarified treemap:

       //TM.Strip, TM.SliceAndDice also work
       TM.Squarified.implement({
         'setColor': function(json) {
           return json.data.$color;
         }
       });
    

    …or adding new node/edge plotting methods in the Hypertree, ST or RGraph:

    Hypertree.Plot.NodeTypes.implement({
      'my-node-rendering-method': function(node, canvas) {
        //implement node rendering here
      }
    });
    

    etc.

  • Customization The library provides many ways for customizing the visualizations. There are controller methods that determine the behavior of the visualization, and configuration parameters like node and edge types, color and dimensions. Node shapes can be square, rectangle, circle, ellipse, etc. and edge shapes: line, hyperline and arrow. I also added transition effects like Quart, Bounce, Elastic, Back, etc. for the animations.
  • Modularity As explained above, the code has been divided into modules, providing a way for making custom builds of the library. Modularity also takes care of namespacing: I only add Classes that are meant to be accessed by the user and I don’t pollute the window object with unnecessary global objects.
  • Composition A major improvement in this version is that all visualizations can co-exist in the same namespace. That means that multiple instances of different visualizations can be used and composed to make new visualizations. I haven’t explored this feature of the library yet, but this would mean that for example I can make a Treemap that has Hypertrees rendered as leaves, or a Spacetree that has Treemaps as nodes, or… well, any other combination of things.

Examples

As you might know, I don’t have the most suited computer for making screencasts, so sorry if you see some performance problems.

This is a short video I made of a RGraph example.

The main idea behind this example is Customization.
That can be seen for example in the different node types, edge types and colors used, as well as in the Elastic transition effect for the animation.

This is just an example to expose as much features as I can in one visualization, so don’t take this as a “useful” visualization example please.

Here is another short video: it illustrates how Graph Operations can be made with the Hypertree visualization.

You’ll see 4 consecutive operations:

  1. Removing a subtree The bottom right subtree will be removed with an animation.
  2. Removing edges Edges from the top left subtree will be removed with an animation.
  3. Adding a graph A graph will be added with an animation
  4. Morphing The graph will transform into another graph -with an animation

Enjoy.

Interactive Visualization of Genealogical Graphs

It’s been a while since I last bumped into a nice visualization project like this one.
It offers an advanced interface for exploring Genealogical graphs.

I personally like how nodes are hidden/shown in demand, how the subtree widget is implemented and how you can easily switch between different layouts.

On a side note, I’ve been screencasting the artist/band visualization project I made some time ago with the JavaScript InfoVis Toolkit, hope you find it interesting: it shows relations between artists and bands by collaborations in albums/songs/bands, etc.

You can access a live example here. I think its better rendered with Firefox, Safari, Opera and Chrome 2 (version 1.0.x has a bug).

The left menu offers some navigation options to choose a band as starting point. You can also find details about the focused band under the Details toggler.

Here’s a short video of what you should be able to see:

JavaScript InfoVis Toolkit 1.1 Preview

In case you’re wondering what I’m up to…

I’ve been adding more features to the JavaScript InfoVis Toolkit, to be released I-don’t-know-when-yet (still a lot of work to do regarding documentation, hosting, scripts, etc.).

Anyway, this video shows only some of the features to be included:

  • Custom nodes: built-in shapes are none, circle, square, rectangle, ellipse, among others
  • Custom edges: built-in shapes are none, line, quadratic, bezier, arrow, among others
  • Custom Animations: linear, Quart, Bounce, Elastic, Back, etc.
  • Change tree orientation: already possible in 1.0.8a.

Unfortunately my video card isn’t very good, so the video quality and fps aren’t as good as I’d wanted.
Animations are pretty smooth though, as you can see for yourself, so don’t blame the library, blame my computer!

Anyway, here’s the video:

Another cool thing is that you can also create custom node and edge rendering functions :)

Stay tuned, there are more features to come!

Cushion Treemaps

Remember Treemaps?

There was a thread at the Google Group for the JIT asking for Gradients in Treemaps.

Actually they’re called cushion treemaps, and they have been created by Ph.Ds Jarke J. van Wijk and Huub van de Wetering. Cushion Treemaps have been used in successful applications like SequoiaView and companies like MagnaView are building very interesting visualizations with cushion treemaps.

The paper is quite interesting: cushion treemaps were created by using shading to show a tree’s structure:

“How can we use shading to show the tree structure? The human visual system is trained to interpret variations in shade as illuminated surfaces [6]. Hence, we can answer the question by constructing a surface which shape encodes the tree structure.”

Shadowing is created by adding bumps to rectangles.

In the JavaScript InfoVis Toolkit, this can be done by overriding the leafBox method of the Treemap class. This method renders a leaf node (nodes which are generally colored in the Treemap).
By adding an image of a radial gradient inside that div we can emulate cushion treemaps.

Instead of creating a new class that extends TM and overrides that method, we can take advantage of JavaScript’s object mutability feature and re-implement the method in the same class.


    TM.Squarified.implement({
       leafBox: function(json, coord) {
        var config = this.config;
        var backgroundColor = config.Color.allow && this.setColor(json),
        offst = config.offset,
        width = coord.width - offst,
        height = coord.height - offst;
        var c = {
         'top': (offst / 2) + "px",
         'height':height + "px",
         'width': width + "px",
         'left': (offst / 2) + "px"
        };
        if(backgroundColor) c['background-color'] = backgroundColor;
       //Add an image to our leaf node to create a cushion treemap.
        var img = "<img src='gradient.png' style='position:absolute; z-index:2; top:0; left:0; width:" + c.width + "; height:"+ c.height +"'; />"; 

        return "<div class='leaf' style=" + this.toStyle(c) + ">" + img + json.name + "</div>";
       }
    });

And that’s it, now we have Squarified Cushion Treemaps. I must say that I love cushion treemaps, they look a lot more cool than simple treemaps.

I made a small POC where you can enable/disable the cushion feature, among other interesting things:

cushion treemap

Using OCaml to visualize Radiohead’s HoC music video (part 2)

This post is about performing advanced camera movement in OpenGL.
We’ll use the same Radiohead’s HoC dataset we used in the previous post.

Once again, the quality of the youtube video is pretty lame. You can right click here and save link as… to download a high quality version of the video (~100MB).
I strongly recommend you to see the high quality video :)

Camera Instructions

Camera movement is made of Translations and/or Rotations.
We want to provide our camera model with instructions of the type:

  • [ Translate from to ]
  • [ Rotate from to rotation_axis ]
  • [ Translate ...; Rotate ... ]

As the last example shows, multiple transformations can be done at the same time (translations and rotations).

The definition for a transformation type is:

type camera_op =
  | Translate of Gl.point3 * Gl.point3
  | Rotate of float * float * Gl.vect3

A camera instruction is a list of these operations (camera_op) and a number specifying the number of frames this transformation should take (i.e the duration of the transformation).

So, for example, this instruction:
( [ Translate( (100., 100., 100.), (0., 0., 0.) ) ], 300. )
translates the camera from (100, 100, 100) to (0, 0, 0) in 300 frames, that is in 10 seconds (at 30 frames per second).

Translation is done by simple interpolation. The interpolation formula for translating from A to B is something like this:
A + (B – A) * delta with delta in (0, 1).

Transitions

It would be nice if camera movement, besides being linear, could also perform other advanced transitions, like the ones used in Fx.Transitions by Mootools.
Some of these transitions are: Quadratic, EaseIn, EaseOut, EaseInOut, Back, Sine, etc…

These effects are achieved by applying functions to the delta value, changing the way it increases or descreases its value.
A possible interface for a Transition module is:

type trans = Linear | Quart
type ease = None | EaseOut | EaseIn | EaseInOut

val linear : 'a -> 'a
val quart : float -> float

val ease_in : ('a -> 'b) -> 'a -> 'b
val ease_out : (float -> float) -> float -> float
val ease_in_out : (float -> float) -> float -> float

val get_transition : trans -> float -> float
val get_ease : ease -> (float -> float) -> float -> float

val get_animation : trans -> ease -> float -> float

By using Transition.get_animation Quad EaseInOut delta we can change the timing of our animation from this:

into this:

Our camera instructions are then defined as:


type camera_op_list = (camera_op list) * float * (trans * ease)

For example:
( [ Translate( (100., 100., 100.), (0., 0., 0.) ) ], 300. (Quad, EaseOut))

The Camera Model

A possible interface for the camera model is:

class camera_model :
  object
    val mutable animations : camera_op list
    val mutable time : float
    val mutable total_frames : float
    val mutable transition : Transition.trans * Transition.ease

    method get_time : float
    method step : unit
    method draw : unit
    method translate : Gl.point3 -> Gl.point3 -> float -> unit
    method rotate : float -> float -> Gl.vect3 -> float -> unit
    method set_animations :
      camera_op list * float * (trans * ease) -> unit
  end

The camera_model instance variables contain the destructured camera_op_list type elements: animations, total_frames and transition.
We also provide individual methods for handling translations and rotations. These methods simply compute a delta value, apply the interpolation and then call GlMat.translate3 or GlMat.rotate3.

The 40 line implementation looks like this:

class camera_model =
 object (self)
  val mutable total_frames = 0.
  val mutable time = 0.
  val mutable transition = (Linear, None)
  val mutable animations = []

  method get_time = time

  method set_animations ans =
    let (x, y, z) = ans in
      animations <- x;
      total_frames <- y;
      transition <- z;
      time <- 0.

  method step =
    if time < total_frames then
      time <- time +. 1.

  method translate start last delta =
    let (trans, ease) = transition in
    let delta_val = Transition.get_animation trans ease delta in
    let (x, y, z) = start in
    let (x', y', z') = last in
    let DVertex(a, b, c, d) = Interpolate.cartesian
                                (DVertex(x, y, z, 0.))
                                (DVertex(x', y', z', 0.))
                                delta_val
    in
      GlMat.translate3 (a, b, c)

  method rotate start last vec delta =
    let (trans, ease) = transition in
    let delta_val = Transition.get_animation trans ease delta in
    let ang = Interpolate.cartesian_float start last delta_val in
    GlMat.rotate3 ang vec 

    method draw =
      let delta = time /. total_frames in
        List.iter (fun anim ->
          match anim with
            | Translate(start, last) ->
               self#translate start last delta
            | Rotate(start, last, vec) ->
               self#rotate start last vec delta ) animations
end

Timeline

Now that we have our camera model, we need a “timeline” object that can pass intructions to the camera at different stages of the animation.
We define a class-less object timeline that holds a list of camera transformations to be executed at a specific frame of the animation:

let timeline =
  object (self)
    val mutable frame = 0.
    (* Starting frame number, camera_instructions *)
    val camera_timeline = [
      (1.,   (* camera_instructions *));
      (310., (* camera_instructions *));
      (631., (* camera_instructions *) ]

    method get_frame = frame

    method tick =
      frame <- frame +. 1.;
      self#update_camera;

    method update_camera =
      try
        let camera_anim = List.assoc frame camera_timeline in
          cam#set_animations camera_anim;
        with
          | Not_found -> ()
end

Download and Use

This is all I’ve done to handle camera movement.
I’m not an advanced OpenGL/OCaml developer, so any comment/suggestion about my understanding of OCaml/OpenGL is very welcome.
You can download the source here.
You can compile the source with:

ocamlc -g str.cma -I +camlimages ci_core.cma ci_jpeg.cma ci_bmp.cma
-I +lablGL lablglut.cma lablgl.cma interpolate.ml transition.ml
camera.ml loader.ml main.ml -o main

Last part of this “trilogy” will be about particle transformations in OpenGL.
Hope you enjoyed it!