Axiis – New data visualization framework

axiis_logo

Well, I guess it is time to finally let the cat out of the bag.  For the past few months Michael VanDaniker and I have been working away on a new open source project we have named Axiis (you can thank Juan Sanchez for the great name.)   We are still a couple months away from our first public alpha release, but I think it is worthwhile spending some time to discuss the details of what we have been developing. 

Axiis represents a new way to conceive of and develop interactive data visualizations.   It is based on Flex and ActionScript 3.0 but has a uniquely different approach to creating visualizations than the standard Flex charts, and pretty much any other data visualization package I have seen.  Our primary goal in developing Axiis is to create very concise, expressive, and flexible framework that uses a purely declarative (markup) based approach to create anything from simple cartesian charts to very complex and involved data visualizations.  

Now I realize the preceeding paragraphs sounds like the over-hyped and cliched parlance of most software marketing materials, but let me go on to explain some of the fundamental precepts of Axiis and why I think those claims are valid descriptions of what we are doing.  Due to the amount of material I want to cover I will break this up across several blog posts. 

Uniquely Different Approach:  

As part of the initial use cases that Michael and I evaluated before we started developing Axiis we looked at a range of visualizations like this and this as well as the standard cartesian and polar charts and many other examples that we wanted to be able to easily describe within Axiis. I wanted to create a domain specific language that made it easy to build these types of visual structures without requiring the developer to devote weeks of effort understanding our library.  I also didn’t want to create a big bag-o-components that was simply some massive library of tightly encapsulated charting components.  One of the things I really struggled with in the standard Flex charts from Adobe was customization, any time I wanted to do anything that didn’t have property exposed for it I very quickly found myself neck deep several levels up an object inheritance chain hacking at protected properties and mucking about in relatively complex procedural code.   I realized the answer was simply not exposing more properties or creating a different class inheritance chain, but taking a fundamentally different approach altogether, and that is what I think we have done. 

Axiis helps the developer to focus on how things are being visualized versus WHAT is being visualized.  This concept while different than standard “data series” focused charting packages, allows us to create a relatively lightweight framework that can be extremely modular and flexible and not dependent on a rigid and/or deep class hierarchy to describe visualization components.  It allow developers to mix and match pieces at a granular level and composite those pieces together to form very complex, reusable, and customized data visualization structures.   

The primary conceptual focus in Axiis revolves around two main core concepts:  Geometries and Layouts.   Geometries represent what graphics are actually getting plotted to the screen when representing data, and Layouts focus on how those Geometries are arranged in relationship to each other and the data itself.   

Geometries: 

Geometries represent a visual plot of a specific data item within a data set, usually represented as a primitive or composite shape.  Every geometry has properties that are unique to that shape that can be declared directly in MXML and bound to other values.  Since we are leveraging the Degrafa Framework for our render engine, you enjoy a rich geometry library with a full complement of styles, fills, strokes and you can also build your own complex geometries by compositing together primitive shapes that can be customized via their attributes.   

Layouts: 

Layouts are really the magic of the framework and where all of the work gets done in translating data values into visual structures.  Layouts in Axiis are very similar to concept of the GeometryRepeater in Degrafa.   A Layout contains two main elements.  One is a reference geometry, which once again can be any geometry or composite geometry you can describe in Degrafa.  The second element is a set of property modifiers which simply target one or more specific properties within the reference geometry for modification.   The modification to the reference properties occur as Layout iterates across a defined dataset.  Here is an example of a HorizontalBoxLayout that simply repeats a Rectangle horizontally (reference geometry) across a given bounds for a given dataset based on the number of items within that data set. 

Horizontal Box Layout:

<BaseLayout> 
<mx:Number id="percentGap">.05</mx:Number> 
<referenceRepeater> 
 <GeometryRepeater id="myLayout" dataProvider="{dataItems}"> 
  <geometry> 
    <degrafa:RegularRectangle   x="0"  y="0"  
      width="{(bounds.width / itemCount) - (bounds.width * percentGap/2)}"  
      height="{bounds.height}"/> 
  </geometry> 
  <modifiers> 
    <PropertyModifier 
       property="x"
       modifier="{bounds.width/itemCount}" 
       modifierOperator="add"/> 
   </modifiers> 
 </GeometryRepeater> 
</referenceRepeater> 
</BaseLayout> 

Something like this could be used as a basis or a layout for a simple column chart with a single series of data, or possibly, by leveraging a nested layout, a more complex example of a clustered or stacked column chart with multiple series of data.  Thats right, Layouts can also contain child layouts which create a mechanism for recursive rendering and traversing multi dimensional and hierarchal data. 

The second main element of a layout (not shown above) is the drawing geometry.  Layouts were designed in a way that you do not have to declare the drawing geometry if you choose to factor a layout into its own MXML class (like above) and use that layout as a basis for other visualizations.   When we release Axiis, we will end up shipping with many pre-configured layouts like the one shown above as a basis for the standard cartesian charts that will also ship with Axiis.    

Bullding Visualizations 

Taking the above HorizontalBoxLayout and using it to create a simple column chart is a relatively easy affair as demonstrated below:

Simple Column Chart:

<DataCanvas xmlns="http://www.axiis/org/2009" 
  xmlns:mx="http://www.adobe.com/2006/mxml
  xmlns:degrafa="http://www.degrafa.com/2007" >     
   <mx:String id="verticalField"/> 
   <mx:String id="horizontalField"/> 
   <mx:Number id="percentGap"/>
   <mx:Boolean id="showLabels"/> 
   <mx:Object id="dataProvider"/>
   
  <LinearScale  id="vScale" dataProvider="{dataProvider}
    dataField="{verticalField}" minLayout="0
    maxLayout="{height-100}" minValue="0"/> 
  <layouts> 
      <HorizontalBoxLayout id="myLayout" dataField="{verticalField}"
       dataProvider="{dataProvider}"   
       width="{this.width}" height="{this.height-100}
       percentGap="{percentGap}" dataField="{verticalField}" labelField="{horizontalField}"> 
         <drawingGeometries> 
            <degrafa:RegularRectangle id="myColumn
               x="{myLayout.currentReference.x}
               y="{myLayout.height-vScale.valueToLayout(myLayout.currentDataValue)}
               height="{vScale.valueToLayout(myLayout.currentValue)}
               fill="{columnFill}
               stroke="{columnStroke}"/> 
             <degrafa:RasterText id="myLabel" text="{myLayout.currentLabel}"  
                 x="{myLayout.currentReference.x}" width="90" y="{height}"  
                 fontSize="16" align="right" fontFamily="Arial" visible="{showLabels}"> 
          <drawingGeometries> 
       </HorizontalBoxLayout> 
   </layouts> 
   <fills> 
     <degrafa:SolidColorFill id="columnFill" color="0x555555"/> 
   </fills> 
   <strokes> 
     <degrafa:SolidStroke id="columnStroke" weight="1" color="black"/> 
   </strokes> 
</DataCanvas> 

The code above represents all of the source code you would use to describe a base column chart class, that can then be implemented within your application with a single line.  In this case this is very simple single series column chart with a fixed set of fills/strokes. 

For the column chart you notice a new base class (DataCanvas) and the addition of a RegularRectangle to the drawingGeometreis of our HorizontalBoxLayout which is used as the layout class for our DataCanvas.  The DataCanvas in Axiis is a container that holds a set of layouts, graphical assets, and some other utility properties.  The role of the DataCanvas is to mange the layouts render lifcycle and coordinate user interaction events within the layouts geometries.   

In the code above we have also added some convenience variables declared in MXML that allow us to expose this column chart as a stand alone component.  This is just a very rudimentary example of a simple chart, but these declared variables and the structure of the chart itself can be expanded to accomodate a much wider array of use cases, such as variable number of series, color palettes, states, and nested layouts.  This is something we will dive into further in future posts. 

The RegularRectangle in drawingGeometries gets most of its properties set via MXML binding to the horizontalBoxLayouts “current” variables.   This declaration of the drawingGeometry is where all the magic happens and can be a little tricky to conceptualize, but once you understand how it works a whole new world opens up and declarative “programming” will take on a new meaning for you. 

The reason why we created a separation between a referenceGeometry and a drawingGeometry was two-fold.  First we wanted to make it possible to describe a layout algorithm without having to predefine the specific rendering implementation.  Second, we wanted to separate logical concerns.  The referenceGeometry’s primary role has to do with the rules that determine the bounds and position (as described by any geometry, not just a Rect) of a data plot in relationship to the iteration, while the drawingGeometry implements the specific visualization that will be rendered to the screen.   In using this design pattern we are really relying upon Flex Binding to do a lot of heavy lifting for us, and as long as the binding is limited by the components render cycle we do not anticipate any significant performance degradation.

Lets explore this in a little more detail. 

Render Lifcycle 

When it comes time for a Layout to render its drawingGeometries it is going to use its dataProvider to iterate through the data, creating a Sprite for each iteration and applying the property modifiers in the referenceRepeater to the referenceGeometry.  For each iteration the layout will first modify the referenceGeomery and then set its currentReference (and currentValue, currentLabel, currentDatum) to the corresponding datum in the dataProvider.  The currentReference is that iterations instance of the referenceGeometry after the property modifiers have been applied.  The drawingGeometries will often have one or more of their properties bound (via MXML binding) to some variation of the layouts currentReference, currentValue, currentLabel, and/or currentDatum.    Thus, for each iteration the Layout first modifies the referenceGeometry, and sets its current values, binding propagates those changes to the drawingGeometry, and the Layout then renders the drawing Geometry to the graphics context of its corresponding Sprite that is generated by the layout and specific to that data item.  This cycle is repeated for each item within the dataset.   So even though in markup you are only defining one reference geometry and one drawing geometry, they both just serve as dynamic description of your final rendering that is based on the compounding of property modifications and binding that occurs through iterating across the dataset. 

I realize the preceding paragraph sounds a bit dense and convoluted, so don’t worry if it doesn’t make a lot of sense right now.  Once you start working with the code you will develop a much more intuitive understanding of what is described above. 

Here is the cycle step by step. 

Layout Render Cycle. 

1. DataCanvas initiates the Layouts render() method 
2. Loop through each item in the dataProvider 
    2.1 Create a Sprite for each data item (if it has not already been created) 
    2.2 Apply all property modifiers to the referenceGeometry for that iteration 
    2.3 Set all "current" properties of Layout (currentReference, currentValue, currentLabel, currentDatum)
    2.4 Binding triggers updates to all drawingGeometries
    2.5 Layout renders the drawingGeometries to the graphics context of that iterations sprite
    2.6 Continue loop for each data item
3. DataCanvas updates its display list 

So that is a quick introduction to what we are doing with Axiis and little deep dive into how we are doing it.   I have glossed over many of the details here, and I suspect this post will raise more questions than it answers, but in a subsequent post I will explore some more details of Axiis that I believe allow it to live up to the claim of expressive, concise, and flexible and describe some of the more complex functionality in more detail.


 
 
 

9 Responses to “Axiis – New data visualization framework”

  1. Ryan Phelan
    1. April 2009 at 13:46

    This sounds awesome. I will definitely be giving this a go. Have you done any performance testing yet?

  2. admin
    1. April 2009 at 15:29

    @Ryan,

    We have done some preliminary performance testing, as we plan on incorporating animation for interpolated layouts. Preliminary results with no optimization is indicating a 1ms-2ms draw rate per data item. Which I don’t consider to be stellar performance, but for a data set with 500 items that would translate to roughly a 500ms-1000ms render cycle. Our goal will be able to support 25 FPS animation for tweening and interpolation of data items, but that work will probably take place a little later in the framework lifecycle.

  3. Draco
    3. April 2009 at 05:49

    WoW o.0

    This sounds great!

    When do you plan to release this?

    Do you want to sell it, or be as nice to us poor developers as creators of Degrafa ;)

    Anyway I am really looking forward to it.

  4. admin
    3. April 2009 at 08:04

    @Draco, will be releasing more details in the coming weeks, but plan on an official announcement (and presentation) at the upcoming 360 Flex in Indianapolis in May. Our plans thus far is to release the core library under MIT (just like Degrafa.) We very much want this to be a community effort, and I will be actively looking for contributors later in the year.

  5. Axiis – Visualization Framework on Datavisualization.ch
    3. April 2009 at 12:08

    [...] Axiis is a new visualization framework based on Flex and AS 3.0. I recommend reading Tom’s extensive post about the creation of the framework. Visit Form-Function for more details. [...]

  6. Rachel
    7. April 2009 at 20:27

    Wow, at first I thought this was an April Fool’s joke (noting 4/1/09 date and “sounds too good to be true” feeling). A few scrolls in, it still sounds good but also sounds true.

    Thank you (in advance) for your work. I’m looking forward to it.

  7. Tom
    7. April 2009 at 20:34

    @Rachel, funny you should mention that. After I posted the entry I had thought “gee, I hope no one thinks this is an April fools joke.” It is for real, and I plan on having our first alpha release ready for 360 Flex in mid-may.

  8. Axiis - A different kind of data visualization framework
    11. April 2009 at 08:29

    [...] data visualization framework we’ve been developing. Tom goes into a good deal of depth about how the system works, so I won’t rehash all those specifics here. I just wanted to share my take on what Axiis is [...]

  9. Jeremy Saenz
    16. April 2009 at 12:17

    Boy am I excited to start playin’ with this :)

Leave a Reply