annotate analyse.html @ 743:ce513811a06d

Added screen shots, edited bib. Some edits to intro, abstract and conclusion.
author Nicholas Jillings <nicholas.jillings@eecs.qmul.ac.uk>
date Thu, 15 Oct 2015 21:17:14 +0100
parents 9da8a3e65a78
children c64529e5dee4
rev   line source
BrechtDeMan@716 1 <!DOCTYPE html>
BrechtDeMan@716 2 <html lang="en">
BrechtDeMan@716 3 <head>
BrechtDeMan@716 4 <meta charset="utf-8">
BrechtDeMan@716 5
BrechtDeMan@716 6 <!-- Always force latest IE rendering engine (even in intranet) & Chrome Frame
BrechtDeMan@716 7 Remove this if you use the .htaccess -->
BrechtDeMan@716 8 <meta http-equiv="X-UA-Compatible" content="IE=edge,chrome=1">
BrechtDeMan@716 9
BrechtDeMan@716 10 <title>Analysis</title>
BrechtDeMan@716 11 <meta name="description" content="Show results from subjective evaluation">
BrechtDeMan@716 12 <meta name="author" content="Brecht De Man">
BrechtDeMan@716 13
BrechtDeMan@716 14 <script type="text/javascript" src="https://www.google.com/jsapi"></script>
BrechtDeMan@716 15 <script type="text/javascript">
BrechtDeMan@716 16 // To aid 'one-page set-up' all scripts and CSS must be included directly in this file!
BrechtDeMan@716 17
BrechtDeMan@716 18 google.load("visualization", "1", {packages:["corechart"]});
BrechtDeMan@716 19
BrechtDeMan@716 20 /*************
BrechtDeMan@715 21 * SETUP *
BrechtDeMan@716 22 *************/
BrechtDeMan@716 23 // folder where to find the XML files
BrechtDeMan@715 24 xmlFileFolder = "analysis_test";
BrechtDeMan@716 25 // array of XML files
BrechtDeMan@715 26 var xmlFiles = ['QM-1-1.xml','QM-2-1.xml','QM-2-2.xml','QM-2-3.xml','QM-3-1.xml','QM-3-2.xml','QM-4-1.xml','QM-5-1.xml','QM-5-2.xml','QM-6-1.xml','QM-6-2.xml','QM-7-1.xml','QM-7-2.xml','QM-8-1.xml','QM-9-1.xml','QM-10-1.xml','QM-11-1.xml','QM-12-1.xml','QM-12-2.xml','QM-13-1.xml','QM-14-1.xml','QM-15-1.xml','QM-16-1.xml','QM-17-1.xml','QM-18-1.xml','QM-18-2.xml','QM-18-3.xml','QM-19-1.xml','QM-20-1.xml','QM-20-2.xml','QM-20-3.xml','QM-21-1.xml','QM-21-2.xml'];
BrechtDeMan@715 27 //['McG-A-2014-03.xml','McG-B-2014-03.xml','McG-C-2014-03.xml','McG-D-2014-03.xml','McG-E-2014-03.xml','McG-F-2014-03.xml','McG-G-2014-03.xml','McG-H-2014-03.xml'];
BrechtDeMan@716 28
BrechtDeMan@716 29 //TODO: make retrieval of file names automatic / drag files on here
BrechtDeMan@716 30
BrechtDeMan@716 31 /****************
BrechtDeMan@715 32 * VARIABLES *
BrechtDeMan@716 33 ****************/
BrechtDeMan@716 34
BrechtDeMan@716 35 // Counters
BrechtDeMan@715 36 // How many files, audioholders, audioelementes and statements annotated (don't count current one)
BrechtDeMan@716 37 var numberOfFiles = -1;
BrechtDeMan@715 38 var numberOfaudioholders = -1;
BrechtDeMan@715 39 var numberOfaudioelementes = -1;
BrechtDeMan@716 40 var numberOfStatements = -1;
BrechtDeMan@716 41 var numberOfSkippedComments = 0;
BrechtDeMan@716 42
BrechtDeMan@716 43 // Object arrays
BrechtDeMan@716 44 var fileNameArray = [];
BrechtDeMan@716 45 var subjectArray = [];
BrechtDeMan@715 46 var audioholderArray = [];
BrechtDeMan@715 47 var audioelementArray = [];
BrechtDeMan@716 48
BrechtDeMan@716 49 // End of (file, audioholder, audioelement) flags
BrechtDeMan@716 50 var newFile = true;
BrechtDeMan@716 51 var newAudioHolder = true;
BrechtDeMan@716 52 var newAudioElement = true;
BrechtDeMan@716 53
BrechtDeMan@716 54 var fileCounter = 0; // file index
BrechtDeMan@715 55 var audioholderCounter=0; // audioholder index (current XML file)
BrechtDeMan@715 56 var audioelementCounter=0; // audioelement index (current audioholder)
BrechtDeMan@716 57 var statementNumber=0; // total number of statements
BrechtDeMan@716 58
BrechtDeMan@716 59 var root; // root of XML file
BrechtDeMan@716 60 var commentInFull = ''; // full comment
BrechtDeMan@716 61
BrechtDeMan@716 62 var playAudio = true; // whether corresponding audio should be played back
BrechtDeMan@716 63
BrechtDeMan@716 64 // // Measuring time
BrechtDeMan@716 65 // var lastTimeMeasured = -1; //
BrechtDeMan@716 66 // var durationLastAnnotation = -1; // duration of last annotation
BrechtDeMan@716 67 // var timeArray = [];
BrechtDeMan@716 68 // var MIN_TIME = 1.0; // minimum time counted as significant
BrechtDeMan@716 69 // var measurementPaused = false; // whether time measurement is paused
BrechtDeMan@716 70 // var timeInBuffer = 0; //
BrechtDeMan@716 71
BrechtDeMan@716 72 var topLevel;
BrechtDeMan@716 73 window.onload = function() {
BrechtDeMan@716 74 // Initialise page
BrechtDeMan@716 75 topLevel = document.getElementById('topLevelBody');
BrechtDeMan@716 76 var setup = document.createElement('div');
BrechtDeMan@716 77 setup.id = 'setupTagDiv';
BrechtDeMan@716 78 loadAllFiles();
BrechtDeMan@716 79
BrechtDeMan@716 80 makePlots();
BrechtDeMan@716 81 // measure time at this point:
BrechtDeMan@716 82 lastTimeMeasured = new Date().getTime(); // in milliseconds
BrechtDeMan@716 83 };
BrechtDeMan@716 84
BrechtDeMan@716 85 // Assert function
BrechtDeMan@716 86 function assert(condition, message) {
BrechtDeMan@716 87 if (!condition) {
BrechtDeMan@716 88 message = message || "Assertion failed";
BrechtDeMan@716 89 if (typeof Error !== "undefined") {
BrechtDeMan@716 90 throw new Error(message);
BrechtDeMan@716 91 }
BrechtDeMan@716 92 throw message; // Fallback
BrechtDeMan@716 93 }
BrechtDeMan@716 94 }
BrechtDeMan@716 95
BrechtDeMan@715 96 function median(values) { // TODO: replace code by '50th percentile' - should be the same?
BrechtDeMan@716 97 values.sort( function(a,b) {return a - b;} );
BrechtDeMan@716 98 var half = Math.floor(values.length/2);
BrechtDeMan@716 99 if(values.length % 2)
BrechtDeMan@716 100 return values[half];
BrechtDeMan@716 101 else
BrechtDeMan@716 102 return (values[half-1] + values[half]) / 2.0;
BrechtDeMan@716 103 }
BrechtDeMan@715 104
BrechtDeMan@715 105 function percentile(values, n) {
BrechtDeMan@715 106 values.sort( function(a,b) {return a - b;} );
BrechtDeMan@715 107 // get ordinal rank
BrechtDeMan@715 108 var rank = Math.min(Math.floor(values.length*n/100), values.length-1);
BrechtDeMan@715 109 return values[rank];
BrechtDeMan@715 110 }
BrechtDeMan@716 111
BrechtDeMan@716 112 /***********************
BrechtDeMan@715 113 * TIME MEASUREMENT *
BrechtDeMan@716 114 ************************/
BrechtDeMan@716 115
BrechtDeMan@716 116 // measure time since last time this function was called
BrechtDeMan@716 117 function timeSinceLastCall() {
BrechtDeMan@716 118 // current time
BrechtDeMan@716 119 var currentTime = new Date().getTime();
BrechtDeMan@716 120 // calculate time difference
BrechtDeMan@716 121 var timeDifference = currentTime - lastTimeMeasured + timeInBuffer;
BrechtDeMan@716 122 // clear buffer (for pausing)
BrechtDeMan@716 123 timeInBuffer = 0;
BrechtDeMan@716 124 // remember last measured time
BrechtDeMan@716 125 lastTimeMeasured = currentTime;
BrechtDeMan@716 126 return timeDifference;
BrechtDeMan@716 127 }
BrechtDeMan@716 128
BrechtDeMan@716 129 // pause time measurement
BrechtDeMan@716 130 function pauseTimeMeasurement() {
BrechtDeMan@716 131 // UN-PAUSE
BrechtDeMan@716 132 if (measurementPaused) { // already paused
BrechtDeMan@716 133 // button shows 'pause' again
BrechtDeMan@716 134 document.getElementById('pauseButton').innerHTML = 'Pause';
BrechtDeMan@716 135 // toggle state
BrechtDeMan@716 136 measurementPaused = false;
BrechtDeMan@716 137 // resume time measurement
BrechtDeMan@716 138 lastTimeMeasured = new Date().getTime(); // reset time, discard time while paused
BrechtDeMan@716 139 } else { // PAUSE
BrechtDeMan@716 140 // button shows 'resume'
BrechtDeMan@716 141 document.getElementById('pauseButton').innerHTML = 'Resume';
BrechtDeMan@716 142 // toggle state
BrechtDeMan@716 143 measurementPaused = true;
BrechtDeMan@716 144 // pause time measurement
BrechtDeMan@716 145 timeInBuffer = timeSinceLastCall();
BrechtDeMan@716 146 }
BrechtDeMan@716 147 }
BrechtDeMan@716 148
BrechtDeMan@716 149 // show elapsed time on interface
BrechtDeMan@716 150 function showTimeElapsedInSeconds() {
BrechtDeMan@716 151 // if paused: un-pause
BrechtDeMan@716 152 if (measurementPaused) {
BrechtDeMan@716 153 pauseTimeMeasurement();
BrechtDeMan@716 154 }
BrechtDeMan@716 155
BrechtDeMan@716 156 // time of last annotation
BrechtDeMan@716 157 var lastAnnotationTime = timeSinceLastCall()/1000;
BrechtDeMan@716 158 document.getElementById('timeDisplay').innerHTML = lastAnnotationTime.toFixed(2);
BrechtDeMan@716 159 // average time over last ... annotations
BrechtDeMan@716 160 var avgAnnotationTime;
BrechtDeMan@716 161 var numberOfElementsToAverage =
BrechtDeMan@716 162 document.getElementById('numberOfTimeAverages').value;
BrechtDeMan@716 163 if (isPositiveInteger(numberOfElementsToAverage)) {
BrechtDeMan@716 164 avgAnnotationTime =
BrechtDeMan@716 165 calculateAverageTime(lastAnnotationTime,
BrechtDeMan@716 166 Number(numberOfElementsToAverage));
BrechtDeMan@716 167 } else {
BrechtDeMan@716 168 // change text field content to 'ALL'
BrechtDeMan@716 169 document.getElementById('numberOfTimeAverages').value = 'ALL';
BrechtDeMan@716 170 avgAnnotationTime = calculateAverageTime(lastAnnotationTime, -1);
BrechtDeMan@716 171 }
BrechtDeMan@716 172 document.getElementById('timeAverageDisplay').innerHTML = avgAnnotationTime.toFixed(2);
BrechtDeMan@716 173 }
BrechtDeMan@716 174
BrechtDeMan@716 175 // auxiliary function: is string a positive integer?
BrechtDeMan@716 176 // http://stackoverflow.com/questions/10834796/...
BrechtDeMan@716 177 // validate-that-a-string-is-a-positive-integer
BrechtDeMan@716 178 function isPositiveInteger(str) {
BrechtDeMan@716 179 var n = ~~Number(str);
BrechtDeMan@716 180 return String(n) === str && n >= 0;
BrechtDeMan@716 181 }
BrechtDeMan@716 182
BrechtDeMan@716 183 // calculate average time
BrechtDeMan@716 184 function calculateAverageTime(newTimeMeasurementInSeconds,numberOfPoints) {
BrechtDeMan@716 185 // append last measurement time to time array, if significant
BrechtDeMan@716 186 if (newTimeMeasurementInSeconds > MIN_TIME) {
BrechtDeMan@716 187 timeArray.push(newTimeMeasurementInSeconds);
BrechtDeMan@716 188 }
BrechtDeMan@716 189 // average over last N elements of this array
BrechtDeMan@716 190 if (numberOfPoints < 0 || numberOfPoints>=timeArray.length) { // calculate average over all
BrechtDeMan@716 191 var sum = 0;
BrechtDeMan@716 192 for (var i = 0; i < timeArray.length; i++) {
BrechtDeMan@716 193 sum += timeArray[i];
BrechtDeMan@716 194 }
BrechtDeMan@716 195 averageOfTimes = sum/timeArray.length;
BrechtDeMan@716 196 } else { // calculate average over specified number of times measured last
BrechtDeMan@716 197 var sum = 0;
BrechtDeMan@716 198 for (var i = timeArray.length-numberOfPoints; i < timeArray.length; i++) {
BrechtDeMan@716 199 sum += timeArray[i];
BrechtDeMan@716 200 }
BrechtDeMan@716 201 averageOfTimes = sum/numberOfPoints;
BrechtDeMan@716 202 }
BrechtDeMan@716 203 return averageOfTimes;
BrechtDeMan@716 204 }
BrechtDeMan@716 205
BrechtDeMan@716 206
BrechtDeMan@716 207 /********************************
BrechtDeMan@715 208 * PLAYBACK OF AUDIO *
BrechtDeMan@716 209 ********************************/
BrechtDeMan@716 210
BrechtDeMan@715 211 //PLAYaudioelement
BrechtDeMan@716 212 // Keep track of whether audio should be played
BrechtDeMan@716 213 function playFlagChanged(){
BrechtDeMan@716 214 playAudio = playFlag.checked; // global variable
BrechtDeMan@716 215
BrechtDeMan@716 216 if (!playAudio){ // if audio needs to stop
BrechtDeMan@716 217 audio.pause(); // stop audio - if anything is playing
BrechtDeMan@715 218 currently_playing = ''; // back to empty string so playaudioelement knows nothing's playing
BrechtDeMan@716 219 }
BrechtDeMan@716 220 }
BrechtDeMan@716 221
BrechtDeMan@715 222 // audioholder that's currently playing
BrechtDeMan@715 223 var currently_playing_audioholder = ''; // at first: empty string
BrechtDeMan@715 224 var currently_playing_audioelement = '';
BrechtDeMan@716 225 var audio;
BrechtDeMan@716 226
BrechtDeMan@715 227 // Play audioelement of audioholder if available, from start or from same position
BrechtDeMan@715 228 function playaudioelement(audioholderName, audioelementerName){
BrechtDeMan@716 229 if (playAudio) { // if enabled
BrechtDeMan@716 230 // get corresponding file from folder
BrechtDeMan@715 231 var file_location = 'audio/'+audioholderName + '/' + audioelementerName + '.mp3'; // fixed path and file name format
BrechtDeMan@716 232
BrechtDeMan@716 233 // if not available, show error/warning message
BrechtDeMan@716 234 //TODO ...
BrechtDeMan@716 235
BrechtDeMan@716 236 // if nothing playing yet, start playing
BrechtDeMan@715 237 if (currently_playing_audioholder == ''){ // signal that nothing is playing
BrechtDeMan@716 238 //playSound(audioBuffer);
BrechtDeMan@716 239 audio = new Audio(file_location);
BrechtDeMan@716 240 audio.loop = true; // loop when end is reached
BrechtDeMan@716 241 audio.play();
BrechtDeMan@715 242 currently_playing_audioholder = audioholderName;
BrechtDeMan@715 243 currently_playing_audioelement = audioelementerName;
BrechtDeMan@715 244 } else if (currently_playing_audioholder != audioholderName) {
BrechtDeMan@715 245 // if different audioholder playing, stop that and start playing
BrechtDeMan@716 246 audio.pause(); // stop audio
BrechtDeMan@716 247 audio = new Audio(file_location); // load new file
BrechtDeMan@716 248 audio.loop = true; // loop when end is reached
BrechtDeMan@716 249 audio.play(); // play audio from the start
BrechtDeMan@715 250 currently_playing_audioholder = audioholderName;
BrechtDeMan@715 251 currently_playing_audioelement = audioelementerName;
BrechtDeMan@715 252 } else if (currently_playing_audioelement != audioelementerName) {
BrechtDeMan@715 253 // if same audioholder playing, start playing from where it left off
BrechtDeMan@716 254 skipTime = audio.currentTime; // time to skip to
BrechtDeMan@716 255 audio.pause(); // stop audio
BrechtDeMan@716 256 audio = new Audio(file_location);
BrechtDeMan@716 257 audio.addEventListener('loadedmetadata', function() {
BrechtDeMan@716 258 this.currentTime = skipTime;
BrechtDeMan@715 259 console.log('Loaded '+audioholderName+'-'+audioelementerName+', playing from '+skipTime);
BrechtDeMan@716 260 }, false); // skip to same time when audio is loaded!
BrechtDeMan@716 261 audio.loop = true; // loop when end is reached
BrechtDeMan@716 262 audio.play(); // play from that time
BrechtDeMan@716 263 audio.currentTime = skipTime;
BrechtDeMan@715 264 currently_playing_audioholder = audioholderName;
BrechtDeMan@715 265 currently_playing_audioelement = audioelementerName;
BrechtDeMan@716 266 }
BrechtDeMan@715 267 // if same audioelement playing: keep on playing (i.e. do nothing)
BrechtDeMan@716 268 }
BrechtDeMan@716 269 }
BrechtDeMan@716 270
BrechtDeMan@716 271 /********************
BrechtDeMan@715 272 * READING FILES *
BrechtDeMan@716 273 ********************/
BrechtDeMan@716 274
BrechtDeMan@716 275 // Read necessary data from XML file
BrechtDeMan@716 276 function readXML(xmlFileName){
BrechtDeMan@716 277 if (window.XMLHttpRequest)
BrechtDeMan@716 278 {// code for IE7+, Firefox, Chrome, Opera, Safari
BrechtDeMan@716 279 xmlhttp=new XMLHttpRequest();
BrechtDeMan@716 280 }
BrechtDeMan@716 281 else
BrechtDeMan@716 282 {// code for IE6, IE5
BrechtDeMan@716 283 xmlhttp=new ActiveXObject("Microsoft.XMLHTTP");
BrechtDeMan@716 284 }
BrechtDeMan@716 285 xmlhttp.open("GET",xmlFileName,false);
BrechtDeMan@716 286 xmlhttp.send();
BrechtDeMan@716 287 return xmlhttp.responseXML;
BrechtDeMan@716 288 }
BrechtDeMan@716 289
BrechtDeMan@716 290 // go over all files and compute relevant statistics
BrechtDeMan@716 291 function loadAllFiles() {
BrechtDeMan@716 292 // retrieve information from XMLs
BrechtDeMan@716 293
BrechtDeMan@716 294 for (fileIndex = 0; fileIndex < xmlFiles.length; fileIndex++) {
BrechtDeMan@716 295 xmlFileName = xmlFileFolder+"/"+xmlFiles[fileIndex];
BrechtDeMan@716 296 xml = readXML(xmlFileName);
BrechtDeMan@716 297 if (xml != null) { // if file exists
BrechtDeMan@716 298 // append file name to array of file names
BrechtDeMan@716 299 fileNameArray.push(xmlFiles[fileIndex]);
BrechtDeMan@716 300
BrechtDeMan@716 301 // get root of XML file
BrechtDeMan@716 302 root = xml.getElementsByTagName('browserevaluationresult')[0];
BrechtDeMan@716 303
BrechtDeMan@716 304 // get subject ID, add to array if not already there
BrechtDeMan@716 305 pretest = root.getElementsByTagName('pretest')[0];
BrechtDeMan@716 306 subjectID = pretest.getElementsByTagName('comment')[0];
BrechtDeMan@716 307 if (subjectID.getAttribute('id')!='sessionId') { // warning in console when not available
BrechtDeMan@716 308 console.log(xmlFiles[fileIndex]+': no SessionID available');
BrechtDeMan@716 309 }
BrechtDeMan@716 310 if (subjectArray.indexOf(subjectID.textContent) == -1) { // if not already in array
BrechtDeMan@716 311 subjectArray.push(subjectID.textContent); // append to array
BrechtDeMan@716 312 }
BrechtDeMan@716 313
BrechtDeMan@715 314 // go over all audioholders, add to array if not already there
BrechtDeMan@715 315 audioholderNodes = root.getElementsByTagName('audioholder');
BrechtDeMan@715 316 // go over audioholderNodes and append audioholder name when not present yet
BrechtDeMan@715 317 for (audioholderIndex = 0; audioholderIndex < audioholderNodes.length; audioholderIndex++) {
BrechtDeMan@715 318 audioholderName = audioholderNodes[audioholderIndex].getAttribute('id');
BrechtDeMan@715 319 if (audioholderArray.indexOf(audioholderName) == -1) { // if not already in array
BrechtDeMan@715 320 audioholderArray.push(audioholderName); // append to array
BrechtDeMan@716 321 }
BrechtDeMan@715 322 // within each audioholder, go over all audioelement IDs, add to array if not already there
BrechtDeMan@715 323 audioelementNodes = audioholderNodes[audioholderIndex].getElementsByTagName('audioelement');
BrechtDeMan@715 324 for (audioelementIndex = 0; audioelementIndex < audioelementNodes.length; audioelementIndex++) {
BrechtDeMan@715 325 audioelementName = audioelementNodes[audioelementIndex].getAttribute('id');
BrechtDeMan@715 326 if (audioelementArray.indexOf(audioelementName) == -1) { // if not already in array
BrechtDeMan@715 327 audioelementArray.push(audioelementName); // append to array
BrechtDeMan@716 328 }
BrechtDeMan@716 329 }
BrechtDeMan@716 330 }
BrechtDeMan@715 331 // count occurrences of each audioholder
BrechtDeMan@716 332 // ...
BrechtDeMan@716 333 }
BrechtDeMan@716 334 else {
BrechtDeMan@716 335 console.log('XML file '+xmlFileName+' not found.');
BrechtDeMan@716 336 }
BrechtDeMan@716 337 }
BrechtDeMan@716 338
BrechtDeMan@716 339 // sort alphabetically
BrechtDeMan@716 340 fileNameArray.sort();
BrechtDeMan@716 341 subjectArray.sort();
BrechtDeMan@715 342 audioholderArray.sort();
BrechtDeMan@715 343 audioelementArray.sort();
BrechtDeMan@716 344
BrechtDeMan@716 345 // display all information in HTML
BrechtDeMan@716 346 // show XML file folder
BrechtDeMan@716 347 document.getElementById('xmlFileFolder_span').innerHTML = "\""+xmlFileFolder+"/\"";
BrechtDeMan@716 348 // show number of files
BrechtDeMan@716 349 document.getElementById('numberOfFiles_span').innerHTML = fileNameArray.length;
BrechtDeMan@716 350 // show list of subject names
BrechtDeMan@716 351 document.getElementById('subjectArray_span').innerHTML = subjectArray.toString();
BrechtDeMan@715 352 // show list of audioholders
BrechtDeMan@715 353 document.getElementById('audioholderArray_span').innerHTML = audioholderArray.toString();
BrechtDeMan@715 354 // show list of audioelementes
BrechtDeMan@715 355 document.getElementById('audioelementArray_span').innerHTML = audioelementArray.toString();
BrechtDeMan@716 356 }
BrechtDeMan@716 357
BrechtDeMan@715 358 function makePlots() { //TODO: split into different functions
BrechtDeMan@715 359 // TEMPORARY
BrechtDeMan@715 360 makeTimeline(xmlFileFolder+"/"+xmlFiles[7]);
BrechtDeMan@715 361
BrechtDeMan@716 362 // create value array
BrechtDeMan@715 363 var ratings = []; // 3D matrix of ratings (audioholder, audioelement, subject)
BrechtDeMan@715 364 for (audioholderIndex = 0; audioholderIndex < audioholderArray.length; audioholderIndex++) {
BrechtDeMan@716 365 ratings.push([]);
BrechtDeMan@715 366 for (audioelementIndex = 0; audioelementIndex < audioelementArray.length; audioelementIndex++) {
BrechtDeMan@715 367 ratings[audioholderIndex].push([]);
BrechtDeMan@716 368 }
BrechtDeMan@716 369 }
BrechtDeMan@716 370
BrechtDeMan@716 371 // go over all XML files
BrechtDeMan@716 372 for (fileIndex = 0; fileIndex < xmlFiles.length; fileIndex++) {
BrechtDeMan@716 373 xmlFileName = xmlFileFolder+"/"+xmlFiles[fileIndex];
BrechtDeMan@716 374 xml = readXML(xmlFileName);
BrechtDeMan@716 375 if (xml != null) { // if file exists
BrechtDeMan@716 376 // get root of XML file
BrechtDeMan@716 377 root = xml.getElementsByTagName('browserevaluationresult')[0];
BrechtDeMan@715 378 // go over all audioholders
BrechtDeMan@715 379 audioholderNodes = root.getElementsByTagName('audioholder');
BrechtDeMan@715 380 for (audioholderIndex = 0; audioholderIndex < audioholderNodes.length; audioholderIndex++) {
BrechtDeMan@715 381 audioholderName = audioholderNodes[audioholderIndex].getAttribute('id');
BrechtDeMan@715 382 audioelementNodes = audioholderNodes[audioholderIndex].getElementsByTagName('audioelement');
BrechtDeMan@716 383 // go over all audioelements
BrechtDeMan@715 384 for (audioelementIndex = 0; audioelementIndex < audioelementNodes.length; audioelementIndex++) {
BrechtDeMan@715 385 audioelementName = audioelementNodes[audioelementIndex].getAttribute('id');
BrechtDeMan@716 386 // get value
BrechtDeMan@715 387 var value = audioelementNodes[audioelementIndex].getElementsByTagName("value")[0].textContent;
BrechtDeMan@716 388 if (value) { // if not empty, null, undefined...
BrechtDeMan@716 389 ratingValue = parseFloat(value);
BrechtDeMan@715 390 // add to matrix at proper position
BrechtDeMan@715 391 aHidx = audioholderArray.indexOf(audioholderName);
BrechtDeMan@715 392 aEidx = audioelementArray.indexOf(audioelementName);
BrechtDeMan@715 393 ratings[aHidx][aEidx].push(ratingValue);
BrechtDeMan@716 394 }
BrechtDeMan@716 395 }
BrechtDeMan@716 396 }
BrechtDeMan@716 397
BrechtDeMan@715 398 // go over all audioholders
BrechtDeMan@716 399
BrechtDeMan@715 400 // go over all audioelements within audioholder, see if present in idMatrix, add if not
BrechtDeMan@716 401 // add corresponding rating to 'ratings', at position corresponding with position in idMatrix
BrechtDeMan@716 402 }
BrechtDeMan@716 403 }
BrechtDeMan@716 404
BrechtDeMan@715 405 for (audioholderIndex = 0; audioholderIndex < audioholderArray.length; audioholderIndex++) {
BrechtDeMan@715 406 audioholderName = audioholderArray[audioholderIndex]; // for this song
BrechtDeMan@716 407 tickArray = []
BrechtDeMan@716 408
BrechtDeMan@716 409 raw_data = [['SubjectID', 'Rating']];
BrechtDeMan@716 410 audioElIdx = 0;
BrechtDeMan@715 411 for (audioelementIndex = 0; audioelementIndex<ratings[audioholderIndex].length; audioelementIndex++){
BrechtDeMan@715 412 if (ratings[audioholderIndex][audioelementIndex].length>0) {
BrechtDeMan@716 413 audioElIdx++; // increase if not empty
BrechtDeMan@716 414 // make tick label
BrechtDeMan@715 415 tickArray.push({v:audioElIdx, f: audioelementArray[audioelementIndex]});
BrechtDeMan@716 416 }
BrechtDeMan@715 417 for (subject = 0; subject<ratings[audioholderIndex][audioelementIndex].length; subject++){
BrechtDeMan@716 418 // add subject-value pair for each subject
BrechtDeMan@715 419 raw_data.push([audioElIdx, ratings[audioholderIndex][audioelementIndex][subject]]);
BrechtDeMan@716 420 }
BrechtDeMan@716 421 }
BrechtDeMan@716 422
BrechtDeMan@716 423 // create plot (one per song)
BrechtDeMan@716 424 var data = google.visualization.arrayToDataTable(raw_data);
BrechtDeMan@716 425
BrechtDeMan@716 426 var options = {
BrechtDeMan@715 427 title: audioholderName,
BrechtDeMan@715 428 hAxis: {title: 'audioelement ID', minValue: 0, maxValue: audioElIdx+1,
BrechtDeMan@716 429 ticks: tickArray},
BrechtDeMan@716 430 vAxis: {title: 'Rating', minValue: 0, maxValue: 1},
BrechtDeMan@716 431 seriesType: 'scatter',
BrechtDeMan@716 432 legend: 'none'
BrechtDeMan@716 433 };
BrechtDeMan@716 434 var div = document.createElement('div');
BrechtDeMan@716 435 document.body.appendChild(div);
BrechtDeMan@715 436 div.id = 'div_'+audioholderName;
BrechtDeMan@716 437 div.style.width = '1100px';
BrechtDeMan@716 438 div.style.height = '350px';
BrechtDeMan@715 439 var chart = new google.visualization.ComboChart(document.getElementById('div_'+audioholderName));
BrechtDeMan@716 440 chart.draw(data, options);
BrechtDeMan@716 441
BrechtDeMan@716 442 // box plots
BrechtDeMan@715 443 var div = document.createElement('div');
BrechtDeMan@715 444 document.body.appendChild(div);
BrechtDeMan@715 445 div.id = 'div_box_'+audioholderName;
BrechtDeMan@715 446 div.style.width = '1100px';
BrechtDeMan@715 447 div.style.height = '350px';
BrechtDeMan@715 448 // Get median, percentiles, maximum and minimum; outliers.
BrechtDeMan@715 449 pctl25 = [];
BrechtDeMan@715 450 pctl75 = [];
BrechtDeMan@715 451 med = [];
BrechtDeMan@715 452 min = [];
BrechtDeMan@715 453 max = [];
BrechtDeMan@715 454 outlierArray = [];
BrechtDeMan@715 455 max_n_outliers = 0; // maximum number of outliers for one audioelement
BrechtDeMan@715 456 for (audioelementIndex = 0; audioelementIndex<ratings[audioholderIndex].length; audioelementIndex++){
BrechtDeMan@715 457 med.push(median(ratings[audioholderIndex][audioelementIndex])); // median
BrechtDeMan@715 458 pctl25.push(percentile(ratings[audioholderIndex][audioelementIndex], 25)); // 25th percentile
BrechtDeMan@715 459 pctl75.push(percentile(ratings[audioholderIndex][audioelementIndex], 75)); // 75th percentile
BrechtDeMan@715 460 IQR = pctl75[pctl75.length-1]-pctl25[pctl25.length-1];
BrechtDeMan@715 461 // outliers: range of values which is above pctl75+1.5*IQR or below pctl25-1.5*IQR
BrechtDeMan@715 462 outliers = [];
BrechtDeMan@715 463 rest = [];
BrechtDeMan@715 464 for (idx = 0; idx<ratings[audioholderIndex][audioelementIndex].length; idx++){
BrechtDeMan@715 465 if (ratings[audioholderIndex][audioelementIndex][idx] > pctl75[pctl75.length-1]+1.5*IQR ||
BrechtDeMan@715 466 ratings[audioholderIndex][audioelementIndex][idx] < pctl25[pctl25.length-1]-1.5*IQR){
BrechtDeMan@715 467 outliers.push(ratings[audioholderIndex][audioelementIndex][idx]);
BrechtDeMan@715 468 }
BrechtDeMan@715 469 else {
BrechtDeMan@715 470 rest.push(ratings[audioholderIndex][audioelementIndex][idx]);
BrechtDeMan@715 471 }
BrechtDeMan@715 472 }
BrechtDeMan@715 473 outlierArray.push(outliers);
BrechtDeMan@715 474 max_n_outliers = Math.max(max_n_outliers, outliers.length); // update max mber
BrechtDeMan@715 475 // max: maximum value which is not outlier
BrechtDeMan@715 476 max.push(Math.max.apply(null, rest));
BrechtDeMan@715 477 // min: minimum value which is not outlier
BrechtDeMan@715 478 min.push(Math.min.apply(null, rest));
BrechtDeMan@715 479 }
BrechtDeMan@715 480
BrechtDeMan@715 481 // Build data array
BrechtDeMan@715 482 boxplot_data = [['ID', 'Span', '', '', '', 'Median']];
BrechtDeMan@715 483 for (idx = 0; idx < max_n_outliers; idx++) {
BrechtDeMan@715 484 boxplot_data[0].push('Outlier');
BrechtDeMan@715 485 }
BrechtDeMan@715 486 for (audioelementIndex = 0; audioelementIndex<ratings[audioholderIndex].length; audioelementIndex++){
BrechtDeMan@715 487 if (ratings[audioholderIndex][audioelementIndex].length>0) { // if rating array not empty for this audioelement
BrechtDeMan@715 488 data_array = [
BrechtDeMan@715 489 audioelementArray[audioelementIndex], // name
BrechtDeMan@715 490 min[audioelementIndex], // minimum
BrechtDeMan@715 491 pctl75[audioelementIndex],
BrechtDeMan@715 492 pctl25[audioelementIndex],
BrechtDeMan@715 493 max[audioelementIndex], // maximum
BrechtDeMan@715 494 med[audioelementIndex]
BrechtDeMan@715 495 ];
BrechtDeMan@715 496 for (idx = 0; idx < max_n_outliers; idx++) {
BrechtDeMan@715 497 if (idx<outlierArray[audioelementIndex].length){
BrechtDeMan@715 498 data_array.push(outlierArray[audioelementIndex][idx]);
BrechtDeMan@715 499 }
BrechtDeMan@715 500 else {
BrechtDeMan@715 501 data_array.push(null);
BrechtDeMan@715 502 }
BrechtDeMan@715 503 }
BrechtDeMan@715 504 boxplot_data.push(data_array);
BrechtDeMan@715 505 }
BrechtDeMan@715 506 }
BrechtDeMan@715 507
BrechtDeMan@715 508 // Create and populate the data table.
BrechtDeMan@715 509 var data = google.visualization.arrayToDataTable(boxplot_data);
BrechtDeMan@715 510 // Create and draw the visualization.
BrechtDeMan@715 511 var ac = new google.visualization.ComboChart(document.getElementById('div_box_'+audioholderName));
BrechtDeMan@715 512 ac.draw(data, {
BrechtDeMan@715 513 title : audioholderName,
BrechtDeMan@715 514 //width: 600,
BrechtDeMan@715 515 //height: 400,
BrechtDeMan@715 516 vAxis: {title: "Rating"},
BrechtDeMan@715 517 hAxis: {title: "audioelement ID"},
BrechtDeMan@715 518 seriesType: "line",
BrechtDeMan@715 519 pointSize: 5,
BrechtDeMan@715 520 lineWidth: 0,
BrechtDeMan@715 521 colors: ['black'],
BrechtDeMan@715 522 series: { 0: {type: "candlesticks", color: 'blue'}, // box plot shape
BrechtDeMan@715 523 1: {type: "line", pointSize: 10, lineWidth: 0, color: 'red' } }, // median
BrechtDeMan@715 524 legend: 'none'
BrechtDeMan@715 525 });
BrechtDeMan@715 526 }
BrechtDeMan@715 527 }
BrechtDeMan@715 528
BrechtDeMan@715 529 function makeTimeline(xmlFileName){ // WIP
BrechtDeMan@715 530 // Based on the XML file name, take time data and plot playback and marker movements
BrechtDeMan@715 531
BrechtDeMan@715 532 // read XML file and check if exists
BrechtDeMan@715 533 xml = readXML(xmlFileName);
BrechtDeMan@715 534 if (!xml) { // if file does not exist
BrechtDeMan@715 535 console.log('XML file '+xml+'does not exist. ('+xmlFileName+')')
BrechtDeMan@715 536 return; // do nothing; exit function
BrechtDeMan@715 537 }
BrechtDeMan@715 538 // get root of XML file
BrechtDeMan@715 539 root = xml.getElementsByTagName('browserevaluationresult')[0];
BrechtDeMan@715 540
BrechtDeMan@715 541 audioholder_time = 0;
BrechtDeMan@715 542 previous_audioholder_time = 0; // time spent before current audioholder
BrechtDeMan@715 543 time_offset = 0; // test starts at zero
BrechtDeMan@715 544
BrechtDeMan@715 545 // go over all audioholders
BrechtDeMan@715 546 audioholderNodes = root.getElementsByTagName('audioholder');
BrechtDeMan@715 547 for (audioholderIndex = 0; audioholderIndex < audioholderNodes.length; audioholderIndex++) {
BrechtDeMan@715 548 audioholderName = audioholderNodes[audioholderIndex].getAttribute('id');
BrechtDeMan@715 549 if (!audioholderName) {
BrechtDeMan@715 550 console.log('audioholder name is empty; go to next one. ('+xmlFileName+')');
BrechtDeMan@715 551 break;
BrechtDeMan@715 552 }
BrechtDeMan@715 553
BrechtDeMan@715 554 // subtract total audioholder length from subsequent audioholder event times
BrechtDeMan@715 555 audioholder_children = audioholderNodes[audioholderIndex].childNodes;
BrechtDeMan@715 556 foundIt = false;
BrechtDeMan@715 557 console.log(audioholder_children[2].getElementsByTagName("metricResult")) // not working!
BrechtDeMan@715 558 for (idx = 0; idx<audioholder_children.length; idx++) { // go over children
BrechtDeMan@715 559
BrechtDeMan@715 560 if (audioholder_children[idx].getElementsByTagName('metricResult').length) {
BrechtDeMan@715 561 console.log(audioholder_children[idx].getElementsByTagName('metricResult')[0]);
BrechtDeMan@715 562 if (audioholder_children[idx].getElementsByTagName('metricResult')[0].getAttribute('id') == "testTime"){
BrechtDeMan@715 563 audioholder_time = parseFloat(audioholder_children[idx].getElementsByTagName('metricResult')[0].textContent);
BrechtDeMan@715 564 console.log(audioholder_time);
BrechtDeMan@715 565 foundIt = true;
BrechtDeMan@715 566 }
BrechtDeMan@715 567 }
BrechtDeMan@715 568 }
BrechtDeMan@715 569 if (!foundIt) {
BrechtDeMan@715 570 console.log("Skipping audioholder without total time specified from "+xmlFileName+"."); // always hitting this
BrechtDeMan@715 571 break;
BrechtDeMan@715 572 }
BrechtDeMan@715 573
BrechtDeMan@715 574 audioelementNodes = audioholderNodes[audioholderIndex].getElementsByTagName('audioelement');
BrechtDeMan@715 575
BrechtDeMan@715 576 // make div
BrechtDeMan@715 577
BrechtDeMan@715 578 // draw chart
BrechtDeMan@715 579
BrechtDeMan@715 580 // legend with audioelement names
BrechtDeMan@716 581 }
BrechtDeMan@716 582 }
BrechtDeMan@716 583
BrechtDeMan@716 584 </script>
BrechtDeMan@716 585
BrechtDeMan@716 586
BrechtDeMan@716 587
BrechtDeMan@716 588 <style>
BrechtDeMan@716 589 div {
BrechtDeMan@716 590 padding: 2px;
BrechtDeMan@716 591 margin-top: 2px;
BrechtDeMan@716 592 margin-bottom: 2px;
BrechtDeMan@716 593 }
BrechtDeMan@716 594 div.head{
BrechtDeMan@716 595 margin-left: 10px;
BrechtDeMan@716 596 border: black;
BrechtDeMan@716 597 border-width: 2px;
BrechtDeMan@716 598 border-style: solid;
BrechtDeMan@716 599 }
BrechtDeMan@716 600 div.attrib{
BrechtDeMan@716 601 margin-left:25px;
BrechtDeMan@716 602 border: black;
BrechtDeMan@716 603 border-width: 2px;
BrechtDeMan@716 604 border-style: dashed;
BrechtDeMan@716 605 margin-bottom: 10px;
BrechtDeMan@716 606 }
BrechtDeMan@716 607 div#headerMatter{
BrechtDeMan@716 608 background-color: #FFFFCC;
BrechtDeMan@716 609 }
BrechtDeMan@716 610 div#currentStatement{
BrechtDeMan@716 611 font-size:3.0em;
BrechtDeMan@716 612 font-weight: bold;
BrechtDeMan@716 613
BrechtDeMan@716 614 }
BrechtDeMan@716 615 div#debugDisplay {
BrechtDeMan@716 616 color: #CCCCCC;
BrechtDeMan@716 617 font-size:0.3em;
BrechtDeMan@716 618 }
BrechtDeMan@716 619 span#scoreDisplay {
BrechtDeMan@716 620 font-weight: bold;
BrechtDeMan@716 621 }
BrechtDeMan@716 622 div#wrapper {
BrechtDeMan@716 623 width: 780px;
BrechtDeMan@716 624 border: 1px solid black;
BrechtDeMan@716 625 overflow: hidden; /* add this to contain floated children */
BrechtDeMan@716 626 }
BrechtDeMan@716 627 div#instrumentSection {
BrechtDeMan@715 628 width: 250px;
BrechtDeMan@715 629 border: 1px solid red;
BrechtDeMan@715 630 display: inline-block;
BrechtDeMan@716 631 }
BrechtDeMan@716 632 div#featureSection {
BrechtDeMan@716 633 width: 250px;
BrechtDeMan@715 634 border: 1px solid green;
BrechtDeMan@715 635 display: inline-block;
BrechtDeMan@716 636 }
BrechtDeMan@716 637 div#valenceSection {
BrechtDeMan@716 638 width: 250px;
BrechtDeMan@715 639 border: 1px solid blue;
BrechtDeMan@715 640 display: inline-block;
BrechtDeMan@716 641 }
BrechtDeMan@716 642 button#previousComment{
BrechtDeMan@716 643 width: 120px;
BrechtDeMan@716 644 height: 150px;
BrechtDeMan@716 645 font-size:1.5em;
BrechtDeMan@716 646 }
BrechtDeMan@716 647 button#nextComment{
BrechtDeMan@716 648 width: 666px;
BrechtDeMan@716 649 height: 150px;
BrechtDeMan@716 650 font-size:1.5em;
BrechtDeMan@716 651 }
BrechtDeMan@716 652 ul
BrechtDeMan@716 653 {
BrechtDeMan@716 654 list-style-type: none; /* no bullet points */
BrechtDeMan@716 655 margin-left: -20px; /* less indent */
BrechtDeMan@716 656 margin-top: 0px;
BrechtDeMan@716 657 margin-bottom: 5px;
BrechtDeMan@716 658 }
BrechtDeMan@716 659 </style>
BrechtDeMan@716 660
BrechtDeMan@716 661 </head>
BrechtDeMan@716 662
BrechtDeMan@716 663 <body>
BrechtDeMan@716 664 <h1>Subjective evaluation results</h1>
BrechtDeMan@716 665
BrechtDeMan@716 666 <div id="debugDisplay">
BrechtDeMan@716 667 XML file folder: <span id="xmlFileFolder_span"></span>
BrechtDeMan@716 668 </div>
BrechtDeMan@716 669
BrechtDeMan@716 670 <div id="headerMatter">
BrechtDeMan@716 671 <div>
BrechtDeMan@716 672 <strong>Result XML files:</strong> <span id="numberOfFiles_span"></span>
BrechtDeMan@716 673 </div>
BrechtDeMan@716 674 <div>
BrechtDeMan@715 675 <strong>Audioholders in dataset:</strong> <span id="audioholderArray_span"></span>
BrechtDeMan@716 676 </div>
BrechtDeMan@716 677 <div>
BrechtDeMan@716 678 <strong>Subjects in dataset:</strong> <span id="subjectArray_span"></span>
BrechtDeMan@716 679 </div>
BrechtDeMan@716 680 <div>
BrechtDeMan@715 681 <strong>Audioelements in dataset:</strong> <span id="audioelementArray_span"></span>
BrechtDeMan@716 682 </div>
BrechtDeMan@716 683 <br>
BrechtDeMan@716 684 </div>
BrechtDeMan@716 685 <br>
BrechtDeMan@716 686
BrechtDeMan@716 687 <!-- Show time elapsed
BrechtDeMan@716 688 The last annotation took <strong><span id="timeDisplay">(N/A)</span></strong> seconds.
BrechtDeMan@716 689 <br>-->
BrechtDeMan@716 690
BrechtDeMan@716 691 </body>
BrechtDeMan@716 692 </html>