n@566: /* n@566: * Analysis script for WAET n@566: */ n@566: n@650: // Firefox does not have an XMLDocument.prototype.getElementsByName n@650: // and there is no searchAll style command, this custom function will n@650: // search all children recusrively for the name. Used for XSD where all n@650: // element nodes must have a name and therefore can pull the schema node n@650: XMLDocument.prototype.getAllElementsByName = function(name) n@650: { n@650: name = String(name); n@650: var selected = this.documentElement.getAllElementsByName(name); n@650: return selected; n@650: } n@650: n@650: Element.prototype.getAllElementsByName = function(name) n@650: { n@650: name = String(name); n@650: var selected = []; n@650: var node = this.firstElementChild; n@650: while(node != null) n@650: { n@650: if (node.getAttribute('name') == name) n@650: { n@650: selected.push(node); n@650: } n@650: if (node.childElementCount > 0) n@650: { n@650: selected = selected.concat(node.getAllElementsByName(name)); n@650: } n@650: node = node.nextElementSibling; n@650: } n@650: return selected; n@650: } n@650: n@650: XMLDocument.prototype.getAllElementsByTagName = function(name) n@650: { n@650: name = String(name); n@650: var selected = this.documentElement.getAllElementsByTagName(name); n@650: return selected; n@650: } n@650: n@650: Element.prototype.getAllElementsByTagName = function(name) n@650: { n@650: name = String(name); n@650: var selected = []; n@650: var node = this.firstElementChild; n@650: while(node != null) n@650: { n@650: if (node.nodeName == name) n@650: { n@650: selected.push(node); n@650: } n@650: if (node.childElementCount > 0) n@650: { n@650: selected = selected.concat(node.getAllElementsByTagName(name)); n@650: } n@650: node = node.nextElementSibling; n@650: } n@650: return selected; n@650: } n@650: n@650: // Firefox does not have an XMLDocument.prototype.getElementsByName n@650: if (typeof XMLDocument.prototype.getElementsByName != "function") { n@650: XMLDocument.prototype.getElementsByName = function(name) n@650: { n@650: name = String(name); n@650: var node = this.documentElement.firstElementChild; n@650: var selected = []; n@650: while(node != null) n@650: { n@650: if (node.getAttribute('name') == name) n@650: { n@650: selected.push(node); n@650: } n@650: node = node.nextElementSibling; n@650: } n@650: return selected; n@650: } n@650: } n@650: n@650: var chartContext, testData; n@566: window.onload = function() { n@566: // Load the Visualization API and the corechart package. n@650: google.charts.load('current', {'packages':['corechart']}); n@566: chartContext = new Chart(); n@650: testData = new Data(); n@650: } n@650: n@650: function get(url) { n@650: // Return a new promise. n@650: return new Promise(function(resolve, reject) { n@650: // Do the usual XHR stuff n@650: var req = new XMLHttpRequest(); n@650: req.open('GET', url); n@650: req.onload = function() { n@650: // This is called even on 404 etc n@650: // so check the status n@650: if (req.status == 200) { n@650: // Resolve the promise with the response text n@650: resolve(req.response); n@650: } n@650: else { n@650: // Otherwise reject with the status text n@650: // which will hopefully be a meaningful error n@650: reject(Error(req.statusText)); n@650: } n@650: }; n@650: n@650: // Handle network errors n@650: req.onerror = function() { n@650: reject(Error("Network Error")); n@650: }; n@650: n@650: // Make the request n@650: req.send(); n@650: }); n@566: } n@566: n@571: function arrayMean(values) { n@571: var mean = 0; n@571: for (var value of values) { n@571: mean += value; n@571: } n@571: mean /= values.length; n@571: return mean; n@571: } n@571: n@641: function percentile(values, p) { n@641: //http://web.stanford.edu/class/archive/anthsci/anthsci192/anthsci192.1064/handouts/calculating%20percentiles.pdf n@571: values.sort( function(a,b) {return a - b;} ); n@571: // get ordinal rank n@641: var index = values.length*p/100; n@641: var k = Math.floor(index); n@641: if (k == index) { n@641: return values[k]; n@641: } else { n@641: var f = index-k; n@641: var x_int = (1-f)*values[k]+f*values[k+1]; n@641: return x_int; n@641: } n@571: } n@571: n@571: function arrayMin(array) { n@571: // Return the minimum value of an array n@571: var min = array[0]; n@571: for (var value of array) { n@571: if (value < min) { n@571: min = value; n@571: } n@571: } n@571: return min; n@571: } n@571: n@571: function arrayMax(array) { n@571: // Return the minimum value of an array n@571: var max = array[0]; n@571: for (var value of array) { n@571: if (value > max) { n@571: max = value; n@571: } n@571: } n@571: return max; n@571: } n@571: n@639: function boxplotRow(array) { n@639: // Take an array of element values and return array of computed intervals n@639: var result = { n@641: median : arrayMean(array), n@639: pct25 : percentile(array,25), n@639: pct75 : percentile(array,75), n@639: IQR : null, n@639: min: null, n@639: max: null, n@639: outliers: new Array() n@639: } n@639: result.IQR = result.pct75-result.pct25; n@639: var rest = []; n@639: var pct75_IQR = result.pct75+1.5*result.IQR; n@639: var pct25_IQR = result.pct25-1.5*result.IQR; n@639: for (var i=0; i pct75_IQR || point < pct25_IQR) { n@639: result.outliers.push(point); n@639: } else { n@639: rest.push(point); n@639: } n@639: } n@639: result.max = arrayMax(rest); n@639: result.min = arrayMin(rest); n@639: return result; n@639: n@639: } n@639: n@571: function arrayHistogram(values,steps,min,max) { n@571: if (steps == undefined) { n@571: steps = 0.25; n@571: console.log("Warning: arrayHistogram called without steps size set, default to 0.25"); n@571: } n@571: if (min == undefined) {min = arrayMin(values);} n@571: if (max == undefined) {max = arrayMax(values);} n@571: var histogram = []; n@571: var index = min; n@571: while(index < max) { n@571: histogram.push({ n@571: marker: index, n@571: lt: index, n@571: rt: index+steps, n@571: count: 0 n@571: }); n@571: index += steps; n@571: } n@571: for (var value of values) { n@571: for (var entry of histogram) { n@571: if (value >= entry.lt && value <= entry.rt) { n@571: entry.count++; n@571: break; n@571: } n@571: } n@571: } n@571: return histogram; n@571: } n@571: n@566: function Chart() { n@650: this.valueData; n@571: this.charts = []; n@566: n@571: this.chartObject = function(name) { n@571: // Create the charting object n@571: this.name = name; n@571: this.root = document.createElement("div"); n@571: this.root.className = "chart-holder"; n@571: this.root.setAttribute("name",name); n@571: this.chartDOM = document.createElement("div"); n@571: this.tableDOM = document.createElement("div"); n@571: this.latexDOM = document.createElement("div"); n@571: this.downloadDOM = document.createElement("div"); n@571: this.chart = undefined; n@571: this.data = new google.visualization.DataTable(); n@571: this.options = {}; n@571: this.print = document.createElement("button"); n@572: this.sortDataButton = document.createElement("button"); n@572: this.sortDataButton.textContent = "Sort by Data"; n@572: this.sortDataButton.addEventListener("click",this); n@572: this.sortDataButton.setAttribute("name","sort-data"); n@572: this.sortNameButton = document.createElement("button"); n@572: this.sortNameButton.textContent = "Sort by Name"; n@572: this.sortNameButton.addEventListener("click",this); n@572: this.sortNameButton.setAttribute("name","sort-name"); n@572: this.draw = function() { n@572: if (this.chart == undefined) {return;} n@572: this.tableDOM.innerHTML = null; n@572: this.latexDOM.innerHTML = null; n@572: this.buildTable(); n@572: this.writeLatex(); n@572: this.chart.draw(this.data,this.options); n@572: } n@572: this.sortData = function() { n@631: this.data.sort(1); n@572: } n@572: this.sortName = function() { n@631: this.data.sort(0); n@572: } n@571: this.handleEvent = function() { n@571: // Only used to handle the chart.event.addListener(this,'ready') callback n@572: switch(event.currentTarget.getAttribute("name")) n@572: { n@572: case "download": n@572: window.open(this.chart.getImageURI()); n@572: break; n@572: case "sort-data": n@572: this.sortData(); n@572: this.draw(); n@572: break; n@572: case "sort-name": n@572: this.sortName(); n@572: this.draw(); n@572: break; n@572: } n@571: } n@571: n@571: this.root.appendChild(this.chartDOM); n@571: this.root.appendChild(this.tableDOM); n@571: this.root.appendChild(this.latexDOM); n@572: this.root.appendChild(this.sortDataButton); n@572: this.root.appendChild(this.sortNameButton); n@571: this.root.appendChild(this.print); n@571: this.print.textContent = "Download"; n@572: this.print.setAttribute("name","download"); n@571: this.print.addEventListener("click",this); n@571: this.root.appendChild(this.downloadDOM); n@571: this.buildTable = function() { n@571: var table = document.createElement("table"); n@571: table.border = "1"; n@630: var numRows = this.data.getNumberOfRows(); n@630: var numColumns = this.data.getNumberOfColumns(); n@630: for (var columnIndex=0; columnIndex"; n@650: this.rootDOM.className = "filter-entry"; n@650: this.handleEvent = function(event) { n@650: switch(this.specification.type) { n@650: case "number": n@650: var name = event.currentTarget.name; n@650: eval("this."+name+" = event.currentTarget.value"); n@650: break; n@650: case "checkbox": n@650: break; n@650: case "radio": n@650: break; n@650: } n@650: this.parent.getFileCount(); n@650: } n@650: this.getFilterPairs = function() { n@650: var pairs = []; n@650: switch(this.specification.type) { n@650: case "number": n@650: if (this.min != "") { n@650: pairs.push([specification.id+"-min",this.min]); n@650: } n@650: if (this.max != "") { n@650: pairs.push([specification.id+"-max",this.max]); n@650: } n@650: break; n@650: case "radio": n@650: case "checkbox": n@650: for (var i=0; i