Mercurial > hg > webaudioevaluationtool
changeset 2275:3ca6e3fb66f4
Merge branch 'master' of https://github.com/BrechtDeMan/WebAudioEvaluationTool
author | www-data <www-data@sucuk.dcs.qmul.ac.uk> |
---|---|
date | Wed, 20 Apr 2016 18:20:58 +0100 |
parents | 64bdcd9ad9a4 (current diff) 2b5990868aa7 (diff) |
children | 372a355779de |
files | |
diffstat | 6 files changed, 75 insertions(+), 68 deletions(-) [+] |
line wrap: on
line diff
--- a/README.md Wed Apr 20 17:22:18 2016 +0100 +++ b/README.md Wed Apr 20 18:20:58 2016 +0100 @@ -16,6 +16,14 @@ Please refer to ['docs/Instructions/Instructions.pdf'](https://github.com/BrechtDeMan/WebAudioEvaluationTool/raw/master/docs/Instructions/Instructions.pdf). +## Dependencies + +Runs out of the box on any web server with PHP (tested on PHP 5.1<=), no third party software needed. + +Alternatively, a local server (no web server or internet connection needed!) and optional Python analysis scripts run on Python 2.7 or 3.x. +Plots rendered using [matplotlib](http://matplotlib.org), [NumPy](http://matplotlib.org) and [SciPy](http://scipy.org). + + ## Academic use ### Citing @@ -37,6 +45,7 @@ Please refer to LICENSE.txt ([GNU General Public License](http://www.gnu.org/licenses/gpl-3.0.en.html)). + ## Other use Other licensing schemes are available - please contact the authors regarding non-academic use.
--- a/docs/Instructions/Instructions.tex Wed Apr 20 17:22:18 2016 +0100 +++ b/docs/Instructions/Instructions.tex Wed Apr 20 18:20:58 2016 +0100 @@ -316,14 +316,14 @@ From \cite{waetwac}. % TODO: add labels like (\textbf{\texttt{horizontal-sliders}}) to show which type of interface can be created using which template - + \begin{itemize} \item AB Test / Pairwise comparison~\cite{lipshitz1981great,david1963method}: Two stimuli presented simultaneously, participant selects a preferred stimulus. \item ABC/HR (ITU-R BS. 1116)~\cite{recommendation19971116} (Mean Opinion Score: MOS): each stimulus has a continuous scale (5-1), labeled as Imperceptible, Perceptible but not annoying, Slightly annoying, Annoying, Very annoying. \item -50 to 50 Bipolar with Ref: each stimulus has a continuous scale -50 to 50 with default values as 0 in middle and a reference. \item Absolute Category Rating (ACR) Scale~\cite{rec1996p}: Likert but labels are Bad, Poor, Fair, Good, Excellent \item ABX Test~\cite{clark1982high}: Two stimuli are presented along with a reference and the participant has to select a preferred stimulus, often the closest to the reference. - \item APE \cite{ape}: Multiple stimuli on one or more axes for inter-sample rating. + \item APE~\cite{ape}: Multiple stimuli on one or more axes for inter-sample rating. %\item APE style 2D \cite{ape}: Multiple stimuli on a 2D plane for inter-sample rating (e.g. Valence Arousal). % TO BE IMPLEMENTED \item Comparison Category Rating (CCR) Scale~\cite{rec1996p}: ACR \& DCR but 7 point scale, with reference: Much better, Better, Slightly better, About the same, Slightly worse, Worse, Much worse. \item Degredation Category Rating (DCR) Scale~\cite{rec1996p}: ABC \& Likert but labels are (5) Inaudible, (4) Audible but not annoying, (3) Slightly annoying, (2) Annoying, (1) Very annoying. @@ -335,6 +335,7 @@ \item 9 Point Hedonic Category Rating Scale~\cite{peryam1952advanced}: each stimulus has a seven point scale with values: Like extremely, Like very much, Like moderate, Like slightly, Neither like nor dislike, Dislike extremely, Dislike very much, Dislike moderate, Dislike slightly. There is also a provided reference. \end{itemize} + \subsection{Building your own interface} \subsubsection{Nodes to familiarise}
--- a/python/comment_parser.py Wed Apr 20 17:22:18 2016 +0100 +++ b/python/comment_parser.py Wed Apr 20 18:20:58 2016 +0100 @@ -14,19 +14,19 @@ # XML results files location if len(sys.argv) == 1: folder_name = "../saves" # Looks in 'saves/' folder from 'scripts/' folder - print "Use: python comment_parser.py [XML_files_location]" - print "Using default path: " + folder_name + print("Use: python comment_parser.py [XML_files_location]") + print("Using default path: " + folder_name) elif len(sys.argv) == 2: folder_name = sys.argv[1] # First command line argument is folder # check if folder_name exists if not os.path.exists(folder_name): #the file is not there - print "Folder '"+folder_name+"' does not exist." + print("Folder '"+folder_name+"' does not exist.") sys.exit() # terminate script execution elif not os.access(os.path.dirname(folder_name), os.W_OK): #the file does exist but write privileges are not given - print "No write privileges in folder '"+folder_name+"'." + print("No write privileges in folder '"+folder_name+"'.") # CODE @@ -45,11 +45,11 @@ page_name = audioholder.get('ref') # get page name if page_name is None: # ignore 'empty' audio_holders - print "WARNING: " + file + " contains empty page. (comment_parser.py)" + print("WARNING: " + file + " contains empty page. (comment_parser.py)") break if audioholder.get("state") != "complete": - print "WARNING: " + file + "test page " + page_name + " is not complete, skipping." + print("WARNING: " + file + "test page " + page_name + " is not complete, skipping.") else: # create folder [page_name] if not yet created if not os.path.exists(folder_name + "/" + page_name): @@ -79,9 +79,9 @@ commentstr = '' # anonymous comments: - #writer.writerow([commentstr.encode("utf-8")]) + #writer.writerow([commentstr]) # .encode("utf-8") # comments with (file) name: - writer.writerow([file[:-4]] + [commentstr.encode("utf-8")]) + writer.writerow([file[:-4]] + [commentstr]) #TODO Replace 'new line' in comment with something else?
--- a/python/score_plot.py Wed Apr 20 17:22:18 2016 +0100 +++ b/python/score_plot.py Wed Apr 20 18:20:58 2016 +0100 @@ -31,34 +31,34 @@ # XML results files location if len(sys.argv) == 1: # no extra arguments enable_boxplot = True # show box plot - print "Use: python score_plot.py [rating folder] [plot_type] [-l/-legend]" - print "Type 'python score_plot.py -h' for help." - print "Using default path: " + rating_folder + " with boxplot." + print("Use: python score_plot.py [rating folder] [plot_type] [-l/-legend]") + print("Type 'python score_plot.py -h' for help.") + print("Using default path: " + rating_folder + " with boxplot.") else: for arg in sys.argv: # go over all arguments if arg == '-h': # show help #TODO: replace with contents of helpfile score_plot.info (or similar) - print "Use: python score_plot.py [rating_folder] [plot_type] [-l] [confidence]" - print " rating_folder:" - print " folder where output of 'score_parser' can be found, and" - print " where plots will be stored." - print " By default, '../saves/ratings/' is used." - print "" - print "PLOT TYPES" - print " Can be used in combination." - print " box | boxplot | -b" - print " Enables the boxplot" - print " conf | confidence | -c" - print " Enables the confidence interval plot" - print " ind | individual | -i" - print " Enables plot of individual ratings" - print "" - print "PLOT OPTIONS" - print " leg | legend | -l" - print " For individual plot: show legend with individual file names" - print " numeric value between 0 and 1, e.g. 0.95" - print " For confidence interval plot: confidence value" + print("Use: python score_plot.py [rating_folder] [plot_type] [-l] [confidence]") + print(" rating_folder:") + print(" folder where output of 'score_parser' can be found, and") + print(" where plots will be stored.") + print(" By default, '../saves/ratings/' is used.") + print("") + print("PLOT TYPES") + print(" Can be used in combination.") + print(" box | boxplot | -b") + print(" Enables the boxplot" ) + print(" conf | confidence | -c") + print(" Enables the confidence interval plot" ) + print(" ind | individual | -i") + print(" Enables plot of individual ratings" ) + print("") + print("PLOT OPTIONS") + print(" leg | legend | -l") + print(" For individual plot: show legend with individual file names") + print(" numeric value between 0 and 1, e.g. 0.95") + print(" For confidence interval plot: confidence value") assert False, ""# stop immediately after showing help #TODO cleaner way # PLOT TYPES @@ -73,17 +73,17 @@ # PLOT OPTIONS elif arg == 'leg' or arg == 'legend' or arg == '-l': if not enable_individual: - print "WARNING: The 'legend' option is only relevant to plots of "+\ - "individual ratings" + print("WARNING: The 'legend' option is only relevant to plots of "+\ + "individual ratings") show_legend = True # show all individual ratings elif arg.isdigit(): if not enable_confidence: - print "WARNING: The numeric confidence value is only relevant when "+\ - "confidence plot is enabled" + print("WARNING: The numeric confidence value is only relevant when "+\ + "confidence plot is enabled") if float(arg)>0 and float(arg)<1: confidence = float(arg) else: - print "WARNING: The confidence value needs to be between 0 and 1" + print("WARNING: The confidence value needs to be between 0 and 1") # FOLDER NAME else: @@ -97,11 +97,11 @@ # check if folder_name exists if not os.path.exists(rating_folder): #the file is not there - print "Folder '"+rating_folder+"' does not exist." + print("Folder '"+rating_folder+"' does not exist.") sys.exit() # terminate script execution elif not os.access(os.path.dirname(rating_folder), os.W_OK): #the file does exist but write rating_folder are not given - print "No write privileges in folder '"+rating_folder+"'." + print("No write privileges in folder '"+rating_folder+"'.") # CONFIGURATION @@ -119,28 +119,25 @@ if file.endswith(".csv"): page_name = file[:-4] # file name (without extension) is page ID - # get header + # get header (as text) + with open(rating_folder+file, 'rt') as readfile: # read this csv file + filereader = csv.reader(readfile, delimiter=',') + headerrow = next(filereader) # use headerrow as X-axis + headerrow = headerrow[1:] + + # read ratings into matrix (as bytes) with open(rating_folder+file, 'rb') as readfile: # read this csv file filereader = csv.reader(readfile, delimiter=',') - headerrow = filereader.next() # use headerrow as X-axis - headerrow = headerrow[1:] - - # read ratings into matrix -# ratings = np.loadtxt(open(rating_folder+file,"rb"), -# delimiter=",", -# skiprows=1, -# usecols=range(1,len(headerrow)+1) -# ) ratings = np.genfromtxt(readfile, delimiter=",", - #skip_header = 1, + skip_header = 1, converters = {3: lambda s: float(s or 'Nan')}, - usecols=range(1,len(headerrow)+1) + usecols=list(range(1,len(headerrow)+1)) ) # assert at least 2 subjects (move on to next file if violated) if ratings.shape[0]<2: - print "WARNING: Just one subject for " + page_name + ". Moving on to next file." + print("WARNING: Just one subject for " + page_name + ". Moving on to next file.") break # BOXPLOT @@ -183,9 +180,9 @@ increment = 0 linehandles = [] legendnames = [] - with open(rating_folder+file, 'rb') as readfile: # read this csv file + with open(rating_folder+file, 'r') as readfile: # read this csv file filereader = csv.reader(readfile, delimiter=',') - headerrow = filereader.next() # use headerrow as X-axis + headerrow = next(filereader) # use headerrow as X-axis headerrow = headerrow[1:] for row in filereader: subject_id = row[0][:-4] # read from beginning of line
--- a/python/timeline_view.py Wed Apr 20 17:22:18 2016 +0100 +++ b/python/timeline_view.py Wed Apr 20 18:20:58 2016 +0100 @@ -14,19 +14,19 @@ # XML results files location if len(sys.argv) == 1: folder_name = "../saves" # Looks in 'saves/' folder from 'scripts/' folder - print "Use: python timeline_view.py [XML_files_location]" - print "Using default path: " + folder_name + print("Use: python timeline_view.py [XML_files_location]") + print("Using default path: " + folder_name) elif len(sys.argv) == 2: folder_name = sys.argv[1] # First command line argument is folder # check if folder_name exists if not os.path.exists(folder_name): #the file is not there - print "Folder '"+folder_name+"' does not exist." + print("Folder '"+folder_name+"' does not exist.") sys.exit() # terminate script execution elif not os.access(os.path.dirname(folder_name), os.W_OK): #the file does exist but write privileges are not given - print "No write privileges in folder '"+folder_name+"'." + print("No write privileges in folder '"+folder_name+"'.") # CONFIGURATION @@ -76,11 +76,11 @@ plot_empty = True # check if any data is plotted if page_name is None: # ignore 'empty' audio_holders - print "WARNING: " + file + " contains empty page. (comment_parser.py)" + print("WARNING: " + file + " contains empty page. (comment_parser.py)") break if audioholder.get("state") != "complete": - print "WARNING: " + file + "test page " + page_name + " is not complete, skipping." + print("WARNING: " + file + "test page " + page_name + " is not complete, skipping.") break; # SORT AUDIO ELEMENTS ALPHABETICALLY audioelements = audioholder.findall("./audioelement")
--- a/python/timeline_view_movement.py Wed Apr 20 17:22:18 2016 +0100 +++ b/python/timeline_view_movement.py Wed Apr 20 18:20:58 2016 +0100 @@ -15,19 +15,19 @@ # XML results files location if len(sys.argv) == 1: folder_name = "../saves" # Looks in 'saves/' folder from 'scripts/' folder - print "Use: python timeline_view_movement.py [XML_files_location]" - print "Using default path: " + folder_name + print("Use: python timeline_view_movement.py [XML_files_location]") + print("Using default path: " + folder_name) elif len(sys.argv) == 2: folder_name = sys.argv[1] # First command line argument is folder # check if folder_name exists if not os.path.exists(folder_name): #the file is not there - print "Folder '"+folder_name+"' does not exist." + print("Folder '"+folder_name+"' does not exist.") sys.exit() # terminate script execution elif not os.access(os.path.dirname(folder_name), os.W_OK): #the file does exist but write privileges are not given - print "No write privileges in folder '"+folder_name+"'." + print("No write privileges in folder '"+folder_name+"'.") # CONFIGURATION @@ -72,7 +72,7 @@ plot_empty = True # check if any data is plotted if page_name is None: # ignore 'empty' audio_holders - print "Skipping empty page name from "+subject_id+"." + print("Skipping empty page name from "+subject_id+".") break # subtract total page length from subsequent page event times @@ -80,7 +80,7 @@ if page_time_temp is not None: page_time = float(page_time_temp.text) else: - print "Skipping page without total time specified from "+subject_id+"." + print("Skipping page without total time specified from "+subject_id+".") break # get audioelements @@ -111,7 +111,7 @@ # break if no initial position or move events registered initial_position_temp = audioelement.find("./metric/metricResult/[@name='elementInitialPosition']") if initial_position_temp is None: - print "Skipping "+page_name+" from "+subject_id+": does not have initial positions specified." + print("Skipping "+page_name+" from "+subject_id+": does not have initial positions specified.") break # get move events, initial and eventual position