Mercurial > hg > webaudioevaluationtool
comparison analyse.html @ 336:378726f0ac91 WAC2016
Paper: Added interface screenshot and box plot example
author | Brecht De Man <b.deman@qmul.ac.uk> |
---|---|
date | Thu, 15 Oct 2015 20:10:00 +0100 |
parents | 5f27d3eb93fe |
children | de9a0a740b6e |
comparison
equal
deleted
inserted
replaced
335:c1b548fbb87c | 336:378726f0ac91 |
---|---|
16 // To aid 'one-page set-up' all scripts and CSS must be included directly in this file! | 16 // To aid 'one-page set-up' all scripts and CSS must be included directly in this file! |
17 | 17 |
18 google.load("visualization", "1", {packages:["corechart"]}); | 18 google.load("visualization", "1", {packages:["corechart"]}); |
19 | 19 |
20 /************* | 20 /************* |
21 * SETUP * | 21 * SETUP * |
22 *************/ | 22 *************/ |
23 // folder where to find the XML files | 23 // folder where to find the XML files |
24 xmlFileFolder = "saves"; | 24 xmlFileFolder = "analysis_test"; |
25 // array of XML files | 25 // array of XML files |
26 var xmlFiles = ['McG-A-2014-03.xml','McG-B-2014-03.xml','McG-C-2014-03.xml']; | 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']; |
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']; | |
27 | 28 |
28 //TODO: make retrieval of file names automatic / drag files on here | 29 //TODO: make retrieval of file names automatic / drag files on here |
29 | 30 |
30 /**************** | 31 /**************** |
31 * VARIABLES * | 32 * VARIABLES * |
32 ****************/ | 33 ****************/ |
33 | 34 |
34 // Counters | 35 // Counters |
35 // How many files, audioHolders, audioElementes and statements annotated (don't count current one) | 36 // How many files, audioholders, audioelementes and statements annotated (don't count current one) |
36 var numberOfFiles = -1; | 37 var numberOfFiles = -1; |
37 var numberOfaudioHolders = -1; | 38 var numberOfaudioholders = -1; |
38 var numberOfaudioElementes = -1; | 39 var numberOfaudioelementes = -1; |
39 var numberOfStatements = -1; | 40 var numberOfStatements = -1; |
40 var numberOfSkippedComments = 0; | 41 var numberOfSkippedComments = 0; |
41 | 42 |
42 // Object arrays | 43 // Object arrays |
43 var fileNameArray = []; | 44 var fileNameArray = []; |
44 var subjectArray = []; | 45 var subjectArray = []; |
45 var audioHolderArray = []; | 46 var audioholderArray = []; |
46 var audioElementArray = []; | 47 var audioelementArray = []; |
47 | 48 |
48 // End of (file, audioholder, audioelement) flags | 49 // End of (file, audioholder, audioelement) flags |
49 var newFile = true; | 50 var newFile = true; |
50 var newAudioHolder = true; | 51 var newAudioHolder = true; |
51 var newAudioElement = true; | 52 var newAudioElement = true; |
52 | 53 |
53 var fileCounter = 0; // file index | 54 var fileCounter = 0; // file index |
54 var audioHolderCounter=0; // audioholder index (current XML file) | 55 var audioholderCounter=0; // audioholder index (current XML file) |
55 var audioElementCounter=0; // audioelement index (current audioholder) | 56 var audioelementCounter=0; // audioelement index (current audioholder) |
56 var statementNumber=0; // total number of statements | 57 var statementNumber=0; // total number of statements |
57 | 58 |
58 var root; // root of XML file | 59 var root; // root of XML file |
59 var commentInFull = ''; // full comment | 60 var commentInFull = ''; // full comment |
60 | 61 |
90 } | 91 } |
91 throw message; // Fallback | 92 throw message; // Fallback |
92 } | 93 } |
93 } | 94 } |
94 | 95 |
95 function median(values) { | 96 function median(values) { // TODO: replace code by '50th percentile' - should be the same? |
96 values.sort( function(a,b) {return a - b;} ); | 97 values.sort( function(a,b) {return a - b;} ); |
97 var half = Math.floor(values.length/2); | 98 var half = Math.floor(values.length/2); |
98 if(values.length % 2) | 99 if(values.length % 2) |
99 return values[half]; | 100 return values[half]; |
100 else | 101 else |
101 return (values[half-1] + values[half]) / 2.0; | 102 return (values[half-1] + values[half]) / 2.0; |
102 } | 103 } |
104 | |
105 function percentile(values, n) { | |
106 values.sort( function(a,b) {return a - b;} ); | |
107 // get ordinal rank | |
108 var rank = Math.min(Math.floor(values.length*n/100), values.length-1); | |
109 return values[rank]; | |
110 } | |
103 | 111 |
104 /*********************** | 112 /*********************** |
105 * TIME MEASUREMENT * | 113 * TIME MEASUREMENT * |
106 ************************/ | 114 ************************/ |
107 | 115 |
108 // measure time since last time this function was called | 116 // measure time since last time this function was called |
109 function timeSinceLastCall() { | 117 function timeSinceLastCall() { |
110 // current time | 118 // current time |
195 return averageOfTimes; | 203 return averageOfTimes; |
196 } | 204 } |
197 | 205 |
198 | 206 |
199 /******************************** | 207 /******************************** |
200 * PLAYBACK OF AUDIO * | 208 * PLAYBACK OF AUDIO * |
201 ********************************/ | 209 ********************************/ |
202 | 210 |
203 //PLAYaudioElement | 211 //PLAYaudioelement |
204 // Keep track of whether audio should be played | 212 // Keep track of whether audio should be played |
205 function playFlagChanged(){ | 213 function playFlagChanged(){ |
206 playAudio = playFlag.checked; // global variable | 214 playAudio = playFlag.checked; // global variable |
207 | 215 |
208 if (!playAudio){ // if audio needs to stop | 216 if (!playAudio){ // if audio needs to stop |
209 audio.pause(); // stop audio - if anything is playing | 217 audio.pause(); // stop audio - if anything is playing |
210 currently_playing = ''; // back to empty string so playaudioElement knows nothing's playing | 218 currently_playing = ''; // back to empty string so playaudioelement knows nothing's playing |
211 } | 219 } |
212 } | 220 } |
213 | 221 |
214 // audioHolder that's currently playing | 222 // audioholder that's currently playing |
215 var currently_playing_audioHolder = ''; // at first: empty string | 223 var currently_playing_audioholder = ''; // at first: empty string |
216 var currently_playing_audioElement = ''; | 224 var currently_playing_audioelement = ''; |
217 var audio; | 225 var audio; |
218 | 226 |
219 // Play audioElement of audioHolder if available, from start or from same position | 227 // Play audioelement of audioholder if available, from start or from same position |
220 function playaudioElement(audioHolderName, audioElementerName){ | 228 function playaudioelement(audioholderName, audioelementerName){ |
221 if (playAudio) { // if enabled | 229 if (playAudio) { // if enabled |
222 // get corresponding file from folder | 230 // get corresponding file from folder |
223 var file_location = 'audio/'+audioHolderName + '/' + audioElementerName + '.mp3'; // fixed path and file name format | 231 var file_location = 'audio/'+audioholderName + '/' + audioelementerName + '.mp3'; // fixed path and file name format |
224 | 232 |
225 // if not available, show error/warning message | 233 // if not available, show error/warning message |
226 //TODO ... | 234 //TODO ... |
227 | 235 |
228 // if nothing playing yet, start playing | 236 // if nothing playing yet, start playing |
229 if (currently_playing_audioHolder == ''){ // signal that nothing is playing | 237 if (currently_playing_audioholder == ''){ // signal that nothing is playing |
230 //playSound(audioBuffer); | 238 //playSound(audioBuffer); |
231 audio = new Audio(file_location); | 239 audio = new Audio(file_location); |
232 audio.loop = true; // loop when end is reached | 240 audio.loop = true; // loop when end is reached |
233 audio.play(); | 241 audio.play(); |
234 currently_playing_audioHolder = audioHolderName; | 242 currently_playing_audioholder = audioholderName; |
235 currently_playing_audioElement = audioElementerName; | 243 currently_playing_audioelement = audioelementerName; |
236 } else if (currently_playing_audioHolder != audioHolderName) { | 244 } else if (currently_playing_audioholder != audioholderName) { |
237 // if different audioHolder playing, stop that and start playing | 245 // if different audioholder playing, stop that and start playing |
238 audio.pause(); // stop audio | 246 audio.pause(); // stop audio |
239 audio = new Audio(file_location); // load new file | 247 audio = new Audio(file_location); // load new file |
240 audio.loop = true; // loop when end is reached | 248 audio.loop = true; // loop when end is reached |
241 audio.play(); // play audio from the start | 249 audio.play(); // play audio from the start |
242 currently_playing_audioHolder = audioHolderName; | 250 currently_playing_audioholder = audioholderName; |
243 currently_playing_audioElement = audioElementerName; | 251 currently_playing_audioelement = audioelementerName; |
244 } else if (currently_playing_audioElement != audioElementerName) { | 252 } else if (currently_playing_audioelement != audioelementerName) { |
245 // if same audioHolder playing, start playing from where it left off | 253 // if same audioholder playing, start playing from where it left off |
246 skipTime = audio.currentTime; // time to skip to | 254 skipTime = audio.currentTime; // time to skip to |
247 audio.pause(); // stop audio | 255 audio.pause(); // stop audio |
248 audio = new Audio(file_location); | 256 audio = new Audio(file_location); |
249 audio.addEventListener('loadedmetadata', function() { | 257 audio.addEventListener('loadedmetadata', function() { |
250 this.currentTime = skipTime; | 258 this.currentTime = skipTime; |
251 console.log('Loaded '+audioHolderName+'-'+audioElementerName+', playing from '+skipTime); | 259 console.log('Loaded '+audioholderName+'-'+audioelementerName+', playing from '+skipTime); |
252 }, false); // skip to same time when audio is loaded! | 260 }, false); // skip to same time when audio is loaded! |
253 audio.loop = true; // loop when end is reached | 261 audio.loop = true; // loop when end is reached |
254 audio.play(); // play from that time | 262 audio.play(); // play from that time |
255 audio.currentTime = skipTime; | 263 audio.currentTime = skipTime; |
256 currently_playing_audioHolder = audioHolderName; | 264 currently_playing_audioholder = audioholderName; |
257 currently_playing_audioElement = audioElementerName; | 265 currently_playing_audioelement = audioelementerName; |
258 } | 266 } |
259 // if same audioElement playing: keep on playing (i.e. do nothing) | 267 // if same audioelement playing: keep on playing (i.e. do nothing) |
260 } | 268 } |
261 } | 269 } |
262 | 270 |
263 /******************** | 271 /******************** |
264 * READING FILES * | 272 * READING FILES * |
265 ********************/ | 273 ********************/ |
266 | 274 |
267 // Read necessary data from XML file | 275 // Read necessary data from XML file |
268 function readXML(xmlFileName){ | 276 function readXML(xmlFileName){ |
269 if (window.XMLHttpRequest) | 277 if (window.XMLHttpRequest) |
301 } | 309 } |
302 if (subjectArray.indexOf(subjectID.textContent) == -1) { // if not already in array | 310 if (subjectArray.indexOf(subjectID.textContent) == -1) { // if not already in array |
303 subjectArray.push(subjectID.textContent); // append to array | 311 subjectArray.push(subjectID.textContent); // append to array |
304 } | 312 } |
305 | 313 |
306 // go over all audioHolders, add to array if not already there | 314 // go over all audioholders, add to array if not already there |
307 audioHolderNodes = root.getElementsByTagName('audioholder'); | 315 audioholderNodes = root.getElementsByTagName('audioholder'); |
308 // go over audioHolderNodes and append audioHolder name when not present yet | 316 // go over audioholderNodes and append audioholder name when not present yet |
309 for (audioHolderIndex = 0; audioHolderIndex < audioHolderNodes.length; audioHolderIndex++) { | 317 for (audioholderIndex = 0; audioholderIndex < audioholderNodes.length; audioholderIndex++) { |
310 audioHolderName = audioHolderNodes[audioHolderIndex].getAttribute('id'); | 318 audioholderName = audioholderNodes[audioholderIndex].getAttribute('id'); |
311 if (audioHolderArray.indexOf(audioHolderName) == -1) { // if not already in array | 319 if (audioholderArray.indexOf(audioholderName) == -1) { // if not already in array |
312 audioHolderArray.push(audioHolderName); // append to array | 320 audioholderArray.push(audioholderName); // append to array |
313 } | 321 } |
314 // within each audioHolder, go over all audioElement IDs, add to array if not already there | 322 // within each audioholder, go over all audioelement IDs, add to array if not already there |
315 audioElementNodes = audioHolderNodes[audioHolderIndex].getElementsByTagName('audioelement'); | 323 audioelementNodes = audioholderNodes[audioholderIndex].getElementsByTagName('audioelement'); |
316 for (audioElementIndex = 0; audioElementIndex < audioElementNodes.length; audioElementIndex++) { | 324 for (audioelementIndex = 0; audioelementIndex < audioelementNodes.length; audioelementIndex++) { |
317 audioElementName = audioElementNodes[audioElementIndex].getAttribute('id'); | 325 audioelementName = audioelementNodes[audioelementIndex].getAttribute('id'); |
318 if (audioElementArray.indexOf(audioElementName) == -1) { // if not already in array | 326 if (audioelementArray.indexOf(audioelementName) == -1) { // if not already in array |
319 audioElementArray.push(audioElementName); // append to array | 327 audioelementArray.push(audioelementName); // append to array |
320 } | 328 } |
321 } | 329 } |
322 } | 330 } |
323 // count occurrences of each audioHolder | 331 // count occurrences of each audioholder |
324 // ... | 332 // ... |
325 } | 333 } |
326 else { | 334 else { |
327 console.log('XML file '+xmlFileName+' not found.'); | 335 console.log('XML file '+xmlFileName+' not found.'); |
328 } | 336 } |
329 } | 337 } |
330 | 338 |
331 // sort alphabetically | 339 // sort alphabetically |
332 fileNameArray.sort(); | 340 fileNameArray.sort(); |
333 subjectArray.sort(); | 341 subjectArray.sort(); |
334 audioHolderArray.sort(); | 342 audioholderArray.sort(); |
335 audioElementArray.sort(); | 343 audioelementArray.sort(); |
336 | 344 |
337 // display all information in HTML | 345 // display all information in HTML |
338 // show XML file folder | 346 // show XML file folder |
339 document.getElementById('xmlFileFolder_span').innerHTML = "\""+xmlFileFolder+"/\""; | 347 document.getElementById('xmlFileFolder_span').innerHTML = "\""+xmlFileFolder+"/\""; |
340 // show number of files | 348 // show number of files |
341 document.getElementById('numberOfFiles_span').innerHTML = fileNameArray.length; | 349 document.getElementById('numberOfFiles_span').innerHTML = fileNameArray.length; |
342 // show list of subject names | 350 // show list of subject names |
343 document.getElementById('subjectArray_span').innerHTML = subjectArray.toString(); | 351 document.getElementById('subjectArray_span').innerHTML = subjectArray.toString(); |
344 // show list of audioHolders | 352 // show list of audioholders |
345 document.getElementById('audioHolderArray_span').innerHTML = audioHolderArray.toString(); | 353 document.getElementById('audioholderArray_span').innerHTML = audioholderArray.toString(); |
346 // show list of audioElementes | 354 // show list of audioelementes |
347 document.getElementById('audioElementArray_span').innerHTML = audioElementArray.toString(); | 355 document.getElementById('audioelementArray_span').innerHTML = audioelementArray.toString(); |
348 } | 356 } |
349 | 357 |
350 function makePlots() { | 358 function makePlots() { //TODO: split into different functions |
359 // TEMPORARY | |
360 makeTimeline(xmlFileFolder+"/"+xmlFiles[7]); | |
361 | |
351 // create value array | 362 // create value array |
352 var ratings = []; // 3D matrix of ratings (audioHolder, audioElement, subject) | 363 var ratings = []; // 3D matrix of ratings (audioholder, audioelement, subject) |
353 for (audioHolderIndex = 0; audioHolderIndex < audioHolderNodes.length; audioHolderIndex++) { | 364 for (audioholderIndex = 0; audioholderIndex < audioholderArray.length; audioholderIndex++) { |
354 ratings.push([]); | 365 ratings.push([]); |
355 for (audioElementIndex = 0; audioElementIndex < audioElementNodes.length; audioElementIndex++) { | 366 for (audioelementIndex = 0; audioelementIndex < audioelementArray.length; audioelementIndex++) { |
356 ratings[audioHolderIndex].push([]); | 367 ratings[audioholderIndex].push([]); |
357 } | 368 } |
358 } | 369 } |
359 | 370 |
360 // go over all XML files | 371 // go over all XML files |
361 for (fileIndex = 0; fileIndex < xmlFiles.length; fileIndex++) { | 372 for (fileIndex = 0; fileIndex < xmlFiles.length; fileIndex++) { |
362 xmlFileName = xmlFileFolder+"/"+xmlFiles[fileIndex]; | 373 xmlFileName = xmlFileFolder+"/"+xmlFiles[fileIndex]; |
363 xml = readXML(xmlFileName); | 374 xml = readXML(xmlFileName); |
364 if (xml != null) { // if file exists | 375 if (xml != null) { // if file exists |
365 // get root of XML file | 376 // get root of XML file |
366 root = xml.getElementsByTagName('browserevaluationresult')[0]; | 377 root = xml.getElementsByTagName('browserevaluationresult')[0]; |
367 // go over all audioHolders | 378 // go over all audioholders |
368 audioHolderNodes = root.getElementsByTagName('audioholder'); | 379 audioholderNodes = root.getElementsByTagName('audioholder'); |
369 for (audioHolderIndex = 0; audioHolderIndex < audioHolderNodes.length; audioHolderIndex++) { | 380 for (audioholderIndex = 0; audioholderIndex < audioholderNodes.length; audioholderIndex++) { |
370 audioHolderName = audioHolderNodes[audioHolderIndex].getAttribute('id'); | 381 audioholderName = audioholderNodes[audioholderIndex].getAttribute('id'); |
371 audioElementNodes = audioHolderNodes[audioHolderIndex].getElementsByTagName('audioelement'); | 382 audioelementNodes = audioholderNodes[audioholderIndex].getElementsByTagName('audioelement'); |
372 // go over all audioelements | 383 // go over all audioelements |
373 for (audioElementIndex = 0; audioElementIndex < audioElementNodes.length; audioElementIndex++) { | 384 for (audioelementIndex = 0; audioelementIndex < audioelementNodes.length; audioelementIndex++) { |
374 audioElementName = audioElementNodes[audioElementIndex].getAttribute('id'); | 385 audioelementName = audioelementNodes[audioelementIndex].getAttribute('id'); |
375 // get value | 386 // get value |
376 var value = audioElementNodes[audioElementIndex].getElementsByTagName("value")[0].textContent; | 387 var value = audioelementNodes[audioelementIndex].getElementsByTagName("value")[0].textContent; |
377 if (value) { // if not empty, null, undefined... | 388 if (value) { // if not empty, null, undefined... |
378 ratingValue = parseFloat(value); | 389 ratingValue = parseFloat(value); |
379 // add to matrix | 390 // add to matrix at proper position |
380 ratings[audioHolderIndex][audioElementIndex].push(ratingValue) | 391 aHidx = audioholderArray.indexOf(audioholderName); |
392 aEidx = audioelementArray.indexOf(audioelementName); | |
393 ratings[aHidx][aEidx].push(ratingValue); | |
381 } | 394 } |
382 } | 395 } |
383 } | 396 } |
384 | 397 |
385 // go over all audioHolders | 398 // go over all audioholders |
386 | 399 |
387 // go over all audioElements within audioHolder, see if present in idMatrix, add if not | 400 // go over all audioelements within audioholder, see if present in idMatrix, add if not |
388 // add corresponding rating to 'ratings', at position corresponding with position in idMatrix | 401 // add corresponding rating to 'ratings', at position corresponding with position in idMatrix |
389 } | 402 } |
390 } | 403 } |
391 | 404 |
392 for (audioHolderIndex = 0; audioHolderIndex < audioHolderArray.length; audioHolderIndex++) { | 405 for (audioholderIndex = 0; audioholderIndex < audioholderArray.length; audioholderIndex++) { |
393 audioHolderName = audioHolderArray[audioHolderIndex]; // for this song | 406 audioholderName = audioholderArray[audioholderIndex]; // for this song |
394 tickArray = [] | 407 tickArray = [] |
395 medianOfAudioElement = [] | |
396 | 408 |
397 raw_data = [['SubjectID', 'Rating']]; | 409 raw_data = [['SubjectID', 'Rating']]; |
398 audioElIdx = 0; | 410 audioElIdx = 0; |
399 for (audioElementIndex = 0; audioElementIndex<ratings[audioHolderIndex].length; audioElementIndex++){ | 411 for (audioelementIndex = 0; audioelementIndex<ratings[audioholderIndex].length; audioelementIndex++){ |
400 if (ratings[audioHolderIndex][audioElementIndex].length>0) { | 412 if (ratings[audioholderIndex][audioelementIndex].length>0) { |
401 audioElIdx++; // increase if not empty | 413 audioElIdx++; // increase if not empty |
402 // make tick label | 414 // make tick label |
403 tickArray.push({v:audioElIdx, f: audioElementArray[audioElementIndex]}); | 415 tickArray.push({v:audioElIdx, f: audioelementArray[audioelementIndex]}); |
404 // add median | 416 } |
405 medianOfAudioElement.push(median(ratings[audioHolderIndex][audioElementIndex])); | 417 for (subject = 0; subject<ratings[audioholderIndex][audioelementIndex].length; subject++){ |
406 } | |
407 for (subject = 0; subject<ratings[audioHolderIndex][audioElementIndex].length; subject++){ | |
408 // add subject-value pair for each subject | 418 // add subject-value pair for each subject |
409 raw_data.push([audioElIdx, ratings[audioHolderIndex][audioElementIndex][subject]]); | 419 raw_data.push([audioElIdx, ratings[audioholderIndex][audioelementIndex][subject]]); |
410 } | 420 } |
411 } | 421 } |
412 | 422 |
413 // create plot (one per song) | 423 // create plot (one per song) |
414 var data = google.visualization.arrayToDataTable(raw_data); | 424 var data = google.visualization.arrayToDataTable(raw_data); |
415 | 425 |
416 var options = { | 426 var options = { |
417 title: audioHolderName, | 427 title: audioholderName, |
418 hAxis: {title: 'Subject', minValue: 0, maxValue: audioElIdx+1, | 428 hAxis: {title: 'audioelement ID', minValue: 0, maxValue: audioElIdx+1, |
419 ticks: tickArray}, | 429 ticks: tickArray}, |
420 vAxis: {title: 'Rating', minValue: 0, maxValue: 1}, | 430 vAxis: {title: 'Rating', minValue: 0, maxValue: 1}, |
421 seriesType: 'scatter', | 431 seriesType: 'scatter', |
422 legend: 'none' | 432 legend: 'none' |
423 }; | 433 }; |
424 var div = document.createElement('div'); | 434 var div = document.createElement('div'); |
425 document.body.appendChild(div); | 435 document.body.appendChild(div); |
426 div.id = 'div_'+audioHolderName; | 436 div.id = 'div_'+audioholderName; |
427 div.style.width = '1100px'; | 437 div.style.width = '1100px'; |
428 div.style.height = '350px'; | 438 div.style.height = '350px'; |
429 var chart = new google.visualization.ComboChart(document.getElementById('div_'+audioHolderName)); | 439 var chart = new google.visualization.ComboChart(document.getElementById('div_'+audioholderName)); |
430 chart.draw(data, options); | 440 chart.draw(data, options); |
431 | 441 |
432 // box plots | 442 // box plots |
433 // function drawVisualization() { | 443 var div = document.createElement('div'); |
434 // // Create and populate the data table. | 444 document.body.appendChild(div); |
435 // var data = google.visualization.arrayToDataTable([ | 445 div.id = 'div_box_'+audioholderName; |
436 // ['ID', 'IQR', '', '', '', 'Median', 'Average'], | 446 div.style.width = '1100px'; |
437 // ['Serie1', 20, 28, 38, 45, 20, 25], | 447 div.style.height = '350px'; |
438 // ['Serie2', 31, 38, 55, 66, 30, 35], | 448 // Get median, percentiles, maximum and minimum; outliers. |
439 // ['Serie3', 50, 55, 77, 80, 10, 15], | 449 pctl25 = []; |
440 // ['Serie4', 77, 77, 66, 50, 20, 25], | 450 pctl75 = []; |
441 // ['Serie5', 68, 66, 22, 15, 30, 35] | 451 med = []; |
442 // // Treat first row as data as well. | 452 min = []; |
443 // ]); | 453 max = []; |
444 // // Create and draw the visualization. | 454 outlierArray = []; |
445 // var ac = new google.visualization.ComboChart(document.getElementById('visualization')); | 455 max_n_outliers = 0; // maximum number of outliers for one audioelement |
446 // ac.draw(data, { | 456 for (audioelementIndex = 0; audioelementIndex<ratings[audioholderIndex].length; audioelementIndex++){ |
447 // title : 'Box Plot with Median and Average', | 457 med.push(median(ratings[audioholderIndex][audioelementIndex])); // median |
448 // width: 600, | 458 pctl25.push(percentile(ratings[audioholderIndex][audioelementIndex], 25)); // 25th percentile |
449 // height: 400, | 459 pctl75.push(percentile(ratings[audioholderIndex][audioelementIndex], 75)); // 75th percentile |
450 // vAxis: {title: "Value"}, | 460 IQR = pctl75[pctl75.length-1]-pctl25[pctl25.length-1]; |
451 // hAxis: {title: "Serie ID"}, | 461 // outliers: range of values which is above pctl75+1.5*IQR or below pctl25-1.5*IQR |
452 // series: { 0: {type: "candlesticks"}, 1: {type: "line", pointSize: 10, lineWidth: | 462 outliers = []; |
453 // 0 }, 2: {type: "line", pointSize: 10, lineWidth: 0, color: 'black' } } | 463 rest = []; |
454 // }); | 464 for (idx = 0; idx<ratings[audioholderIndex][audioelementIndex].length; idx++){ |
455 // } | 465 if (ratings[audioholderIndex][audioelementIndex][idx] > pctl75[pctl75.length-1]+1.5*IQR || |
466 ratings[audioholderIndex][audioelementIndex][idx] < pctl25[pctl25.length-1]-1.5*IQR){ | |
467 outliers.push(ratings[audioholderIndex][audioelementIndex][idx]); | |
468 } | |
469 else { | |
470 rest.push(ratings[audioholderIndex][audioelementIndex][idx]); | |
471 } | |
472 } | |
473 outlierArray.push(outliers); | |
474 max_n_outliers = Math.max(max_n_outliers, outliers.length); // update max mber | |
475 // max: maximum value which is not outlier | |
476 max.push(Math.max.apply(null, rest)); | |
477 // min: minimum value which is not outlier | |
478 min.push(Math.min.apply(null, rest)); | |
479 } | |
480 | |
481 // Build data array | |
482 boxplot_data = [['ID', 'Span', '', '', '', 'Median']]; | |
483 for (idx = 0; idx < max_n_outliers; idx++) { | |
484 boxplot_data[0].push('Outlier'); | |
485 } | |
486 for (audioelementIndex = 0; audioelementIndex<ratings[audioholderIndex].length; audioelementIndex++){ | |
487 if (ratings[audioholderIndex][audioelementIndex].length>0) { // if rating array not empty for this audioelement | |
488 data_array = [ | |
489 audioelementArray[audioelementIndex], // name | |
490 min[audioelementIndex], // minimum | |
491 pctl75[audioelementIndex], | |
492 pctl25[audioelementIndex], | |
493 max[audioelementIndex], // maximum | |
494 med[audioelementIndex] | |
495 ]; | |
496 for (idx = 0; idx < max_n_outliers; idx++) { | |
497 if (idx<outlierArray[audioelementIndex].length){ | |
498 data_array.push(outlierArray[audioelementIndex][idx]); | |
499 } | |
500 else { | |
501 data_array.push(null); | |
502 } | |
503 } | |
504 boxplot_data.push(data_array); | |
505 } | |
506 } | |
507 | |
508 // Create and populate the data table. | |
509 var data = google.visualization.arrayToDataTable(boxplot_data); | |
510 // Create and draw the visualization. | |
511 var ac = new google.visualization.ComboChart(document.getElementById('div_box_'+audioholderName)); | |
512 ac.draw(data, { | |
513 title : audioholderName, | |
514 //width: 600, | |
515 //height: 400, | |
516 vAxis: {title: "Rating"}, | |
517 hAxis: {title: "audioelement ID"}, | |
518 seriesType: "line", | |
519 pointSize: 5, | |
520 lineWidth: 0, | |
521 colors: ['black'], | |
522 series: { 0: {type: "candlesticks", color: 'blue'}, // box plot shape | |
523 1: {type: "line", pointSize: 10, lineWidth: 0, color: 'red' } }, // median | |
524 legend: 'none' | |
525 }); | |
526 } | |
527 } | |
528 | |
529 function makeTimeline(xmlFileName){ // WIP | |
530 // Based on the XML file name, take time data and plot playback and marker movements | |
531 | |
532 // read XML file and check if exists | |
533 xml = readXML(xmlFileName); | |
534 if (!xml) { // if file does not exist | |
535 console.log('XML file '+xml+'does not exist. ('+xmlFileName+')') | |
536 return; // do nothing; exit function | |
537 } | |
538 // get root of XML file | |
539 root = xml.getElementsByTagName('browserevaluationresult')[0]; | |
540 | |
541 audioholder_time = 0; | |
542 previous_audioholder_time = 0; // time spent before current audioholder | |
543 time_offset = 0; // test starts at zero | |
544 | |
545 // go over all audioholders | |
546 audioholderNodes = root.getElementsByTagName('audioholder'); | |
547 for (audioholderIndex = 0; audioholderIndex < audioholderNodes.length; audioholderIndex++) { | |
548 audioholderName = audioholderNodes[audioholderIndex].getAttribute('id'); | |
549 if (!audioholderName) { | |
550 console.log('audioholder name is empty; go to next one. ('+xmlFileName+')'); | |
551 break; | |
552 } | |
553 | |
554 // subtract total audioholder length from subsequent audioholder event times | |
555 audioholder_children = audioholderNodes[audioholderIndex].childNodes; | |
556 foundIt = false; | |
557 console.log(audioholder_children[2].getElementsByTagName("metricResult")) // not working! | |
558 for (idx = 0; idx<audioholder_children.length; idx++) { // go over children | |
559 | |
560 if (audioholder_children[idx].getElementsByTagName('metricResult').length) { | |
561 console.log(audioholder_children[idx].getElementsByTagName('metricResult')[0]); | |
562 if (audioholder_children[idx].getElementsByTagName('metricResult')[0].getAttribute('id') == "testTime"){ | |
563 audioholder_time = parseFloat(audioholder_children[idx].getElementsByTagName('metricResult')[0].textContent); | |
564 console.log(audioholder_time); | |
565 foundIt = true; | |
566 } | |
567 } | |
568 } | |
569 if (!foundIt) { | |
570 console.log("Skipping audioholder without total time specified from "+xmlFileName+"."); // always hitting this | |
571 break; | |
572 } | |
573 | |
574 audioelementNodes = audioholderNodes[audioholderIndex].getElementsByTagName('audioelement'); | |
575 | |
576 // make div | |
577 | |
578 // draw chart | |
579 | |
580 // legend with audioelement names | |
456 } | 581 } |
457 } | 582 } |
458 | 583 |
459 </script> | 584 </script> |
460 | 585 |
498 width: 780px; | 623 width: 780px; |
499 border: 1px solid black; | 624 border: 1px solid black; |
500 overflow: hidden; /* add this to contain floated children */ | 625 overflow: hidden; /* add this to contain floated children */ |
501 } | 626 } |
502 div#instrumentSection { | 627 div#instrumentSection { |
503 width: 250px; | 628 width: 250px; |
504 border: 1px solid red; | 629 border: 1px solid red; |
505 display: inline-block; | 630 display: inline-block; |
506 } | 631 } |
507 div#featureSection { | 632 div#featureSection { |
508 width: 250px; | 633 width: 250px; |
509 border: 1px solid green; | 634 border: 1px solid green; |
510 display: inline-block; | 635 display: inline-block; |
511 } | 636 } |
512 div#valenceSection { | 637 div#valenceSection { |
513 width: 250px; | 638 width: 250px; |
514 border: 1px solid blue; | 639 border: 1px solid blue; |
515 display: inline-block; | 640 display: inline-block; |
516 } | 641 } |
517 button#previousComment{ | 642 button#previousComment{ |
518 width: 120px; | 643 width: 120px; |
519 height: 150px; | 644 height: 150px; |
520 font-size:1.5em; | 645 font-size:1.5em; |
545 <div id="headerMatter"> | 670 <div id="headerMatter"> |
546 <div> | 671 <div> |
547 <strong>Result XML files:</strong> <span id="numberOfFiles_span"></span> | 672 <strong>Result XML files:</strong> <span id="numberOfFiles_span"></span> |
548 </div> | 673 </div> |
549 <div> | 674 <div> |
550 <strong>Audioholders in dataset:</strong> <span id="audioHolderArray_span"></span> | 675 <strong>Audioholders in dataset:</strong> <span id="audioholderArray_span"></span> |
551 </div> | 676 </div> |
552 <div> | 677 <div> |
553 <strong>Subjects in dataset:</strong> <span id="subjectArray_span"></span> | 678 <strong>Subjects in dataset:</strong> <span id="subjectArray_span"></span> |
554 </div> | 679 </div> |
555 <div> | 680 <div> |
556 <strong>Audioelements in dataset:</strong> <span id="audioElementArray_span"></span> | 681 <strong>Audioelements in dataset:</strong> <span id="audioelementArray_span"></span> |
557 </div> | 682 </div> |
558 <br> | 683 <br> |
559 </div> | 684 </div> |
560 <br> | 685 <br> |
561 | 686 |