Reading time: 6 minutes and 45 seconds.
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.
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:
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.
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.