Hi everybody,
I have been running into some interesting problems with Lumira in building a Lumira extension. The idea comes originally via here and here. I used R to get my data set (thanks to scripts you can find through the second link), and was able to pretty quickly get the chart developed in D3.js, and working in VizPacker:
So far, so good.
However, this doesn't work at all in Lumira. Once I get this in, the best I can get is something like this:
but adding in the alpha.factor or dens.scaled will give me this:
Or, with different way of structuring data, something like this:
Without question, it is to do with how the data is structured, and how Lumira handles it.
Out of R I get some 6,700 rows of data with "density" data, with an x, a y, scaled density (between 0-1, dens.scaled), and alpha.factor (between 0-1) which creates the yellow/red shape (see first image). Then, I have 300 actual data points to be plotted on top (the blue dots). In the attached CSV files you can see this.
In the "data_continuous.csv" I have the actual X and Y as columns next to the "density" dataset, when they should really be separate tables (there is no semantic relationship between these first 300 rows of actuals and the rest of the dataset, in these rows). In the "modded" version, I added the actuals as rows in X and Y, but added a type column to indicate which was "density" and which was "datapoint".
In the D3.js version or in VizPacker, it doesn't seem to matter how the data is structured: I simply get a dataset and can do with each element what I want (whether using the modded or unmodded versions). In Lumira, even when I set all measures aggregations to "None", I can't get this to work, and get these partial visualizations, or a dataset explosion (total data elements is ~7,000, so there should never be any 20,000+ data points (yes, I expanded my 10,000 default....))
Anybody any good ideas? This is not the first time I am running into differences between how VizPacker and Lumira itself treat data, but this is the first time it has really been a show stopper. This visually weighted regression visualization is much better than just showing a confidence interval, and it would be great to get this into Lumira. Anybody any suggestions how I should structure the data, and choose what should be Dimensions, what should be Measures and in what set?
render.js: (uses the 'modded' csv)
/*<<dependency*/
define("comsapvizweightedregression-src/js/render", ["comsapvizweightedregression-src/js/utils/util"], function(util){
/*dependency>>*/
/**
* This function is a drawing function; you should put all your drawing logic in it.
* it's called in moduleFunc.prototype.render
* @param {Object} data - data set passed in
* @param {Object} container - target DOM element (SVG or DIV) of the plot area to render in
* @param {float} width - width of canvas
* @param {float} height - height of canvas
* @param {Array of color string} colorPalette - color palette
* @param {Object} properties - properties of chart
* @param {Object} dispatch - event dispatcher
*/
var render = function(data, container, width, height, colorPalette, properties, dispatch) {
//prepare canvas with width and height of container
container.selectAll('svg').remove();
var vis = container.append('svg').attr('width', width).attr('height', height)
.append('g').attr('class', 'vis').attr('width', width).attr('height', height);
// START: sample render code for a column chart
// Replace the code below with your own one to develop a new extension
/**
* To get the dimension set, you can use either name or index of the dimension set, for example
* var dset_xaxis = data.meta.dimensions('X Axis’); // by name
* var dset1 = data.meta.dimensions(0); // by index
*
* To get the dimension or measure name, you should only use index of the dimension and avoid
* hardcoded names.
* var dim1= dset_xaxis[0]; // the name of first dimension of dimension set ‘X Axis'
*
* The same rule also applies to get measures by using data.meta.measures()
*/
/**
*
*/
var margin = {
top: 20,
right: 20,
bottom: 60,
left: 40
};
var plotWidth = width - margin.left - margin.right,
plotHeight = height - margin.top - margin.bottom;
//transform plot area
vis.attr("transform", "translate(" + margin.left + "," + margin.top + ")");
//create x and y scales, domains and axes
var x = d3.scale.linear()
.range([0, plotWidth]);
x.domain([d3.min(data, function(d){ return +d.x - (Math.abs(+d.x*0.1)); }), d3.max(data, function(d) { return +d.x*1.1; })]);
//y scale:
var y = d3.scale.linear()
.range([plotHeight,0]);
y.domain([d3.min(data, function(d){ return +d.y - (Math.abs(+d.y*0.1)); }), d3.max(data, function(d) { return +d.y*1.1; })]);
var xAxis = d3.svg.axis()
.orient("bottom")
.scale(x)
.tickFormat(d3.format(".2s"));;
var yAxis = d3.svg.axis()
.scale(y)
.orient("left")
.tickFormat(d3.format(".2s"));
//gradient color scale for scaled density
var color = d3.scale.linear()
.domain([0, 1])
.range(["yellow", "red"]);
var densitydata = data.filter(function(el){
return el.type == "density";
});
console.log(densitydata);
var circle = vis.selectAll("density")
.data(densitydata);
circle.enter().append("circle")
.attr("class", "density")
.attr("cx", function(d) { return x(+d.x); })
.attr("cy", function(d) { return y(+d.y); })
.attr("r", "3")
.style("fill", function(d) { return color(+d["dens.scaled"]); })
.style("opacity", function(d) { return (+d["alpha.factor"]>0.02) ? +d["alpha.factor"]*.6 : 0; });
circle.exit().remove();
var actuals = data.filter(function(el){
return el.type == "datapoint";
});
//console.log(actuals);
//draw the data points
var datapoints = vis.selectAll("datapoints")
.data(actuals);
datapoints.enter().append("circle")
.attr("class", "datapoints")
.attr("cx", function(d) { return x(+d.x); })
.attr("cy", function(d) { return y(+d.y); })
.attr("r", "2.5")
.style("stroke", "#404080")
.style("fill", "#bfbfff");
datapoints.exit().remove();
//paint the axes
vis.append("g")
.attr("class", "x axis")
.attr("transform", "translate(0, " + plotHeight + ")")
.call(xAxis);
vis.append("g")
.attr("class", "y axis")
.call(yAxis);
//set style of axis and its ticks and text
$(".axis path, .axis line").css({
fill: 'none',
stroke: '#000',
'shape-rendering': 'crispEdges'
});
$(".axis text").css({
'font-size': '12px'
});
$(".axis > text").css({
"font-size": "16px",
"font-weight": "bold"
});
//set style of axis and its ticks and text
$(".axis path, .axis line").css({
fill: 'none',
stroke: '#000',
'shape-rendering': 'crispEdges'
});
$(".axis text").css({
'font-size': '12px'
});
$(".axis > text").css({
"font-size": "16px",
"font-weight": "bold"
});
// END: sample render code
};
return render;
});