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.
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 12oo 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 para = SAGE2_App.extend( {
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 thee terminal and enter pwd 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
https://bl.ocks.org/mbostock/1341021 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