Hassan Jalil
Hassan Jalil

Reputation: 1194

NVD3 : Display different values on X axis as compared to the data

I am creating a scattered Graph using NVD3 using the code they have provided in their limited documentation. I have created a Scatter graph function that loops over a JSON and pushes the values to the data array. Now I have 2 values for x axis in my Json , x and run Number. What i want is that the graph should be plotted for the value "x" (which have equal gaps) but it should display values of Run Number on the x axis (which have unequal gaps). We want to do this to make the graph more symmetric, as it is not important for us to display the gaps in graph accurately. What i did was create a new Array xAxisValue and push the Run Numbers onto it while we loop the JSON to get values. values for x are pushed onto the data array , Then using

chart.xAxis.axisLabel('Run No.').tickFormat(d3.format('0d')).tickValues(
        xAxisValue);

I set the Tick Values to the xAxisValue (run Number) and then pass the data variable to the draw chart function

d3.select('#chart svg').datum(myData).call(chart);

But this does not seem to work. My Axis is blank and hovering over a value displays the tool tip displays values of x instead of run number. Because we are dynamically updating the graph i have separated the add Graph and upgrade graph function Here is the code

function addGraph() {

var jsons = [];


chart = nv.models.scatterChart().showDistX(true).showDistY(true)
        .transitionDuration(350).color(d3.scale.category10().range());


chart.tooltipContent(function(key) {
    return '<h3>' + key + '</h3>';
});


chart.scatter.onlyCircles(false);



var myData = scatterData(2, 11, jsons);


d3.select('#chart svg').datum(myData).call(chart);

// add zoom handler

nv.utils.windowResize(chart.update);

return chart;

}

Upgrade Graph Function

function upgradeGraph() {
minValue = 1000000, maxValue = 0, minValueY = 100000000, maxValueY = 0;
var jsons = [];
d3.select('svg').text('');
if ($("#check2").is(':checked')) {
    jsons.push("charge_ONTk_Barrel_L2_mpv.json");
}
if ($("#check1").is(':checked')) {
    jsons.push("charge_ONTk_Barrel_L1_mpv.json");
}
if ($("#check3").is(':checked')) {
    jsons.push("charge_ONTk_Barrel_L3_mpv.json");
}

var myData = scatterData(2, 11, jsons);
chart.xAxis.axisLabel('Run No.').tickFormat(d3.format('0d')).tickValues(
        xAxisValue);
chart.yAxis.axisLabel('S/N (mpv)').tickFormat(d3.format('.04f'));

for (var i = 0; i < xAxisValue.length; i++) {
    console.log("Run Number: " + xAxisValue[i]);
}
console.log("Min Y: " + minValueY + " Max Y " + maxValueY);
chart.forceX([ minValue - 2, maxValue + 2 ]);
chart.forceY([ minValueY - 3, maxValueY + 3 ]);


d3.select('#chart svg').datum(myData).call(chart);

// add zoom
addZoom({
    xAxis : chart.xAxis,
    yAxis : chart.yAxis,
    yDomain : chart.yDomain,
    xDomain : chart.xDomain,
    redraw : function() {
        chart.update();
    },
    svg : chart.svg
});

nv.utils.windowResize(chart.update);
return chart;
}

And the ScatterData Function

function scatterData(groups, points, jsons) {

var data = [];
data.push({
    key : 'Error',
    values : [],
    color : '#FBEC5D'
});
data.push({
    key : 'Bin Content ',
    values : [],
    color : '#0D4F8B'
});
for (var i = 0; i < jsons.length; i++) {
    xAxisValue = [];
    var jsonURL = jsons[i];
    var xmlhttp = new XMLHttpRequest();
    var url = "alljsons/" + jsons[i];

    var parameters = location.search;

    xmlhttp.onreadystatechange = function() {
        if (xmlhttp.readyState == 4 && xmlhttp.status == 200) {
            var myArr = JSON.parse(xmlhttp.responseText);

            var jsonName = jsonURL.split(".");
            var temp = jsonName[0];

            var value = myArr[temp];

            // $(".title" + loop).html(temp);

            for ( var i in value) {

                if (value[i].run > maxValue) {
                    maxValue = value[i].x;
                }
                if (value[i].run < minValue) {
                    minValue = value[i].x;
                }
                if (value[i].y > maxValueY) {
                    maxValueY = value[i].y;
                }
                if (value[i].y < minValueY) {
                    minValueY = value[i].y;
                }
                xAxisValue.push(value[i].run);
                data[1].values.push({
                    x : value[i].x,
                    y : value[i].y,
                    size : 6 // Configure the size of each scatter point
                    ,
                    shape : "circle" 

                });
                var err = value[i].y - value[i].yErr;
                if (err < 0) {
                    err = 0;
                    console.log("error: " + err);
                }
                data[0].values.push({
                    x : value[i].x,
                    y : err,
                    size : 6 // Configure the size of each scatter point
                    ,
                    shape : "triangle-down" 
                });
            }
        }

    };

    xmlhttp.open("GET", url, false);
    xmlhttp.send();
}

return data;

}

Here is the Output i am getting

Outputs

Upvotes: 1

Views: 1589

Answers (1)

Lucas
Lucas

Reputation: 1389

If I understand your question correctly:

For the x-axis ticks, I would use D3's axis.tickformat function. You could create a function mapXToRunNumber(x) that takes an x value and returns a run number (you seem to be close to having this already). Then, you would use: chart.xAxis.tickFormat(mapXtoRunNumber);

For the tooltip to also show the same value as the x-axis, you would use the nvD3 function chart.interactiveLayer.tooltip.headerFormatter(mapXToRunNumber).

Upvotes: 1

Related Questions