I am a newbie with D3 library and I am stuck with zooming on a graph.
I display correctly my data over several graphs. But when I zoom, everything goes wrong. I don't know if I miss something with Domains or Ranges or anything... so I ask.
You can find a demo of my code here: http://pastehtml.com/view/cos13vodt.html
And here is the jsFiddle example: http://jsfiddle.net/84mSQ/
And my JS code is there:
var margin = {top: 30, right: 150, bottom: 30, left: 50},
width = 960 - margin.left - margin.right,
height = 500 - margin.top - margin.bottom;
//To parse dates as they are into the CSV
var parseDate = d3.time.format("%Y/%m/%d-%H:%M").parse;
var format = d3.time.format("%d/%m/%y-%H:%M");
var x = d3.time.scale()
.range([0, width]);
var y = d3.scale.linear()
.range([height, 0]);
var color = d3.scale.category10();
var xAxis = d3.svg.axis().scale(x)
.orient("bottom");
var yAxis = d3.svg.axis().scale(y)
.orient("left")/*.ticks(30)*/;
var zoom = d3.behavior.zoom()
.x(x)
.scaleExtent([1, 2])
.on("zoom", function(scale, translate){
console.log("fonction zoom");
console.log(scale); console.log(translate);
zoomed(scale, translate);
});
// A line generator.
var line = d3.svg.line()
.interpolate("basis")
.x(function(d) { return x(d.date); })
.y(function(d) { return y(d.value); });
var svg = d3.select("body")
.append("svg")
.attr("width", width + margin.left + margin.right)
.attr("height", height + margin.top + margin.bottom)
.append("svg:g")
.attr("transform", "translate(" + margin.left + "," + margin.top + ")")
.call(zoom);
svg.append("rect")
.attr("class", "pane")
.attr("width", width)
.attr("height", height);
// Get the data
d3.csv("./enregistrement-subset2.csv", function(data) {
color.domain(d3.keys(data[0])
.filter(function(key) {
return key !== "date" && key !== "ECS - Button A" ;
}));
data.forEach(function(d) {
//Parse the date
d.date = parseDate(d.date);
});
var dataSet = color.domain().map(function(name) {
return {
name: name,
values: data.map(function(d) {
//parses the number by using the '+' operator
if(name == "CO2 chambre"){
return { date: d.date, value: (+d[name])/10};
}
else{
return { date: d.date, value: +d[name]};
}
})
};
});
// Scale the range of the data
x.domain(d3.extent(data, function(d) { return d.date; }));
y.domain([
d3.min(dataSet, function(c) { var mini = d3.min(c.values, function(v) { return v.value; }); return mini; }),
d3.max(dataSet, function(c) { var maxi = d3.max(c.values, function(v) { return v.value; }); return maxi; })
]);
svg.append("g")
.attr("class", "x axis")
.attr("transform", "translate(0," + height + ")")
.call(xAxis);
svg.append("g")
.attr("class", "y axis")
.call(yAxis)
.append("text")
.attr("transform", "rotate(-90)")
.attr("y", 6)
.attr("dy", ".71em")
.style("text-anchor", "end")
.text("Value of");
var valueSet = svg.selectAll(".valueSet")
.data(dataSet)
.enter().append("g")
.attr("class", "valueSet");
valueSet.append("path")
.attr("class", "line")
.attr("d", function(d) { return line(d.values); })
.style("stroke", function(d) { return color(d.name); })
.call(line);
valueSet.append("text")
.datum(function(d) { return {name: d.name, value: d.values[d.values.length - 1]}; })
.attr("transform", function(d) { return "translate(" + x(d.value.date) + "," + y(d.value.value) + ")"; })
.attr("x", 3)
.attr("dy", ".35em")
.text(function(d) { return d.name; });
//zoomed();
});
function zoomed() {
console.log("here", d3.event);
svg.select("g.x.axis").call(xAxis);
svg.select("g.y.axis").call(yAxis);
//svg.selectAll("path.line").call(line);
svg.selectAll("path.line").attr("d", line);
//d3.select("#footer span").text("PĂ©riode de temps: " + x.domain().map(format).join("-"));
}
Can anybody tell me what I did wrong with this code ?
Should I re-design it ?
Are there performances issue to preview if I use a huge amount of data and what should I do then ?
var zoom = d3.behavior.zoom()
.x(x)
**.scaleExtent([1, 2])** <---
.on("zoom", function(scale, translate){
console.log("fonction zoom");
console.log(scale); console.log(translate);
zoomed(scale, translate);
});
take out the .scaleExtent([1, 2]) and check if it is working
should be
var zoom = d3.behavior.zoom()
.x(x)
.on("zoom", function(scale, translate){
console.log("fonction zoom");
console.log(scale); console.log(translate);
zoomed(scale, translate);
});
it is because your x axis is time.
Related
I have a line graph which looks fine. The data set is mostly random data with one big spike. The second dataset is just the log2 of each value. I can transition between the two and it looks great. The y axis is transitioning too. But the scale of the line is not transitioning. Not sure how to get the line to update with the right scale.
$(function() {
var margin = { top: 300, right: 100, bottom: 100, left: 100 },
width = 1400 - margin.right - margin.left,
height = 1080 - margin.top - margin.bottom;
var parseTime = d3.timeParse("%H:%M:%S");
var x = d3.scaleTime().range([0, width]);
var y = d3.scaleLinear().range([height, 0]);
var log2y = d3.scaleLinear().range([height, 0]);
var valueline = d3.line()
.curve(d3.curveMonotoneX)
.x(function (d) { return x(d.date); })
.y(function (d) { return y(d.value); });
var log2valueline = d3.line()
.x(function (d) { return x(d.date); })
.y(function (d) { return y(Math.log2(d.value)); });
var svg = d3.select("body").append("svg")
.attr("width", width + margin.left + margin.right)
.attr("height", height + margin.top + margin.bottom)
.append("g")
.attr("transform", "translate(" + margin.left + "," + margin.top + ")");
d3.select("body").attr("align", "center");
d3.csv("data.csv", function (error, data) {
if (error) {
throw error;
}
var log2data = [];
var log10data = [];
data.forEach(function (d, index) {
d.date = parseTime(d.date);
d.value = +d.value;
log2data[index] = { "date": d.date, "value": Math.log2(+d.value) };
log10data[index] = { "date": d.date, "value": Math.log10(+d.value) };
});
x.domain(d3.extent(data, function (d) { return d.date; }));
y.domain([0, d3.max(data, function (d) { return d.value; })]);
log2y.domain([0, d3.max(log2data, function (d) { return d.value; }) ]);
svg.append("path")
.data([data])
.attr("class", "line")
.attr("d", valueline);
svg.append("g")
.attr("class", "xaxis")
.attr("class", "chart")
.attr("transform", "translate(0, " + height + ")")
.call(d3.axisBottom(x).ticks(d3.timeMinute.every(10)));
var yaxis = svg.append("g")
.attr("class", "yaxis")
.attr("class", "chart")
.call(d3.axisLeft(y).ticks(5));
yaxis
.transition().duration(500).delay(2000)
.call(d3.axisLeft(log2y).ticks(4));
svg.selectAll("path")
.data([log2data])
.transition().duration(500).delay(2000)
.attr("d", valueline);
});
});
So here is the chart before the transition:
And here is the chart after the transition:
Adding the update from Harpal, I see this:
It's because the new line is still using the old scale (valueline)
Change this:
svg.selectAll("path")
.data([log2data])
.transition().duration(500).delay(2000)
.attr("d", valueline);
to this:
svg.selectAll("path")
.data([log2data])
.transition().duration(500).delay(2000)
.attr("d", log2valueline);
So the solution, as with so many things, is to go for a walk, get something to eat, and return with a fresh look. I rewrote it, based on what I learned thus far and have a working solution:
$(function () {
var margin = { top: 300, right: 100, bottom: 100, left: 100 },
winwidth = $(window).width(),
winheight = $(window).height(),
width = winwidth - margin.right - margin.left,
height = winheight - margin.top - margin.bottom,
x = d3.scaleTime().range([0, width]),
y = d3.scaleLinear().range([height, 0]);
var parseTime = d3.timeParse("%H:%M:%S");
var valueline = d3.line()
.curve(d3.curveMonotoneX)
.x(function (d) { return x(d.date); })
.y(function (d) { return y(d.value); });
var svg = d3.select('body').append('svg')
.attr("width", winwidth)
.attr("height", winheight)
.append("g")
.attr("transform", "translate(" + margin.left + "," + margin.top + ")");
var path = svg.append("path");
var xaxis = svg.append("g")
.attr("class", "xaxis")
.attr("class", "chart")
.attr("transform", "translate(0, " + height + ")");
var yaxis = svg.append("g")
.attr("class", "yaxis")
.attr("class", "chart");
function step1(sourcedata) {
var data = sourcedata.data;
var y = d3.scaleLinear().range([height, 0]);
y.domain([0, d3.max(data, function (d) { return Math.log2(d.value); })]);
valueline = d3.line()
.curve(d3.curveMonotoneX)
.x(function (d) { return x(d.date); })
.y(function (d) { return y(Math.log2(d.value)); });
path
.data([data])
.transition()
.attr("class", "line")
.attr("d", valueline);
yaxis
.transition()
.call(d3.axisLeft(y).ticks(4));
}
d3.select("body").attr("align", "center");
d3.csv("data.csv", function (error, data) {
if (error) {
throw error;
}
data.forEach(function (d) {
d.date = parseTime(d.date);
d.value = +d.value;
});
x.domain(d3.extent(data, function (d) { return d.date; }));
y.domain([0, d3.max(data, function (d) { return d.value; })]);
path
.data([data])
.attr("class", "line")
.attr("d", valueline);
xaxis
.attr("transform", "translate(0, " + height + ")")
.call(d3.axisBottom(x).ticks(d3.timeMinute.every(10)));
yaxis.call(d3.axisLeft(y).ticks(5));
$("#rescale").click(data, step1);
});
});
And the graph works as follows:
I'm trying to get 2 completely different d3 charts (2 line charts but totally different data - one with several lines and negative data, other with one line positive data) on the same page.
Right now, I only get the first one to be generated and shown correctly on the HTML page, the second chart doesn't show at all (not even svg container is generated).
Here is my code:
(function() {
// Get the data
d3.json("../assets/js/json/temperature.json", function(data) {
// Set the dimensions of the canvas / graph
var margin = {top: 30, right: 20, bottom: 30, left: 25},
width = 600 - margin.left - margin.right,
height = 270 - margin.top - margin.bottom;
// Parse the date / time
var parseDate = d3.time.format("%Y-%m-%d %H:%M:%S").parse;
// Set the ranges
var x = d3.time.scale().range([0, width]);
var y = d3.scale.linear().range([height, 0]);
// Define the axes
var xAxis = d3.svg.axis().scale(x)
.orient("bottom").ticks(5);
var yAxis = d3.svg.axis().scale(y)
.orient("left").ticks(5);
// Define the line
var valueline = d3.svg.line()
.x(function(d) { return x(d.temps); })
.y(function(d) { return y(d.temperature); });
// prepare data
data.forEach(function(d) {
d.temps = parseDate(d.temps);
d.temperature = +d.temperature;
});
// Adds the svg canvas
var svg = d3.select("#graphTemp")
.append("svg")
.attr("width", width + margin.left + margin.right)
.attr("height", height + margin.top + margin.bottom)
.append("g")
.attr("transform", "translate(" + margin.left + "," + margin.top + ")");
// Scale the range of the data on domain
x.domain(d3.extent(data, function(d) { return d.temps; }));
y.domain([0, d3.max(data, function(d) { return d.temperature; })]);
// Add the valueline path.
svg.append("path")
.attr("class", "line")
.attr("d", valueline(data));
// Add the X Axis
svg.append("g")
.attr("class", "x axis")
.attr("transform", "translate(0," + height + ")")
.call(xAxis);
// Add the Y Axis
svg.append("g")
.attr("class", "y axis")
.call(yAxis)
.append("text")
.attr("transform", "rotate(-90)")
.attr("y", 6)
.attr("dy", ".71em")
.style("text-anchor", "end")
.text("Temperatures");
});
})();
(function(){
// loads the data and loads it into chart - main function
d3.json("../assets/js/json/maitrise.json", function(data) {
var m = {top: 20, right: 5, bottom: 30, left: 40},
w = 70 - m.left - m.right,
h = 30 - m.top - m.bottom;
var x = d3.scale.linear().domain([0, data.length]).range([0 + m.left, w - m.right]);
var y = d3.scale.linear()
.rangeRound([h, 0]);
var line = d3.svg.line()
.interpolate("cardinal")
.x(function(d,i) { return x(i); })
.y(function (d) { return y(d.value); });
var color = d3.scale.ordinal()
.range(["#28c6af","#ffd837","#e6443c","#9c8305","#d3c47c"]);
var svg2 = d3.select("#maitrisee").append("svg")
.attr("width", w + m.left + m.right)
.attr("height", h + m.top + m.bottom)
.append("g")
.attr("transform", "translate(" + m.left + "," + m.top + ")");
// prep axis variables
var xAxis2 = d3.svg.axis()
.scale(x)
.orient("bottom");
var yAxis2 = d3.svg.axis()
.scale(y)
.orient("left");
//console.log("Inital Data", data);
var labelVar = 'id'; //A
var varNames = d3.keys(data[0])
.filter(function (key) { return key !== labelVar;}); //B
color.domain(varNames); //C
var seriesData = varNames.map(function (name) { //D
return {
name: name,
values: data.map(function (d) {
return {name: name, label: d[labelVar], value: +d[name]};
})
};
});
console.log("seriesData", seriesData);
y.domain([
d3.min(seriesData, function (c) {
return d3.min(c.values, function (d) { return d.value; });
}),
d3.max(seriesData, function (c) {
return d3.max(c.values, function (d) { return d.value; });
})
]);
var series = svg2.selectAll(".series")
.data(seriesData)
.enter().append("g")
.attr("class", function (d) { return d.name; });
series.append("path")
.attr("class", "line")
.attr("d", function (d) { return line(d.values); })
.style("stroke", function (d) { return color(d.name); })
.style("stroke-width", "2px")
.style("fill", "none");
});
})();
OK, I found where the error was coming from. There was a piece of javascript in the middle of the HTML page that stopped d3 to generate the second graph further down in the page.
Thanks for all the help!
I've adapted this code from the multi-line line chart example here. The biggest issue I'm now having after researching what changes I needed to make is that the data lines disappear when I use .rangePoints on the x-axis ordinal scale. With just .range, the x-axis displays nothing and the data lines are bunched up along the left side of the y-axis. This has something to do with the fact I altered the original code from a time scale to ordinal, but I'm stumped as to what further changes I need to make.
Code below:
var margin = {top: 20, right: 80, bottom: 30, left: 50},
width = 500 - margin.left - margin.right,
height = 280 - margin.top - margin.bottom;
var x = d3.scale.ordinal()
.rangePoints([0, width]);
var y = d3.scale.linear()
.range([height, 0]);
var color = d3.scale.category10();
var xAxis = d3.svg.axis()
.scale(x)
.orient("bottom");
var yAxis = d3.svg.axis()
.scale(y)
.orient("left");
var line = d3.svg.line()
.interpolate("linear")
.x(function(d) { return x(d.episodes); })
.y(function(d) { return y(d.season); });
var svg = d3.select("body").append("svg")
.attr("width", width + margin.left + margin.right)
.attr("height", height + margin.top + margin.bottom)
.append("g")
.attr("transform", "translate(" + margin.left + "," + margin.top + ")");
d3.csv("data.csv", function(error, data) {
color.domain(d3.keys(data[0]).filter(function(key) { return key !== "episodes"; }));
var seasons = color.domain().map(function(name) {
return {
name: name,
values: data.map(function(d) {
return {date: d.episodes, season: +d[name]};
})
};
});
x.domain(data.map(function(d) { return d.episodes; }));
y.domain([
d3.min(seasons, function(c) { return d3.min(c.values, function(v) { return v.season; }); }),
d3.max(seasons, function(c) { return d3.max(c.values, function(v) { return v.season; }); })
]);
svg.append("g")
.attr("class", "x axis")
.attr("transform", "translate(0," + height + ")")
.call(xAxis);
svg.append("g")
.attr("class", "y axis")
.call(yAxis)
.append("text")
.attr("transform", "rotate(-90)")
.attr("y", 6)
.attr("dy", ".71em")
.style("text-anchor", "end")
.text("Viewership (in mlns)");
var s = svg.selectAll(".city")
.data(seasons)
.enter().append("g")
.attr("class", "city");
s.append("path")
.attr("class", "line")
.attr("d", function(d) { return line(d.values); })
.style("stroke", function(d) { return color(d.name); });
s.append("text")
.datum(function(d) { return {name: d.name, value: d.values[d.values.length - 1]}; })
.attr("transform", function(d) { return "translate(" + x(d.value.date) + "," + y(d.value.season) + ")"; })
.attr("x", 3)
.attr("dy", ".35em")
.text(function(d) { return d.name; });
});
I'm a d3 novice trying to create a simple, two-series bar chart that transitions when different buttons are clicked. The original chart is constructed:
var margin = {top: 20, right: 20, bottom: 30, left: 40},
width = 960 - margin.left - margin.right,
height = 500 - margin.top - margin.bottom;
var x0 = d3.scale.ordinal()
.rangeRoundBands([0, width], .1);
var x1 = d3.scale.ordinal();
var y = d3.scale.linear()
.range([height, 0]);
var color = d3.scale.ordinal()
.range(["#d4d4d4", "#58bd5b",]);
var xAxis = d3.svg.axis()
.scale(x0)
.orient("bottom");
var yAxis = d3.svg.axis()
.scale(y)
.orient("left")
.tickFormat(d3.format(".2s"));
var svg = d3.select("div.d3space").append("svg")
.attr("width", width + margin.left + margin.right)
.attr("height", height + margin.top + margin.bottom)
.append("g")
.attr("transform", "translate(" + margin.left + "," + margin.top + ")");
d3.csv("/assets/data/data3.csv", function(error, data) {
var hourBuckets = d3.keys(data[0]).filter(function(key) { return key !== "Client"; });
data.forEach(function(d) {
d.hours = hourBuckets.map(function(name) { return {name: name, value: +d[name]}; });
});
x0.domain(data.map(function(d) { return d.Client; }));
x1.domain(hourBuckets).rangeRoundBands([0, x0.rangeBand()]);
y.domain([0, d3.max(data, function(d) { return d3.max(d.hours, function(d) { return d.value; }); })]);
svg.append("g")
.attr("class", "x axis")
.attr("transform", "translate(0," + height + ")")
.call(xAxis);
svg.append("g")
.attr("class", "y axis")
.call(yAxis)
.append("text")
.attr("transform", "rotate(-90)")
.attr("y", 6)
.attr("dy", ".71em")
.style("text-anchor", "end")
.text("Hours");
var client = svg.selectAll(".client")
.data(data)
.enter().append("g")
.attr("class", "g")
.attr("transform", function(d) { return "translate(" + x0(d.Client) + ",0)"; });
client.selectAll("rect")
.data(function(d) { return d.hours; })
.enter().append("rect")
.attr("width", x1.rangeBand())
.attr("x", function(d) { return x1(d.name); })
.attr("y", function(d) { return y(d.value); })
.attr("height", function(d) { return height - y(d.value); })
.style("fill", function(d) { return color(d.name); });
var legend = svg.selectAll(".legend")
.data(hourBuckets.slice().reverse())
.enter().append("g")
.attr("class", "legend")
.attr("transform", function(d, i) { return "translate(0," + i * 20 + ")"; });
legend.append("rect")
.attr("x", width - 18)
.attr("width", 18)
.attr("height", 18)
.style("fill", color);
legend.append("text")
.attr("x", width - 24)
.attr("y", 9)
.attr("dy", ".35em")
.style("text-anchor", "end")
.text(function(d) { return d; });
});
The csv being accessed is in the following format:
Client,Planned,Actual
ICC,25,50
RNR,50,47.5
MB,10,2.5
This chart renders as desired. The piece I am struggling with is getting this graph to transition to reflect different data when a link is clicked (link has id="fourweeks"). I have tried this onclick function:
window.onload = function() {
var a = document.getElementById("fourweeks");
var b = document.getElementById("eightweeks");
var c = document.getElementById("twelveweeks");
a.onclick = function() {
d3.csv("/assets/data/data1.csv", function(error, data) {
var hourBuckets = d3.keys(data[0]).filter(function(key) { return key !== "Client"; });
data.forEach(function(d) {
d.hours = hourBuckets.map(function(name) { return {name: name, value: +d[name]}; });
});
var client = svg.selectAll(".client")
client.selectAll("rect")
.data(function(d) { return d.hours; })
.transition()
.duration(1000)
.attr("y", function(d) { return y(d.value); })
.attr("height", function(d) { return height - y(d.value); })
});
}
}
...no dice. I can get this to work when creating / transitioning simple one-series bar charts that use list inputs, but not the multi-series csv ones. data2.csv is the exact same file as data1.csv, with the values adjusted slightly.
Thanks for your time reading - any advice?
First svg.selectAll(".client") returns an empty selection, because you gave these elements the class 'g' instead of 'client'.
Secondly you need to update the data of the .client-elements:
var client = svg.selectAll(".client")
.data(data);
btw. you should use selection.classed() instead of selection.attr('class')
We are plotting a multilinear graph using d3.v2.js .
We are using ordinal scale for x-axis and linear scale for y-axis as we have labels(string) to be shown in x-axis
and numbers to be shown in y-axis.
In some cases graph appears to be fine , but in some cases it plots x-axis and y-axis independently and y-axis values are not in sync with x-axis values.
Also plotting starts from 0 instead of first x-axis value.
Any pointers to this issue would be of great help.
Thanks in advance.
Please find the code below.
function plotMOAGraph(data , sigPathways){
var margin = {top: 20, right: 80, bottom: 30, left: 100},
width = 960 - margin.left - margin.right,
height = 400 - margin.top - margin.bottom;
var x = d3.scale.ordinal(
(d3.range(0,sigPathways.length))).rangeBands([0, width]);
var y = d3.scale.linear()
.range([height, 0]);
var color = d3.scale.category10();
var xAxis = d3.svg.axis()
.scale(x)
.orient("bottom");
var yAxis = d3.svg.axis()
.scale(y)
.orient("left");
var line = d3.svg.line()
.interpolate("basis")
.x(function(d) { return x(d.pathway); })
.y(function(d) { return y(d.score); });
var svg = d3.select("#graphDiv").append("svg")
.attr("width", width + margin.left + margin.right)
.attr("height", 450 + margin.top + margin.bottom)
.append("g")
.attr("transform", "translate(" + margin.left + "," + margin.top + ")");
color.domain(d3.keys(data[0]).filter(function(key) { return key !== "pathway"; }));
var entityNames = color.domain().map(function(name) {
return {
name: name,
values: data.map(function(d) {
return {pathway: d.pathway, score: +d[name]};
})
};
});
x.domain(sigPathways);
y.domain([
d3.min(entityNames, function(c) { return d3.min(c.values, function(v) { return v.score; }); }),
d3.max(entityNames, function(c) { return d3.max(c.values, function(v) { return v.score; }); })
]);
svg.append("g")
.attr("class", "x axis")
.attr("transform", "translate(0," + height + ")")
.call(xAxis)
.append("text")
.attr("dy", "9em")
.attr("dx","40em")
.style("text-anchor", "end")
.text("Pathways");
svg.append("g")
.attr("class", "y axis")
.call(yAxis)
.append("text")
.attr("transform", "rotate(-90)")
.attr("y", 6)
.attr("dy", "-4em")
.style("text-anchor", "end")
.text("Pathway Scores");
var tooltip = d3.select("#graphDiv")
.append("div")
.style("visibility", "hidden")
;
var rotateXAxis = function(d) {
var name = d.substr(0, 15);
if(name !== d) {
name = name + " ... ";
}
var el = d3.select(this);
el.text('').attr("transform", "rotate(-45)").attr("text-anchor", "end").on("mouseover", showTooltip).on("mouseout",hideTooltip);
var tspan = el.append('tspan').text(name);
tspan.attr('x', 0).attr('dy', '0');
};
svg.selectAll('g.x.axis g text').each(rotateXAxis);
function showTooltip(d) {
tooltip.text(d).style("position","absolute")
.style("top", (d3.event.pageY)-10+"px")
.style("left", (d3.event.pageX)-300+"px")
.style("visibility", "visible")
.style("font-size", "12px");
}
function hideTooltip() {
tooltip.style("visibility", "hidden");
}
var entityName = svg.selectAll(".entityName")
.data(entityNames)
.enter().append("g")
.attr("class", "entityName");
entityName.append("path")
.attr("class", "line")
.attr("d", function(d) {
return line(d.values); })
.style("stroke", function(d) {return color(d.name); });
entityName.append("text")
.datum(function(d) { return {name: d.name, value: d.values[d.values.length - 1]}; })
.attr("transform", function(d) { return "translate(" + x(d.value.pathway) + "," + y(d.value.score) + ")"; })
.attr("x", 3)
.attr("dy", ".35em")
.text(function(d) { return d.name; });
}