Parallel Coordinates
Getting Started
In this tutorial we will take a simple implementation of parallel coordinates and adapt it to work within SAGE2, this is a continuation from the previous tutorial. This tutorial presumes you already know how to set up a new app, and added the d3min.js library to SAGE2.
About Parallel Coordinates
Parallel Coordinates is a powerful tool to map multiple variables. It assists you to drill down into your data set, notice relationships within your data and gain new insight from your data.It allows you to, creates constraints and interacts with the constraints you have created. For more information on the Data Arena Parallel Coordinates pipeline click here.
Customise your App
Change the name of the para.js file to something more relevant. I will rename the file to para.js then edit the instruction script to reflect this change. In this tutorial, we will change The Title, The Description, The script it links to “main_script” and the “type” .
- Edit para.js to be simplebar.js
- Open the instrucations.js file
- Change edit the name script property to reference your renamed script “para.js”
- Edit title Property “Parallel Coordinates”
- Change the width and height to 1200 by 600
{
"main_script": "para.js",
"icon": "sage2.png",
"width": 1200,
"height": 600,
"animation": true,
"dependencies": [],
"load": {
"mode": 0
},
"title": "Parallel Coordinates",
"version": "1.0.0",
"description": "Parallel Coordinates",
"keywords": [ "clock", "2d", "svg" ],
"author": "Luc Renambot <renambot@uic.edu>",
"license": "SAGE2-Software-License"
}
For a full list of properties have a look at the API.
The Data
Download the cars.csv data and save it to your parallel coordinates folder under /sage2/public/apps/ParallelCoordinates.
Setup
Now we will edit the boilerplate to reference your new app. Edit the myApp
variable to and change it to the name of your app:
var simplebar = SAGE2_App.extend( { //...etc
init: function
this.SAGE2Init(“div”, data);
creates a div
in our SAGE2 application. We want to change this to an object so when we create our SVG container we can append it the object. In standard d3 code, we would append to the body of an HTML document.
d3.select("body").append("svg")
Editing Parallel Coordinates
Copy the parallel coordinates code inside the init:function
and under this.myvalue = 5
. Change d3.select(“body”).append(“svg”)
to d3.select(“object”).append(“svg”)
.
d3.select(“object”)
appends the SVG to object we just created above.
Edit the path for the JSON file
Within SAGE2 it is important to put the full path of your JSON file to find out your full path. Open a terminal and run pwd
(print working directory) in the /parallelcoordinates app folder. Then edit the d3.csv method include the full path for your file. Example:
d3.csv("/Users/127904/sage/sage2/public/uploads/apps/clocktwo_svg/cars.csv", function(error, cars) {
Edit the CSS
This implementation Parallel Coordinates of came with some custom CSS style, to make things easier I added in the needed CSS for it to display as a custom attribute within the D3 code.
CSS Background path
.background path {
fill: none;
stroke: #ddd;
}
D3 Background Path
I added in .attr(“fill”,none”)
and .attr(“stroke”,”#ddd”)
to the background path.
background = svg.append("g")
.attr("class", "background")
.selectAll("path")
.data(cars)
.enter().append("path")
.attr("fill", "none")
.attr("stroke","#ddd")
.attr("d", path);
CSS Foreground path
.foreground path {
fill: none;
stroke: steelblue;
}
CSS Foreground path
I added in .attr(“fill”, “none”)
and .attr(“stroke”,”steelblue”)
to the background path.
foreground = svg.append("g")
.attr("class", "foreground")
.selectAll("path")
.data(cars)
.enter().append("path")
.attr("fill", "none")
.attr("stroke","steelblue")
.attr("d", path);
Now my full init: function looks like this
init: function(data) {
// data: contains initialization parameters, such as `x`, `y`, `width`, `height`, and `date`
this.SAGE2Init("object", data);
this.resizeEvents = "continuous";//see below for other options
// initialize your variables
this.myvalue = 5.0;
var margin = {top: 30, right: 10, bottom: 10, left: 10},
width = 960 - margin.left - margin.right,
height = 500 - margin.top - margin.bottom;
var x = d3.scale.ordinal().rangePoints([0, width], 1),
y = {};
var line = d3.svg.line(),
axis = d3.svg.axis().orient("left"),
background,
foreground;
var svg = d3.select("object").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("/Users/127904/sage/sage2/public/uploads/apps/clocktwo_svg/cars.csv", function(error, cars) {
// Extract the list of dimensions and create a scale for each.
x.domain(dimensions = d3.keys(cars[0]).filter(function(d) {
return d != "name" && (y[d] = d3.scale.linear()
.domain(d3.extent(cars, function(p) { return +p[d]; }))
.range([height, 0]));
}));
// Add grey background lines for context.
background = svg.append("g")
.attr("class", "background")
.selectAll("path")
.data(cars)
.enter().append("path")
.attr("fill", "none")
.attr("stroke","#ddd")
.attr("d", path);
// Add blue foreground lines for focus.
foreground = svg.append("g")
.attr("class", "foreground")
.selectAll("path")
.data(cars)
.enter().append("path")
.attr("fill", "none")
.attr("stroke","steelblue")
.attr("d", path);
// Add a group element for each dimension.
var g = svg.selectAll(".dimension")
.data(dimensions)
.enter().append("g")
.attr("class", "dimension")
.attr("transform", function(d) { return "translate(" + x(d) + ")"; });
// Add an axis and title.
g.append("g")
.attr("class", "axis")
.each(function(d) { d3.select(this).call(axis.scale(y[d])); })
.append("text")
.style("text-anchor", "middle")
.attr("y", -9)
.text(function(d) { return d; });
// Add and store a brush for each axis.
g.append("g")
.attr("class", "brush")
.each(function(d) { d3.select(this).call(y[d].brush = d3.svg.brush().y(y[d]).on("brush", brush)); })
.selectAll("rect")
.attr("x", -8)
.attr("width", 16);
});
// Returns the path for a given data point.
function path(d) {
return line(dimensions.map(function(p) { return [x(p), y[p](d[p])]; }));
}
// Handles a brush event, toggling the display of foreground lines.
function brush() {
var actives = dimensions.filter(function(p) { return !y[p].brush.empty(); }),
extents = actives.map(function(p) { return y[p].brush.extent(); });
foreground.style("display", function(d) {
return actives.every(function(p, i) {
return extents[i][0] <= d[p] && d[p] <= extents[i][1];
}) ? null : "none";
});
}
},
Now save and close para.js
and relaunch the SAGE2.
- Type
exit
into the terminal to stop the stage2 environment from running - Press up on the keyboard to reload the previous command, reenter.
node server.js default-cfg.json
to restart the server - In Chrome navigate to https://localhost:9090/index.html