annotate analyse.html @ 715:50c651d27330

Paper: Added interface screenshot and box plot example
author Brecht De Man <BrechtDeMan@users.noreply.github.com>
date Thu, 15 Oct 2015 20:10:00 +0100
parents
children 9da8a3e65a78
rev   line source
BrechtDeMan@715 1 <!DOCTYPE html>
BrechtDeMan@715 2 <html lang="en">
BrechtDeMan@715 3 <head>
BrechtDeMan@715 4 <meta charset="utf-8">
BrechtDeMan@715 5
BrechtDeMan@715 6 <!-- Always force latest IE rendering engine (even in intranet) & Chrome Frame
BrechtDeMan@715 7 Remove this if you use the .htaccess -->
BrechtDeMan@715 8 <meta http-equiv="X-UA-Compatible" content="IE=edge,chrome=1">
BrechtDeMan@715 9
BrechtDeMan@715 10 <title>Analysis</title>
BrechtDeMan@715 11 <meta name="description" content="Show results from subjective evaluation">
BrechtDeMan@715 12 <meta name="author" content="Brecht De Man">
BrechtDeMan@715 13
BrechtDeMan@715 14 <script type="text/javascript" src="https://www.google.com/jsapi"></script>
BrechtDeMan@715 15 <script type="text/javascript">
BrechtDeMan@715 16 // To aid 'one-page set-up' all scripts and CSS must be included directly in this file!
BrechtDeMan@715 17
BrechtDeMan@715 18 google.load("visualization", "1", {packages:["corechart"]});
BrechtDeMan@715 19
BrechtDeMan@715 20 /*************
BrechtDeMan@715 21 * SETUP *
BrechtDeMan@715 22 *************/
BrechtDeMan@715 23 // folder where to find the XML files
BrechtDeMan@715 24 xmlFileFolder = "analysis_test";
BrechtDeMan@715 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@715 28
BrechtDeMan@715 29 //TODO: make retrieval of file names automatic / drag files on here
BrechtDeMan@715 30
BrechtDeMan@715 31 /****************
BrechtDeMan@715 32 * VARIABLES *
BrechtDeMan@715 33 ****************/
BrechtDeMan@715 34
BrechtDeMan@715 35 // Counters
BrechtDeMan@715 36 // How many files, audioholders, audioelementes and statements annotated (don't count current one)
BrechtDeMan@715 37 var numberOfFiles = -1;
BrechtDeMan@715 38 var numberOfaudioholders = -1;
BrechtDeMan@715 39 var numberOfaudioelementes = -1;
BrechtDeMan@715 40 var numberOfStatements = -1;
BrechtDeMan@715 41 var numberOfSkippedComments = 0;
BrechtDeMan@715 42
BrechtDeMan@715 43 // Object arrays
BrechtDeMan@715 44 var fileNameArray = [];
BrechtDeMan@715 45 var subjectArray = [];
BrechtDeMan@715 46 var audioholderArray = [];
BrechtDeMan@715 47 var audioelementArray = [];
BrechtDeMan@715 48
BrechtDeMan@715 49 // End of (file, audioholder, audioelement) flags
BrechtDeMan@715 50 var newFile = true;
BrechtDeMan@715 51 var newAudioHolder = true;
BrechtDeMan@715 52 var newAudioElement = true;
BrechtDeMan@715 53
BrechtDeMan@715 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@715 57 var statementNumber=0; // total number of statements
BrechtDeMan@715 58
BrechtDeMan@715 59 var root; // root of XML file
BrechtDeMan@715 60 var commentInFull = ''; // full comment
BrechtDeMan@715 61
BrechtDeMan@715 62 var playAudio = true; // whether corresponding audio should be played back
BrechtDeMan@715 63
BrechtDeMan@715 64 // // Measuring time
BrechtDeMan@715 65 // var lastTimeMeasured = -1; //
BrechtDeMan@715 66 // var durationLastAnnotation = -1; // duration of last annotation
BrechtDeMan@715 67 // var timeArray = [];
BrechtDeMan@715 68 // var MIN_TIME = 1.0; // minimum time counted as significant
BrechtDeMan@715 69 // var measurementPaused = false; // whether time measurement is paused
BrechtDeMan@715 70 // var timeInBuffer = 0; //
BrechtDeMan@715 71
BrechtDeMan@715 72 var topLevel;
BrechtDeMan@715 73 window.onload = function() {
BrechtDeMan@715 74 // Initialise page
BrechtDeMan@715 75 topLevel = document.getElementById('topLevelBody');
BrechtDeMan@715 76 var setup = document.createElement('div');
BrechtDeMan@715 77 setup.id = 'setupTagDiv';
BrechtDeMan@715 78 loadAllFiles();
BrechtDeMan@715 79
BrechtDeMan@715 80 makePlots();
BrechtDeMan@715 81 // measure time at this point:
BrechtDeMan@715 82 lastTimeMeasured = new Date().getTime(); // in milliseconds
BrechtDeMan@715 83 };
BrechtDeMan@715 84
BrechtDeMan@715 85 // Assert function
BrechtDeMan@715 86 function assert(condition, message) {
BrechtDeMan@715 87 if (!condition) {
BrechtDeMan@715 88 message = message || "Assertion failed";
BrechtDeMan@715 89 if (typeof Error !== "undefined") {
BrechtDeMan@715 90 throw new Error(message);
BrechtDeMan@715 91 }
BrechtDeMan@715 92 throw message; // Fallback
BrechtDeMan@715 93 }
BrechtDeMan@715 94 }
BrechtDeMan@715 95
BrechtDeMan@715 96 function median(values) { // TODO: replace code by '50th percentile' - should be the same?
BrechtDeMan@715 97 values.sort( function(a,b) {return a - b;} );
BrechtDeMan@715 98 var half = Math.floor(values.length/2);
BrechtDeMan@715 99 if(values.length % 2)
BrechtDeMan@715 100 return values[half];
BrechtDeMan@715 101 else
BrechtDeMan@715 102 return (values[half-1] + values[half]) / 2.0;
BrechtDeMan@715 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@715 111
BrechtDeMan@715 112 /***********************
BrechtDeMan@715 113 * TIME MEASUREMENT *
BrechtDeMan@715 114 ************************/
BrechtDeMan@715 115
BrechtDeMan@715 116 // measure time since last time this function was called
BrechtDeMan@715 117 function timeSinceLastCall() {
BrechtDeMan@715 118 // current time
BrechtDeMan@715 119 var currentTime = new Date().getTime();
BrechtDeMan@715 120 // calculate time difference
BrechtDeMan@715 121 var timeDifference = currentTime - lastTimeMeasured + timeInBuffer;
BrechtDeMan@715 122 // clear buffer (for pausing)
BrechtDeMan@715 123 timeInBuffer = 0;
BrechtDeMan@715 124 // remember last measured time
BrechtDeMan@715 125 lastTimeMeasured = currentTime;
BrechtDeMan@715 126 return timeDifference;
BrechtDeMan@715 127 }
BrechtDeMan@715 128
BrechtDeMan@715 129 // pause time measurement
BrechtDeMan@715 130 function pauseTimeMeasurement() {
BrechtDeMan@715 131 // UN-PAUSE
BrechtDeMan@715 132 if (measurementPaused) { // already paused
BrechtDeMan@715 133 // button shows 'pause' again
BrechtDeMan@715 134 document.getElementById('pauseButton').innerHTML = 'Pause';
BrechtDeMan@715 135 // toggle state
BrechtDeMan@715 136 measurementPaused = false;
BrechtDeMan@715 137 // resume time measurement
BrechtDeMan@715 138 lastTimeMeasured = new Date().getTime(); // reset time, discard time while paused
BrechtDeMan@715 139 } else { // PAUSE
BrechtDeMan@715 140 // button shows 'resume'
BrechtDeMan@715 141 document.getElementById('pauseButton').innerHTML = 'Resume';
BrechtDeMan@715 142 // toggle state
BrechtDeMan@715 143 measurementPaused = true;
BrechtDeMan@715 144 // pause time measurement
BrechtDeMan@715 145 timeInBuffer = timeSinceLastCall();
BrechtDeMan@715 146 }
BrechtDeMan@715 147 }
BrechtDeMan@715 148
BrechtDeMan@715 149 // show elapsed time on interface
BrechtDeMan@715 150 function showTimeElapsedInSeconds() {
BrechtDeMan@715 151 // if paused: un-pause
BrechtDeMan@715 152 if (measurementPaused) {
BrechtDeMan@715 153 pauseTimeMeasurement();
BrechtDeMan@715 154 }
BrechtDeMan@715 155
BrechtDeMan@715 156 // time of last annotation
BrechtDeMan@715 157 var lastAnnotationTime = timeSinceLastCall()/1000;
BrechtDeMan@715 158 document.getElementById('timeDisplay').innerHTML = lastAnnotationTime.toFixed(2);
BrechtDeMan@715 159 // average time over last ... annotations
BrechtDeMan@715 160 var avgAnnotationTime;
BrechtDeMan@715 161 var numberOfElementsToAverage =
BrechtDeMan@715 162 document.getElementById('numberOfTimeAverages').value;
BrechtDeMan@715 163 if (isPositiveInteger(numberOfElementsToAverage)) {
BrechtDeMan@715 164 avgAnnotationTime =
BrechtDeMan@715 165 calculateAverageTime(lastAnnotationTime,
BrechtDeMan@715 166 Number(numberOfElementsToAverage));
BrechtDeMan@715 167 } else {
BrechtDeMan@715 168 // change text field content to 'ALL'
BrechtDeMan@715 169 document.getElementById('numberOfTimeAverages').value = 'ALL';
BrechtDeMan@715 170 avgAnnotationTime = calculateAverageTime(lastAnnotationTime, -1);
BrechtDeMan@715 171 }
BrechtDeMan@715 172 document.getElementById('timeAverageDisplay').innerHTML = avgAnnotationTime.toFixed(2);
BrechtDeMan@715 173 }
BrechtDeMan@715 174
BrechtDeMan@715 175 // auxiliary function: is string a positive integer?
BrechtDeMan@715 176 // http://stackoverflow.com/questions/10834796/...
BrechtDeMan@715 177 // validate-that-a-string-is-a-positive-integer
BrechtDeMan@715 178 function isPositiveInteger(str) {
BrechtDeMan@715 179 var n = ~~Number(str);
BrechtDeMan@715 180 return String(n) === str && n >= 0;
BrechtDeMan@715 181 }
BrechtDeMan@715 182
BrechtDeMan@715 183 // calculate average time
BrechtDeMan@715 184 function calculateAverageTime(newTimeMeasurementInSeconds,numberOfPoints) {
BrechtDeMan@715 185 // append last measurement time to time array, if significant
BrechtDeMan@715 186 if (newTimeMeasurementInSeconds > MIN_TIME) {
BrechtDeMan@715 187 timeArray.push(newTimeMeasurementInSeconds);
BrechtDeMan@715 188 }
BrechtDeMan@715 189 // average over last N elements of this array
BrechtDeMan@715 190 if (numberOfPoints < 0 || numberOfPoints>=timeArray.length) { // calculate average over all
BrechtDeMan@715 191 var sum = 0;
BrechtDeMan@715 192 for (var i = 0; i < timeArray.length; i++) {
BrechtDeMan@715 193 sum += timeArray[i];
BrechtDeMan@715 194 }
BrechtDeMan@715 195 averageOfTimes = sum/timeArray.length;
BrechtDeMan@715 196 } else { // calculate average over specified number of times measured last
BrechtDeMan@715 197 var sum = 0;
BrechtDeMan@715 198 for (var i = timeArray.length-numberOfPoints; i < timeArray.length; i++) {
BrechtDeMan@715 199 sum += timeArray[i];
BrechtDeMan@715 200 }
BrechtDeMan@715 201 averageOfTimes = sum/numberOfPoints;
BrechtDeMan@715 202 }
BrechtDeMan@715 203 return averageOfTimes;
BrechtDeMan@715 204 }
BrechtDeMan@715 205
BrechtDeMan@715 206
BrechtDeMan@715 207 /********************************
BrechtDeMan@715 208 * PLAYBACK OF AUDIO *
BrechtDeMan@715 209 ********************************/
BrechtDeMan@715 210
BrechtDeMan@715 211 //PLAYaudioelement
BrechtDeMan@715 212 // Keep track of whether audio should be played
BrechtDeMan@715 213 function playFlagChanged(){
BrechtDeMan@715 214 playAudio = playFlag.checked; // global variable
BrechtDeMan@715 215
BrechtDeMan@715 216 if (!playAudio){ // if audio needs to stop
BrechtDeMan@715 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@715 219 }
BrechtDeMan@715 220 }
BrechtDeMan@715 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@715 225 var audio;
BrechtDeMan@715 226
BrechtDeMan@715 227 // Play audioelement of audioholder if available, from start or from same position
BrechtDeMan@715 228 function playaudioelement(audioholderName, audioelementerName){
BrechtDeMan@715 229 if (playAudio) { // if enabled
BrechtDeMan@715 230 // get corresponding file from folder
BrechtDeMan@715 231 var file_location = 'audio/'+audioholderName + '/' + audioelementerName + '.mp3'; // fixed path and file name format
BrechtDeMan@715 232
BrechtDeMan@715 233 // if not available, show error/warning message
BrechtDeMan@715 234 //TODO ...
BrechtDeMan@715 235
BrechtDeMan@715 236 // if nothing playing yet, start playing
BrechtDeMan@715 237 if (currently_playing_audioholder == ''){ // signal that nothing is playing
BrechtDeMan@715 238 //playSound(audioBuffer);
BrechtDeMan@715 239 audio = new Audio(file_location);
BrechtDeMan@715 240 audio.loop = true; // loop when end is reached
BrechtDeMan@715 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@715 246 audio.pause(); // stop audio
BrechtDeMan@715 247 audio = new Audio(file_location); // load new file
BrechtDeMan@715 248 audio.loop = true; // loop when end is reached
BrechtDeMan@715 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@715 254 skipTime = audio.currentTime; // time to skip to
BrechtDeMan@715 255 audio.pause(); // stop audio
BrechtDeMan@715 256 audio = new Audio(file_location);
BrechtDeMan@715 257 audio.addEventListener('loadedmetadata', function() {
BrechtDeMan@715 258 this.currentTime = skipTime;
BrechtDeMan@715 259 console.log('Loaded '+audioholderName+'-'+audioelementerName+', playing from '+skipTime);
BrechtDeMan@715 260 }, false); // skip to same time when audio is loaded!
BrechtDeMan@715 261 audio.loop = true; // loop when end is reached
BrechtDeMan@715 262 audio.play(); // play from that time
BrechtDeMan@715 263 audio.currentTime = skipTime;
BrechtDeMan@715 264 currently_playing_audioholder = audioholderName;
BrechtDeMan@715 265 currently_playing_audioelement = audioelementerName;
BrechtDeMan@715 266 }
BrechtDeMan@715 267 // if same audioelement playing: keep on playing (i.e. do nothing)
BrechtDeMan@715 268 }
BrechtDeMan@715 269 }
BrechtDeMan@715 270
BrechtDeMan@715 271 /********************
BrechtDeMan@715 272 * READING FILES *
BrechtDeMan@715 273 ********************/
BrechtDeMan@715 274
BrechtDeMan@715 275 // Read necessary data from XML file
BrechtDeMan@715 276 function readXML(xmlFileName){
BrechtDeMan@715 277 if (window.XMLHttpRequest)
BrechtDeMan@715 278 {// code for IE7+, Firefox, Chrome, Opera, Safari
BrechtDeMan@715 279 xmlhttp=new XMLHttpRequest();
BrechtDeMan@715 280 }
BrechtDeMan@715 281 else
BrechtDeMan@715 282 {// code for IE6, IE5
BrechtDeMan@715 283 xmlhttp=new ActiveXObject("Microsoft.XMLHTTP");
BrechtDeMan@715 284 }
BrechtDeMan@715 285 xmlhttp.open("GET",xmlFileName,false);
BrechtDeMan@715 286 xmlhttp.send();
BrechtDeMan@715 287 return xmlhttp.responseXML;
BrechtDeMan@715 288 }
BrechtDeMan@715 289
BrechtDeMan@715 290 // go over all files and compute relevant statistics
BrechtDeMan@715 291 function loadAllFiles() {
BrechtDeMan@715 292 // retrieve information from XMLs
BrechtDeMan@715 293
BrechtDeMan@715 294 for (fileIndex = 0; fileIndex < xmlFiles.length; fileIndex++) {
BrechtDeMan@715 295 xmlFileName = xmlFileFolder+"/"+xmlFiles[fileIndex];
BrechtDeMan@715 296 xml = readXML(xmlFileName);
BrechtDeMan@715 297 if (xml != null) { // if file exists
BrechtDeMan@715 298 // append file name to array of file names
BrechtDeMan@715 299 fileNameArray.push(xmlFiles[fileIndex]);
BrechtDeMan@715 300
BrechtDeMan@715 301 // get root of XML file
BrechtDeMan@715 302 root = xml.getElementsByTagName('browserevaluationresult')[0];
BrechtDeMan@715 303
BrechtDeMan@715 304 // get subject ID, add to array if not already there
BrechtDeMan@715 305 pretest = root.getElementsByTagName('pretest')[0];
BrechtDeMan@715 306 subjectID = pretest.getElementsByTagName('comment')[0];
BrechtDeMan@715 307 if (subjectID.getAttribute('id')!='sessionId') { // warning in console when not available
BrechtDeMan@715 308 console.log(xmlFiles[fileIndex]+': no SessionID available');
BrechtDeMan@715 309 }
BrechtDeMan@715 310 if (subjectArray.indexOf(subjectID.textContent) == -1) { // if not already in array
BrechtDeMan@715 311 subjectArray.push(subjectID.textContent); // append to array
BrechtDeMan@715 312 }
BrechtDeMan@715 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@715 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@715 328 }
BrechtDeMan@715 329 }
BrechtDeMan@715 330 }
BrechtDeMan@715 331 // count occurrences of each audioholder
BrechtDeMan@715 332 // ...
BrechtDeMan@715 333 }
BrechtDeMan@715 334 else {
BrechtDeMan@715 335 console.log('XML file '+xmlFileName+' not found.');
BrechtDeMan@715 336 }
BrechtDeMan@715 337 }
BrechtDeMan@715 338
BrechtDeMan@715 339 // sort alphabetically
BrechtDeMan@715 340 fileNameArray.sort();
BrechtDeMan@715 341 subjectArray.sort();
BrechtDeMan@715 342 audioholderArray.sort();
BrechtDeMan@715 343 audioelementArray.sort();
BrechtDeMan@715 344
BrechtDeMan@715 345 // display all information in HTML
BrechtDeMan@715 346 // show XML file folder
BrechtDeMan@715 347 document.getElementById('xmlFileFolder_span').innerHTML = "\""+xmlFileFolder+"/\"";
BrechtDeMan@715 348 // show number of files
BrechtDeMan@715 349 document.getElementById('numberOfFiles_span').innerHTML = fileNameArray.length;
BrechtDeMan@715 350 // show list of subject names
BrechtDeMan@715 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@715 356 }
BrechtDeMan@715 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@715 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@715 365 ratings.push([]);
BrechtDeMan@715 366 for (audioelementIndex = 0; audioelementIndex < audioelementArray.length; audioelementIndex++) {
BrechtDeMan@715 367 ratings[audioholderIndex].push([]);
BrechtDeMan@715 368 }
BrechtDeMan@715 369 }
BrechtDeMan@715 370
BrechtDeMan@715 371 // go over all XML files
BrechtDeMan@715 372 for (fileIndex = 0; fileIndex < xmlFiles.length; fileIndex++) {
BrechtDeMan@715 373 xmlFileName = xmlFileFolder+"/"+xmlFiles[fileIndex];
BrechtDeMan@715 374 xml = readXML(xmlFileName);
BrechtDeMan@715 375 if (xml != null) { // if file exists
BrechtDeMan@715 376 // get root of XML file
BrechtDeMan@715 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@715 383 // go over all audioelements
BrechtDeMan@715 384 for (audioelementIndex = 0; audioelementIndex < audioelementNodes.length; audioelementIndex++) {
BrechtDeMan@715 385 audioelementName = audioelementNodes[audioelementIndex].getAttribute('id');
BrechtDeMan@715 386 // get value
BrechtDeMan@715 387 var value = audioelementNodes[audioelementIndex].getElementsByTagName("value")[0].textContent;
BrechtDeMan@715 388 if (value) { // if not empty, null, undefined...
BrechtDeMan@715 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@715 394 }
BrechtDeMan@715 395 }
BrechtDeMan@715 396 }
BrechtDeMan@715 397
BrechtDeMan@715 398 // go over all audioholders
BrechtDeMan@715 399
BrechtDeMan@715 400 // go over all audioelements within audioholder, see if present in idMatrix, add if not
BrechtDeMan@715 401 // add corresponding rating to 'ratings', at position corresponding with position in idMatrix
BrechtDeMan@715 402 }
BrechtDeMan@715 403 }
BrechtDeMan@715 404
BrechtDeMan@715 405 for (audioholderIndex = 0; audioholderIndex < audioholderArray.length; audioholderIndex++) {
BrechtDeMan@715 406 audioholderName = audioholderArray[audioholderIndex]; // for this song
BrechtDeMan@715 407 tickArray = []
BrechtDeMan@715 408
BrechtDeMan@715 409 raw_data = [['SubjectID', 'Rating']];
BrechtDeMan@715 410 audioElIdx = 0;
BrechtDeMan@715 411 for (audioelementIndex = 0; audioelementIndex<ratings[audioholderIndex].length; audioelementIndex++){
BrechtDeMan@715 412 if (ratings[audioholderIndex][audioelementIndex].length>0) {
BrechtDeMan@715 413 audioElIdx++; // increase if not empty
BrechtDeMan@715 414 // make tick label
BrechtDeMan@715 415 tickArray.push({v:audioElIdx, f: audioelementArray[audioelementIndex]});
BrechtDeMan@715 416 }
BrechtDeMan@715 417 for (subject = 0; subject<ratings[audioholderIndex][audioelementIndex].length; subject++){
BrechtDeMan@715 418 // add subject-value pair for each subject
BrechtDeMan@715 419 raw_data.push([audioElIdx, ratings[audioholderIndex][audioelementIndex][subject]]);
BrechtDeMan@715 420 }
BrechtDeMan@715 421 }
BrechtDeMan@715 422
BrechtDeMan@715 423 // create plot (one per song)
BrechtDeMan@715 424 var data = google.visualization.arrayToDataTable(raw_data);
BrechtDeMan@715 425
BrechtDeMan@715 426 var options = {
BrechtDeMan@715 427 title: audioholderName,
BrechtDeMan@715 428 hAxis: {title: 'audioelement ID', minValue: 0, maxValue: audioElIdx+1,
BrechtDeMan@715 429 ticks: tickArray},
BrechtDeMan@715 430 vAxis: {title: 'Rating', minValue: 0, maxValue: 1},
BrechtDeMan@715 431 seriesType: 'scatter',
BrechtDeMan@715 432 legend: 'none'
BrechtDeMan@715 433 };
BrechtDeMan@715 434 var div = document.createElement('div');
BrechtDeMan@715 435 document.body.appendChild(div);
BrechtDeMan@715 436 div.id = 'div_'+audioholderName;
BrechtDeMan@715 437 div.style.width = '1100px';
BrechtDeMan@715 438 div.style.height = '350px';
BrechtDeMan@715 439 var chart = new google.visualization.ComboChart(document.getElementById('div_'+audioholderName));
BrechtDeMan@715 440 chart.draw(data, options);
BrechtDeMan@715 441
BrechtDeMan@715 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@715 581 }
BrechtDeMan@715 582 }
BrechtDeMan@715 583
BrechtDeMan@715 584 </script>
BrechtDeMan@715 585
BrechtDeMan@715 586
BrechtDeMan@715 587
BrechtDeMan@715 588 <style>
BrechtDeMan@715 589 div {
BrechtDeMan@715 590 padding: 2px;
BrechtDeMan@715 591 margin-top: 2px;
BrechtDeMan@715 592 margin-bottom: 2px;
BrechtDeMan@715 593 }
BrechtDeMan@715 594 div.head{
BrechtDeMan@715 595 margin-left: 10px;
BrechtDeMan@715 596 border: black;
BrechtDeMan@715 597 border-width: 2px;
BrechtDeMan@715 598 border-style: solid;
BrechtDeMan@715 599 }
BrechtDeMan@715 600 div.attrib{
BrechtDeMan@715 601 margin-left:25px;
BrechtDeMan@715 602 border: black;
BrechtDeMan@715 603 border-width: 2px;
BrechtDeMan@715 604 border-style: dashed;
BrechtDeMan@715 605 margin-bottom: 10px;
BrechtDeMan@715 606 }
BrechtDeMan@715 607 div#headerMatter{
BrechtDeMan@715 608 background-color: #FFFFCC;
BrechtDeMan@715 609 }
BrechtDeMan@715 610 div#currentStatement{
BrechtDeMan@715 611 font-size:3.0em;
BrechtDeMan@715 612 font-weight: bold;
BrechtDeMan@715 613
BrechtDeMan@715 614 }
BrechtDeMan@715 615 div#debugDisplay {
BrechtDeMan@715 616 color: #CCCCCC;
BrechtDeMan@715 617 font-size:0.3em;
BrechtDeMan@715 618 }
BrechtDeMan@715 619 span#scoreDisplay {
BrechtDeMan@715 620 font-weight: bold;
BrechtDeMan@715 621 }
BrechtDeMan@715 622 div#wrapper {
BrechtDeMan@715 623 width: 780px;
BrechtDeMan@715 624 border: 1px solid black;
BrechtDeMan@715 625 overflow: hidden; /* add this to contain floated children */
BrechtDeMan@715 626 }
BrechtDeMan@715 627 div#instrumentSection {
BrechtDeMan@715 628 width: 250px;
BrechtDeMan@715 629 border: 1px solid red;
BrechtDeMan@715 630 display: inline-block;
BrechtDeMan@715 631 }
BrechtDeMan@715 632 div#featureSection {
BrechtDeMan@715 633 width: 250px;
BrechtDeMan@715 634 border: 1px solid green;
BrechtDeMan@715 635 display: inline-block;
BrechtDeMan@715 636 }
BrechtDeMan@715 637 div#valenceSection {
BrechtDeMan@715 638 width: 250px;
BrechtDeMan@715 639 border: 1px solid blue;
BrechtDeMan@715 640 display: inline-block;
BrechtDeMan@715 641 }
BrechtDeMan@715 642 button#previousComment{
BrechtDeMan@715 643 width: 120px;
BrechtDeMan@715 644 height: 150px;
BrechtDeMan@715 645 font-size:1.5em;
BrechtDeMan@715 646 }
BrechtDeMan@715 647 button#nextComment{
BrechtDeMan@715 648 width: 666px;
BrechtDeMan@715 649 height: 150px;
BrechtDeMan@715 650 font-size:1.5em;
BrechtDeMan@715 651 }
BrechtDeMan@715 652 ul
BrechtDeMan@715 653 {
BrechtDeMan@715 654 list-style-type: none; /* no bullet points */
BrechtDeMan@715 655 margin-left: -20px; /* less indent */
BrechtDeMan@715 656 margin-top: 0px;
BrechtDeMan@715 657 margin-bottom: 5px;
BrechtDeMan@715 658 }
BrechtDeMan@715 659 </style>
BrechtDeMan@715 660
BrechtDeMan@715 661 </head>
BrechtDeMan@715 662
BrechtDeMan@715 663 <body>
BrechtDeMan@715 664 <h1>Subjective evaluation results</h1>
BrechtDeMan@715 665
BrechtDeMan@715 666 <div id="debugDisplay">
BrechtDeMan@715 667 XML file folder: <span id="xmlFileFolder_span"></span>
BrechtDeMan@715 668 </div>
BrechtDeMan@715 669
BrechtDeMan@715 670 <div id="headerMatter">
BrechtDeMan@715 671 <div>
BrechtDeMan@715 672 <strong>Result XML files:</strong> <span id="numberOfFiles_span"></span>
BrechtDeMan@715 673 </div>
BrechtDeMan@715 674 <div>
BrechtDeMan@715 675 <strong>Audioholders in dataset:</strong> <span id="audioholderArray_span"></span>
BrechtDeMan@715 676 </div>
BrechtDeMan@715 677 <div>
BrechtDeMan@715 678 <strong>Subjects in dataset:</strong> <span id="subjectArray_span"></span>
BrechtDeMan@715 679 </div>
BrechtDeMan@715 680 <div>
BrechtDeMan@715 681 <strong>Audioelements in dataset:</strong> <span id="audioelementArray_span"></span>
BrechtDeMan@715 682 </div>
BrechtDeMan@715 683 <br>
BrechtDeMan@715 684 </div>
BrechtDeMan@715 685 <br>
BrechtDeMan@715 686
BrechtDeMan@715 687 <!-- Show time elapsed
BrechtDeMan@715 688 The last annotation took <strong><span id="timeDisplay">(N/A)</span></strong> seconds.
BrechtDeMan@715 689 <br>-->
BrechtDeMan@715 690
BrechtDeMan@715 691 </body>
BrechtDeMan@715 692 </html>