Reading time: 6 minutes and 45 seconds.

Mod data views

This page gives you an introduction to the mod data views.

Data view definition

A mod can create a single aggregated data view.

The data view is declared in the mod manifest. Its content is specified as a number of axes. The Spotfire UI will provide controls to set actual columns/expressions used to build the data view in runtime.

In the simplest form, the data view definition part of a mod manifest could look like this.

"dataViewDefinition": {  
    "axes": [  
        {
            "name": "Y",  
            "mode": "continuous"
        }  
    ]  
}

This specifies that the mod will have a single continuous axis called Y, that will compute a single aggregated value, e.g. Sum(Sales). Continuous axes are typically rendered on a continuous scale.

Bar Chart 1

The “mode” parameter can be “continuous”, “categorical” or “dual”. Dual means that the axis supports both continuous and categorical mode and can be switched between them.

A categorical axis always splits the aggregation. The columns/expressions on the axes are used in the group by clause in the aggregated query generated for the visualization. Categorical axes are typically rendered on a categorical, or discrete, scale.

If we continue the example above we could add a categorical x axis to the visualization.

"dataViewDefinition": {  
    "axes": [  
        {
            "name": "X",  
            "mode": "categorical",  
        },
        {
            "name": "Y",  
            "mode": "continuous",  
        }
    ]  
}

That could be rendered like this:

Bar Chart 2

It is always possible to add more columns to the expression on a categorical axis. This will split the aggregation further, and Spotfire usually renders this as a hierarchy.

Bar Chart 3

Consuming data from JavaScript

The data view object

On the javascript side data is retrieved via a DataView object. The data view has methods for retrieving data rows and information about the current axes that has data mapped to them. The methods on the data view are asynchronous so you need to await their result.

There are two methods available to retrieve the value for an axis in a data row. Depending on the mode of the axis that is being queried there is a continuous method for continuous axes and a categorical method for categorical axes. So, assuming that the Y axis is continuous, you would do the following to get its value:

let yValue = row.continuous("Y");

The value retrieved by these methods can be of two types depending on which one is called. Either it is a DataViewContinuousValue, or it is a DataViewCategoricalValue. To list all values of a data view in csv like format, you could do this:

async function logDataView(dataView)
{
    // Print axes names
    const axes = await dataView.axes();
    console.log(axes.map(axis => axis.name).join(","));

    // Print the row values.
    const rows = await dataView.allRows();
    rows.forEach(row => {
        console.log(axes.map(axis => {
            if(axis.isCategorical){
                return row.categorical(axis.name).formattedValue()
            }
            return row.continuous(axis.name).value()
        }).join(","));

    });
}

For the simple bar chart above showing sales per fruit, the output would be:

X,Y
Apples,16000
Oranges,31000

DataViewContinuousValue and DataViewCategoricalValue

A DataViewContinuousValue is a simple object with methods to retrieve the actual value (value), and to get a string representation of it (formattedValue).

A DataViewCategoricalValue on the other hand is a bit more complicated. Since categorical axes form hierarchies, each DataViewCategoricalValue is made up from parts describing the path in the hierarchy. However, a mod developer may choose to ignore this and treat the whole path as a single value as seen in the simple code example above. For the third bar chart example, the output from the logDataView function would be:

X,Y
Apples >> Spain,2500
Apples >> USA,13500
Oranges >> Spain,12000
Oranges >> USA,19000

If, on the other hand, you want to access all parts of the path this can be done via the path property that returns an array of DataViewCategoricalValuePathElement objects. There is also a leafIndex property, which is the index of this value among the leaves in the hierarchy generated for the axis. This leads us to the next subject.

Hierarchies

Another way to access the data in the data view is to go via hierarchies. These are represented by DataViewHierarchy objects that can be retrieved for all categorical axes. Either via the hierarchy property on the axis you get via getAxis, or via the hierarchy function on the data view.

The hierarchy is a tree structure with some metadata about the levels, and a method to retrieve the root of the tree (root). If you care about the hierarchical structure, you would traverse from the root. If not, you would just use the leaf nodes retrieved from the leaves method on the root object.

Each node in the tree can be mapped to rows in the data view. The following sample shows how to traverse the data view for a bar chart above from the x hierarchy:

async function logViaHierarchy(dataView)
{
    const xHierarchy = await dataView.hierarchy("X");
    const root = await xHierarchy.root();
    log(root, "");

    function log(node, indent) {
        console.log(indent + node.formattedValue());
        indent += "    ";
        if(node.children) {
            node.children.forEach(node => log(node, indent));
        }
        else {
            node.rows().forEach(row => console.log(indent + row.continuous("Y").value()))
        }
    }
}

This would produce the following output (the root has no name):

    Apples
         Spain
             2500
         USA
             13500
     Oranges
         Spain
             12000
         USA
             19000

Data type mapping

Columns and expressions in Spotfire can have a number of different data types. When reading data in JavaScript these types are mapped to corresponding JavaScript types as follows:

Spotfire data type JavaScript data type
Integer number
LongInteger number
Real number
SingleReal number
Currency number
Date Date
DateTime Date
Time Custom object Time
TimeSpan Custom objecet TimeSpan
Boolean boolean
String string
Binary Not supported

Note that some types may have a higher precision in Spotfire than can be represented by the native JavaScript types. For instance the JavaScript Date type has a precision of 1 millisecond, while Spotfire internally has a precision of 100 nanoseconds. The numeric data types LongInteger and Currency, as well as the TimeSpan data type, may also suffer from precision loss.

Specifying data types for continuous axes

Categorical axes basically treat all data types the same way. The data is ordered and its string representation is used. For continuous axes it is possible to specify what data types should be supported. By default, they allow only numeric data. You may also choose to allow additional data types by specifying it in the axis section of the manifest. For instance to support date and time data, you would specify the following:

"dataTypes": {
    "allowDateTime": true,
    "allowNumeric": true
}

In addition to these two flags, there are also flags to turn on support for strings, booleans and time spans.

Using the Spotfire color axis

Mods can use the same color axis as is used by the native Spotfire visualizations. You do this by specifying a “colorAxis” entry in the data view definition section of the manifest:

"dataViewDefinition": {
    "colorAxis": {
    "mode": "dual"
}

The “mode” and other properties for the color axis are specified the same way as for other axes.

On the Javascript side you access the data values for the color axis by referring to it by its name, “Color”. The actual color computed for each row can be retrieved via the color function on a row. It returns an object with the color hexcode.

Using multiple measures on continuous axes

By default you can only have a single measure on a continuous axis. However Spotfire allows having one axis with multiple measures on it. To turn this on, you set the “allowMultipleMeasures” flag to true for the axis in the manifest.

When an axis has multiple measures, Spotfire will place each measure on its own row in the data view. This also requires the special “(Column Names)” expression, [Axis.Default.Names] in the expression language, to be used on a categorical axis in the visualization.

Using non-aggregating expressions on a continuous axes

Mod data views are always aggregated, and by default the expressions used on them must be aggregating. To enable non-aggregating expressions, you can set the “allowNonAggregatingMeasures” flag to true for the axis in the manifest. The Spotfire UIs will then add a (None) option to the aggregation methods. Note that the data view is still aggregated, so the values on the axes will be used to group by in the aggregation.

Data view sort order

By default, the rows in data views are ordered by the categorical axes (or more specifically by the axes that are used to group by when performing the aggregation), in the order in which they are declared. So for instance if you declare a “Column” axis followed by a “Row” axis, the data view will first be sorted by the values on the “Column” axis and then by the “Row” axis.

The color axis is currently always last.

Last modified November 6, 2020