annotate analysis/analysis.js @ 1265:5946b03fffe5

Analysis.js sort uses Google's DataTable sort functions.
author Nicholas Jillings <n.g.r.jillings@se14.qmul.ac.uk>
date Mon, 21 Mar 2016 16:22:49 +0000
parents 055d020099ea
children 227ca4d00ab1
rev   line source
n@1223 1 /*
n@1223 2 * Analysis script for WAET
n@1223 3 */
n@1223 4
n@1223 5 var chartContext;
n@1223 6 window.onload = function() {
n@1223 7 // Load the Visualization API and the corechart package.
n@1223 8 google.charts.load('current', {'packages':['corechart']});
n@1223 9 chartContext = new Chart();
n@1223 10 }
n@1223 11
n@1227 12 function arrayMean(values) {
n@1227 13 var mean = 0;
n@1227 14 for (var value of values) {
n@1227 15 mean += value;
n@1227 16 }
n@1227 17 mean /= values.length;
n@1227 18 return mean;
n@1227 19 }
n@1227 20
n@1227 21 function percentile(values, n) {
n@1227 22 values.sort( function(a,b) {return a - b;} );
n@1227 23 // get ordinal rank
n@1227 24 var rank = Math.min(Math.floor(values.length*n/100), values.length-1);
n@1227 25 return values[rank];
n@1227 26 }
n@1227 27
n@1227 28 function arrayMin(array) {
n@1227 29 // Return the minimum value of an array
n@1227 30 var min = array[0];
n@1227 31 for (var value of array) {
n@1227 32 if (value < min) {
n@1227 33 min = value;
n@1227 34 }
n@1227 35 }
n@1227 36 return min;
n@1227 37 }
n@1227 38
n@1227 39 function arrayMax(array) {
n@1227 40 // Return the minimum value of an array
n@1227 41 var max = array[0];
n@1227 42 for (var value of array) {
n@1227 43 if (value > max) {
n@1227 44 max = value;
n@1227 45 }
n@1227 46 }
n@1227 47 return max;
n@1227 48 }
n@1227 49
n@1227 50 function arrayHistogram(values,steps,min,max) {
n@1227 51 if (steps == undefined) {
n@1227 52 steps = 0.25;
n@1227 53 console.log("Warning: arrayHistogram called without steps size set, default to 0.25");
n@1227 54 }
n@1227 55 if (min == undefined) {min = arrayMin(values);}
n@1227 56 if (max == undefined) {max = arrayMax(values);}
n@1227 57 var histogram = [];
n@1227 58 var index = min;
n@1227 59 while(index < max) {
n@1227 60 histogram.push({
n@1227 61 marker: index,
n@1227 62 lt: index,
n@1227 63 rt: index+steps,
n@1227 64 count: 0
n@1227 65 });
n@1227 66 index += steps;
n@1227 67 }
n@1227 68 for (var value of values) {
n@1227 69 for (var entry of histogram) {
n@1227 70 if (value >= entry.lt && value <= entry.rt) {
n@1227 71 entry.count++;
n@1227 72 break;
n@1227 73 }
n@1227 74 }
n@1227 75 }
n@1227 76 return histogram;
n@1227 77 }
n@1227 78
n@1223 79 function Chart() {
n@1226 80 this.valueData = null;
n@1226 81 this.commentData = null;
n@1226 82 this.loadStatus = 0;
n@1227 83 this.charts = [];
n@1223 84
n@1226 85 var XMLHttp = new XMLHttpRequest();
n@1226 86 XMLHttp.parent = this;
n@1226 87 XMLHttp.open("GET","../scripts/score_parser.php?format=JSON",true);
n@1226 88 XMLHttp.onload = function() {
n@1226 89 // Now we have the JSON data, extract
n@1226 90 this.parent.valueData = JSON.parse(this.responseText);
n@1226 91 this.parent.loadStatus++;
n@1223 92 }
n@1226 93 XMLHttp.send();
n@1226 94 var XMLHttp2 = new XMLHttpRequest();
n@1226 95 XMLHttp2.parent = this;
n@1226 96 XMLHttp2.open("GET","../scripts/comment_parser.php?format=JSON",true);
n@1226 97 XMLHttp2.onload = function() {
n@1226 98 // Now we have the JSON data, extract
n@1226 99 this.parent.commentData = JSON.parse(this.responseText);
n@1226 100 this.parent.loadStatus++;
n@1226 101 }
n@1226 102 XMLHttp2.send();
n@1223 103
n@1227 104 this.chartObject = function(name) {
n@1227 105 // Create the charting object
n@1227 106 this.name = name;
n@1227 107 this.root = document.createElement("div");
n@1227 108 this.root.className = "chart-holder";
n@1227 109 this.root.setAttribute("name",name);
n@1227 110 this.chartDOM = document.createElement("div");
n@1227 111 this.tableDOM = document.createElement("div");
n@1227 112 this.latexDOM = document.createElement("div");
n@1227 113 this.downloadDOM = document.createElement("div");
n@1227 114 this.chart = undefined;
n@1227 115 this.data = new google.visualization.DataTable();
n@1227 116 this.options = {};
n@1227 117 this.print = document.createElement("button");
n@1228 118 this.sortDataButton = document.createElement("button");
n@1228 119 this.sortDataButton.textContent = "Sort by Data";
n@1228 120 this.sortDataButton.addEventListener("click",this);
n@1228 121 this.sortDataButton.setAttribute("name","sort-data");
n@1228 122 this.sortNameButton = document.createElement("button");
n@1228 123 this.sortNameButton.textContent = "Sort by Name";
n@1228 124 this.sortNameButton.addEventListener("click",this);
n@1228 125 this.sortNameButton.setAttribute("name","sort-name");
n@1228 126 this.draw = function() {
n@1228 127 if (this.chart == undefined) {return;}
n@1228 128 this.tableDOM.innerHTML = null;
n@1228 129 this.latexDOM.innerHTML = null;
n@1228 130 this.buildTable();
n@1228 131 this.writeLatex();
n@1228 132 this.chart.draw(this.data,this.options);
n@1228 133 }
n@1228 134 this.sortData = function() {
n@1265 135 this.data.sort(1);
n@1228 136 }
n@1228 137 this.sortName = function() {
n@1265 138 this.data.sort(0);
n@1228 139 }
n@1227 140 this.handleEvent = function() {
n@1227 141 // Only used to handle the chart.event.addListener(this,'ready') callback
n@1228 142 switch(event.currentTarget.getAttribute("name"))
n@1228 143 {
n@1228 144 case "download":
n@1228 145 window.open(this.chart.getImageURI());
n@1228 146 break;
n@1228 147 case "sort-data":
n@1228 148 this.sortData();
n@1228 149 this.draw();
n@1228 150 break;
n@1228 151 case "sort-name":
n@1228 152 this.sortName();
n@1228 153 this.draw();
n@1228 154 break;
n@1228 155 }
n@1227 156 }
n@1227 157
n@1227 158 this.root.appendChild(this.chartDOM);
n@1227 159 this.root.appendChild(this.tableDOM);
n@1227 160 this.root.appendChild(this.latexDOM);
n@1228 161 this.root.appendChild(this.sortDataButton);
n@1228 162 this.root.appendChild(this.sortNameButton);
n@1227 163 this.root.appendChild(this.print);
n@1227 164 this.print.textContent = "Download";
n@1228 165 this.print.setAttribute("name","download");
n@1227 166 this.print.addEventListener("click",this);
n@1227 167 this.root.appendChild(this.downloadDOM);
n@1227 168 this.buildTable = function() {
n@1227 169 var table = document.createElement("table");
n@1227 170 table.border = "1";
n@1264 171 var numRows = this.data.getNumberOfRows();
n@1264 172 var numColumns = this.data.getNumberOfColumns();
n@1264 173 for (var columnIndex=0; columnIndex<numColumns; columnIndex++)
n@1264 174 {
n@1264 175 var table_row = document.createElement('tr');
n@1264 176 table.appendChild(table_row);
n@1264 177 var row_title = document.createElement('td');
n@1264 178 table_row.appendChild(row_title);
n@1264 179 row_title.textContent = this.data.getColumnLabel(columnIndex);
n@1264 180 for (var rowIndex=0; rowIndex<numRows; rowIndex++)
n@1264 181 {
n@1264 182 var row_entry = document.createElement('td');
n@1264 183 table_row.appendChild(row_entry);
n@1264 184 var entry = this.data.getValue(rowIndex,columnIndex);
n@1264 185 if (isFinite(Number(entry)))
n@1264 186 {
n@1264 187 entry = String(Number(entry).toFixed(4));
n@1264 188 }
n@1264 189 row_entry.textContent = entry;
n@1227 190 }
n@1227 191 }
n@1227 192 this.tableDOM.appendChild(table);
n@1227 193 };
n@1227 194 this.writeLatex = function() {
n@1264 195 var numRows = this.data.getNumberOfRows();
n@1264 196 var numColumns = this.data.getNumberOfColumns();
n@1227 197 var root = document.createElement("div");
n@1227 198 root.className = "code";
n@1227 199 var holder = document.createElement("pre");
n@1227 200 // Table start
n@1227 201 var start = document.createElement("p");
n@1227 202 start.textContent = "\\" + "begin{tabular}{|l|";
n@1227 203 holder.appendChild(start);
n@1264 204 for (var i=0; i<numRows; i++) {
n@1227 205 start.textContent = start.textContent+"c|";
n@1227 206 }
n@1228 207 start.textContent = start.textContent.concat("}");
n@1227 208 // Now write the rows:
n@1264 209 for (var rIndex=0; rIndex<numColumns; rIndex++) {
n@1227 210 var row = document.createElement("p");
n@1264 211 row.textContent = this.data.getColumnLabel(rIndex).concat(" & ");
n@1264 212 for (var cIndex=0; cIndex<numRows; cIndex++) {
n@1264 213 var entry = this.data.getValue(cIndex,rIndex);
n@1264 214 if (isFinite(Number(entry)))
n@1264 215 {
n@1264 216 entry = String(Number(entry).toFixed(4));
n@1264 217 }
n@1264 218 row.textContent = row.textContent.concat(entry);
n@1264 219 if (cIndex < numRows-1) {
n@1227 220 row.textContent = row.textContent.concat(" & ");
n@1227 221 }
n@1227 222 }
n@1227 223 holder.appendChild(row);
n@1227 224 }
n@1227 225 // Table end
n@1227 226 var end = document.createElement("p");
n@1227 227 end.textContent = "\\" + "end{tabular}";
n@1227 228 holder.appendChild(end);
n@1227 229 root.appendChild(holder);
n@1227 230 this.latexDOM.appendChild(root);
n@1227 231 }
n@1227 232 }
n@1227 233
n@1227 234 this.clear = function() {
n@1227 235 var inject = document.getElementById("test-pages");
n@1227 236 for (var chart of this.charts) {
n@1227 237 inject.removeChild(chart.root);
n@1227 238 }
n@1227 239 this.charts = [];
n@1227 240 }
n@1227 241
n@1227 242 this.drawTestMean = function() {
n@1227 243 // This draws one bargraph per axis with every test element on
n@1227 244 if (this.valueData == null) {
n@1227 245 console.log("Error - Data not loaded");
n@1227 246 return;
n@1227 247 }
n@1227 248 var chartList = [];
n@1227 249
n@1227 250 // Create the data table
n@1227 251 for (var page of this.valueData.pages) {
n@1227 252 for (var element of page.elements) {
n@1227 253 for (var axis of element.axis) {
n@1227 254 // Find the axis
n@1227 255 var axisChart = chartList.find(function(element,index,array){
n@1227 256 if (element.name == this) {return true;} else {return false;}
n@1227 257 },"mean-test-"+axis.id);
n@1227 258 if (axisChart == null) {
n@1227 259 axisChart = new this.chartObject("mean-test-"+axis.id);
n@1227 260 axisChart.options = {
n@1227 261 'title':'Mean of axis: '+axis.name,
n@1227 262 'width':window.innerWidth*0.9,
n@1227 263 'height':(window.innerWidth*0.9)/1.77
n@1227 264 }
n@1227 265 axisChart.data.addColumn('string','id');
n@1227 266 axisChart.data.addColumn('number',axis.name);
n@1227 267 chartList.push(axisChart);
n@1227 268 document.getElementById("test-pages").appendChild(axisChart.root);
n@1227 269 }
n@1227 270 var mean = arrayMean(axis.values);
n@1227 271 axisChart.data.addRow([element.id,mean]);
n@1227 272 }
n@1227 273 }
n@1227 274 }
n@1227 275
n@1227 276 // Build and push charts
n@1227 277 for (var chart of chartList) {
n@1227 278 chart.chart = new google.visualization.ColumnChart(chart.chartDOM);
n@1227 279 chart.chart.draw(chart.data,chart.options);
n@1227 280 chart.buildTable();
n@1227 281 chart.writeLatex();
n@1227 282 this.charts.push(chart);
n@1227 283 }
n@1227 284 }
n@1227 285
n@1227 286 this.drawPageMean = function() {
n@1223 287 // First we must get the value data
n@1226 288 if (this.valueData == null) {
n@1226 289 console.log("Error - Data not loaded");
n@1226 290 return;
n@1226 291 }
n@1226 292 // We create one plot per page
n@1226 293 for (var page of this.valueData.pages) {
n@1227 294
n@1227 295 // Create the chart resulting point
n@1227 296 var chart = new this.chartObject("mean-page-"+page.id);
n@1227 297 document.getElementById("test-pages").appendChild(chart.root);
n@1226 298
n@1226 299 // Create the data table
n@1227 300 chart.data.addColumn('string','id');
n@1226 301 // Get axis labels
n@1226 302 for (var axis of page.elements[0].axis) {
n@1227 303 chart.data.addColumn('number',axis.name);
n@1226 304 }
n@1226 305 var rows = []; // Rows is an array of tuples [col1, col2, col3 ... colN];
n@1226 306 for (var element of page.elements) {
n@1226 307 var entry = [element.id];
n@1226 308 for (var i=0; i<page.elements[0].axis.length; i++) {
n@1226 309 var mean =0;
n@1226 310 if (i < element.axis.length) {
n@1226 311 var axis = element.axis[i];
n@1227 312 mean = arrayMean(axis.values);
n@1226 313 }
n@1226 314 entry.push(mean);
n@1226 315 }
n@1226 316 rows.push(entry);
n@1226 317 }
n@1227 318 chart.data.addRows(rows);
n@1227 319 chart.options = {
n@1227 320 'title':'Mean of page: '+page.id,
n@1227 321 'width':800,
n@1227 322 'height':700
n@1227 323 }
n@1226 324 // Draw the chart
n@1227 325 chart.chart = new google.visualization.ColumnChart(chart.chartDOM);
n@1227 326 chart.chart.draw(chart.data,chart.options);
n@1227 327 chart.buildTable();
n@1227 328 chart.writeLatex();
n@1227 329 this.charts.push(chart);
n@1227 330 }
n@1227 331 }
n@1227 332
n@1227 333 this.drawElementHistogram = function() {
n@1227 334 // First we must get the value data
n@1227 335 if (this.valueData == null) {
n@1227 336 console.log("Error - Data not loaded");
n@1227 337 return;
n@1227 338 }
n@1227 339 // We create one plot per element, enjoy...
n@1227 340 for (var page of this.valueData.pages) {
n@1227 341 for (var element of page.elements) {
n@1227 342 // Build the chart object
n@1227 343 var chart = new this.chartObject("histogram-element-"+element.id);
n@1227 344 document.getElementById("test-pages").appendChild(chart.root);
n@1227 345 chart.data.addColumn('string','index');
n@1227 346 var histograms = [];
n@1227 347 for (var axis of element.axis) {
n@1227 348 chart.data.addColumn('number',axis.name);
n@1227 349 histograms.push(arrayHistogram(axis.values,0.125,0.0,1.0));
n@1227 350 }
n@1227 351 for (var axis of element.axis) {
n@1227 352 for (var i=0; i<histograms[0].length; i++)
n@1227 353 {
n@1227 354 var entry = [""+histograms[0][i].lt.toPrecision(2)+"-"+histograms[0][i].rt.toPrecision(3)]
n@1227 355 for (var histogram of histograms) {
n@1227 356 entry.push(histogram[i].count);
n@1227 357 }
n@1227 358 chart.data.addRow(entry);
n@1227 359 }
n@1227 360 }
n@1227 361 chart.options = {
n@1227 362 'title':'Histogram of element: '+element.id,
n@1227 363 'width':800,
n@1227 364 'height':700,
n@1227 365 'bar':{'groupWidth': '100%'}
n@1227 366 }
n@1227 367 // Draw the chart
n@1227 368 chart.chart = new google.visualization.ColumnChart(chart.chartDOM);
n@1227 369 chart.chart.draw(chart.data,chart.options);
n@1227 370 chart.buildTable();
n@1227 371 chart.writeLatex();
n@1227 372 this.charts.push(chart);
n@1227 373 }
n@1226 374 }
n@1223 375 }
n@1223 376 }