Mercurial > hg > webaudioevaluationtool
changeset 2135:9691be359d6a
Created mean test/page plots, element histogram plots. Latex and tables included. Can download charts as PNG
author | Nicholas Jillings <nickjillings@users.noreply.github.com> |
---|---|
date | Wed, 24 Feb 2016 13:03:08 +0000 |
parents | a12f1720c321 |
children | a55aa62ff3f9 |
files | analysis/analysis.css analysis/analysis.js analysis/index.html |
diffstat | 3 files changed, 283 insertions(+), 18 deletions(-) [+] |
line wrap: on
line diff
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/analysis/analysis.css Wed Feb 24 13:03:08 2016 +0000 @@ -0,0 +1,10 @@ +div.chart-holder { + border: 1px black solid; + margin: 10px 0px; +} +div.code { + margin: 5px; + padding-left: 15px; + background-color: rgb(200,200,200); + border: 2px dashed black; +} \ No newline at end of file
--- a/analysis/analysis.js Tue Feb 23 19:35:18 2016 +0000 +++ b/analysis/analysis.js Wed Feb 24 13:03:08 2016 +0000 @@ -9,10 +9,78 @@ chartContext = new Chart(); } +function arrayMean(values) { + var mean = 0; + for (var value of values) { + mean += value; + } + mean /= values.length; + return mean; +} + +function percentile(values, n) { + values.sort( function(a,b) {return a - b;} ); + // get ordinal rank + var rank = Math.min(Math.floor(values.length*n/100), values.length-1); + return values[rank]; +} + +function arrayMin(array) { + // Return the minimum value of an array + var min = array[0]; + for (var value of array) { + if (value < min) { + min = value; + } + } + return min; +} + +function arrayMax(array) { + // Return the minimum value of an array + var max = array[0]; + for (var value of array) { + if (value > max) { + max = value; + } + } + return max; +} + +function arrayHistogram(values,steps,min,max) { + if (steps == undefined) { + steps = 0.25; + console.log("Warning: arrayHistogram called without steps size set, default to 0.25"); + } + if (min == undefined) {min = arrayMin(values);} + if (max == undefined) {max = arrayMax(values);} + var histogram = []; + var index = min; + while(index < max) { + histogram.push({ + marker: index, + lt: index, + rt: index+steps, + count: 0 + }); + index += steps; + } + for (var value of values) { + for (var entry of histogram) { + if (value >= entry.lt && value <= entry.rt) { + entry.count++; + break; + } + } + } + return histogram; +} + function Chart() { this.valueData = null; this.commentData = null; this.loadStatus = 0; + this.charts = []; var XMLHttp = new XMLHttpRequest(); XMLHttp.parent = this; @@ -33,7 +101,134 @@ } XMLHttp2.send(); - this.drawMean = function() { + this.chartObject = function(name) { + // Create the charting object + this.name = name; + this.root = document.createElement("div"); + this.root.className = "chart-holder"; + this.root.setAttribute("name",name); + this.chartDOM = document.createElement("div"); + this.tableDOM = document.createElement("div"); + this.latexDOM = document.createElement("div"); + this.downloadDOM = document.createElement("div"); + this.chart = undefined; + this.data = new google.visualization.DataTable(); + this.options = {}; + this.print = document.createElement("button"); + this.handleEvent = function() { + // Only used to handle the chart.event.addListener(this,'ready') callback + this.downloadDOM.innerHTML = '<a href="' + this.chart.getImageURI() + '">Download</a>'; + } + + this.root.appendChild(this.chartDOM); + this.root.appendChild(this.tableDOM); + this.root.appendChild(this.latexDOM); + this.root.appendChild(this.print); + this.print.textContent = "Download"; + this.print.addEventListener("click",this); + this.root.appendChild(this.downloadDOM); + this.buildTable = function() { + var table = document.createElement("table"); + table.border = "1"; + for (var rowIndex=0; rowIndex<this.data.If.length; rowIndex++) { + var row = document.createElement("tr"); + table.appendChild(row); + var rowTitle = document.createElement("td"); + rowTitle.textContent = this.data.If[rowIndex].label; + row.appendChild(rowTitle); + for (var cIndex=0; cIndex<this.data.cc.length; cIndex++) { + var column = document.createElement("td"); + column.textContent = this.data.cc[cIndex][rowIndex].tf; + row.appendChild(column); + } + } + this.tableDOM.appendChild(table); + }; + this.writeLatex = function() { + var root = document.createElement("div"); + root.className = "code"; + var holder = document.createElement("pre"); + // Table start + var start = document.createElement("p"); + start.textContent = "\\" + "begin{tabular}{|l|"; + holder.appendChild(start); + for (var i=0; i<this.data.cc.length; i++) { + start.textContent = start.textContent+"c|"; + } + // Now write the rows: + for (var rIndex=0; rIndex<this.data.If.length; rIndex++) { + var row = document.createElement("p"); + row.textContent = this.data.If[rIndex].label.concat(" & "); + for (var cIndex=0; cIndex<this.data.cc.length; cIndex++) { + row.textContent = row.textContent.concat(this.data.cc[cIndex][rIndex].tf); + if (cIndex < this.data.cc.length-1) { + row.textContent = row.textContent.concat(" & "); + } + } + holder.appendChild(row); + } + // Table end + var end = document.createElement("p"); + end.textContent = "\\" + "end{tabular}"; + holder.appendChild(end); + root.appendChild(holder); + this.latexDOM.appendChild(root); + } + } + + this.clear = function() { + var inject = document.getElementById("test-pages"); + for (var chart of this.charts) { + inject.removeChild(chart.root); + } + this.charts = []; + } + + this.drawTestMean = function() { + // This draws one bargraph per axis with every test element on + if (this.valueData == null) { + console.log("Error - Data not loaded"); + return; + } + var chartList = []; + + // Create the data table + for (var page of this.valueData.pages) { + for (var element of page.elements) { + for (var axis of element.axis) { + // Find the axis + var axisChart = chartList.find(function(element,index,array){ + if (element.name == this) {return true;} else {return false;} + },"mean-test-"+axis.id); + if (axisChart == null) { + axisChart = new this.chartObject("mean-test-"+axis.id); + axisChart.options = { + 'title':'Mean of axis: '+axis.name, + 'width':window.innerWidth*0.9, + 'height':(window.innerWidth*0.9)/1.77 + } + axisChart.data.addColumn('string','id'); + axisChart.data.addColumn('number',axis.name); + chartList.push(axisChart); + document.getElementById("test-pages").appendChild(axisChart.root); + } + var mean = arrayMean(axis.values); + axisChart.data.addRow([element.id,mean]); + } + } + } + + // Build and push charts + for (var chart of chartList) { + chart.chart = new google.visualization.ColumnChart(chart.chartDOM); + chart.chart.draw(chart.data,chart.options); + chart.buildTable(); + chart.writeLatex(); + this.charts.push(chart); + } + } + + this.drawPageMean = function() { // First we must get the value data if (this.valueData == null) { console.log("Error - Data not loaded"); @@ -41,16 +236,16 @@ } // We create one plot per page for (var page of this.valueData.pages) { - // First, create the chart resulting point - var inject = document.createElement("div"); - document.getElementById("test-pages").appendChild(inject); + + // Create the chart resulting point + var chart = new this.chartObject("mean-page-"+page.id); + document.getElementById("test-pages").appendChild(chart.root); // Create the data table - var data = new google.visualization.DataTable(); - data.addColumn('string','id'); + chart.data.addColumn('string','id'); // Get axis labels for (var axis of page.elements[0].axis) { - data.addColumn('number',axis.name); + chart.data.addColumn('number',axis.name); } var rows = []; // Rows is an array of tuples [col1, col2, col3 ... colN]; for (var element of page.elements) { @@ -59,22 +254,68 @@ var mean =0; if (i < element.axis.length) { var axis = element.axis[i]; - for (var value of axis.values) { - mean += value; - } - mean /= axis.values.length; + mean = arrayMean(axis.values); } entry.push(mean); } rows.push(entry); } - data.addRows(rows); - var options = {'title':'Mean of page: '+page.id, - 'width':800, - 'height':700}; + chart.data.addRows(rows); + chart.options = { + 'title':'Mean of page: '+page.id, + 'width':800, + 'height':700 + } // Draw the chart - var chart = new google.visualization.ColumnChart(inject); - chart.draw(data,options); + chart.chart = new google.visualization.ColumnChart(chart.chartDOM); + chart.chart.draw(chart.data,chart.options); + chart.buildTable(); + chart.writeLatex(); + this.charts.push(chart); + } + } + + this.drawElementHistogram = function() { + // First we must get the value data + if (this.valueData == null) { + console.log("Error - Data not loaded"); + return; + } + // We create one plot per element, enjoy... + for (var page of this.valueData.pages) { + for (var element of page.elements) { + // Build the chart object + var chart = new this.chartObject("histogram-element-"+element.id); + document.getElementById("test-pages").appendChild(chart.root); + chart.data.addColumn('string','index'); + var histograms = []; + for (var axis of element.axis) { + chart.data.addColumn('number',axis.name); + histograms.push(arrayHistogram(axis.values,0.125,0.0,1.0)); + } + for (var axis of element.axis) { + for (var i=0; i<histograms[0].length; i++) + { + var entry = [""+histograms[0][i].lt.toPrecision(2)+"-"+histograms[0][i].rt.toPrecision(3)] + for (var histogram of histograms) { + entry.push(histogram[i].count); + } + chart.data.addRow(entry); + } + } + chart.options = { + 'title':'Histogram of element: '+element.id, + 'width':800, + 'height':700, + 'bar':{'groupWidth': '100%'} + } + // Draw the chart + chart.chart = new google.visualization.ColumnChart(chart.chartDOM); + chart.chart.draw(chart.data,chart.options); + chart.buildTable(); + chart.writeLatex(); + this.charts.push(chart); + } } } } \ No newline at end of file
--- a/analysis/index.html Tue Feb 23 19:35:18 2016 +0000 +++ b/analysis/index.html Wed Feb 24 13:03:08 2016 +0000 @@ -1,12 +1,26 @@ <html lang="en"> <head> <meta charset="utf-8" /> + <link rel='stylesheet' href="analysis.css" type="text/css"/> <script type="text/javascript" src="https://www.gstatic.com/charts/loader.js"></script> <script type="text/javascript" src="analysis.js"></script> </head> <body> <h1>Web Audio Evaluation Toolbox: Analysis</h1> - <button onclick="chartContext.drawMean();">Means</button> + <button onclick="chartContext.clear();">Clear Charts</button> + <div id="test-charts"> + <p>Charts per test</p> + <button onclick="chartContext.drawTestMean();">Means</button> + </div> + <div id="page-charts"> + <p>Charts per test page</p> + <button onclick="chartContext.drawPageMean();">Means</button> + </div> + <div id="element-charts"> + <p>Charts per element</p> + <button onclick="chartContext.drawElementHistogram();">Histogram</button> + </div> + <div id="test-pages"></div> </body> </html> \ No newline at end of file