changeset 1070:f1201566b54b

Scripts: modification to timeline plots: do not save (/show) plot if empty, e.g. legacy result files with no timing data
author Brecht De Man <BrechtDeMan@users.noreply.github.com>
date Mon, 17 Aug 2015 18:20:30 +0200
parents 4dd1cb18b77c
children e2dd3105a84c
files README.txt scripts/timeline_view.py scripts/timeline_view_movement.py
diffstat 3 files changed, 57 insertions(+), 38 deletions(-) [+]
line wrap: on
line diff
--- a/README.txt	Wed Aug 12 10:31:10 2015 +0200
+++ b/README.txt	Mon Aug 17 18:20:30 2015 +0200
@@ -35,6 +35,7 @@
 
 
 QUICK START
+
 Using the example project: 
 1. Make sure your system sample rate corresponds with the sample rate of the audio files, if the input XML file enforces the given sample rate. 
 2. Run pythonServer.py (make sure you have Python installed). 
@@ -44,6 +45,7 @@
 
 
 LEGACY
+
 The APE interface and most of the functionality of the interface is inspired by the APE toolbox for MATLAB [1]. See https://code.soundsoftware.ac.uk/projects/ape for the source code and corresponding paper. 
 
 
@@ -81,10 +83,15 @@
 In Firefox, go to Tools>Web Developer>Web Console, or hit Cmd + Alt + K. 
 
 
+REMOTE TESTS
+
+As the test is browser-based, it can be run remotely from a web server without modification. To allow for remote storage of the output XML files (as opposed to saving them locally on the subject’s machine, which is the default if no ‘save’ path is specified or found), a PHP script on the server needs to accept the output XML files. An example of such script will be included in a future version. 
+
+
 SCRIPTS
 
-The tool comes with a few handy Python scripts for easy extraction of ratings or comments, and visualisation of ratings and timelines. See below for a quick guide on how to use them. All scripts written for Python 2.7. Visualisation requires the free matplotlib toolbox (http://matplotlib.org), numpy and scipy. 
-By default, the scripts can be run from the ‘scripts’ folder, with the result files in the ‘saves’ folder (the default location where result XMLs are stored). 
+The tool comes with a few handy Python (2.7) scripts for easy extraction of ratings or comments, and visualisation of ratings and timelines. See below for a quick guide on how to use them. All scripts written for Python 2.7. Visualisation requires the free matplotlib toolbox (http://matplotlib.org), numpy and scipy. 
+By default, the scripts can be run from the ‘scripts’ folder, with the result files in the ‘saves’ folder (the default location where result XMLs are stored). Each script takes the XML file folder as an argument, along with other arguments in some cases. 
 
 	comment_parser.py
 		Extracts comments from the output XML files corresponding with the different subjects found in ‘saves/’. It creates a folder per ‘audioholder’/page it finds, and stores a CSV file with comments for every ‘audioelement’/fragment within these respective ‘audioholders’/pages. In this CSV file, every line corresponds with a subject/output XML file. Depending on the settings, the first column containing the name of the corresponding XML file can be omitted (for anonymisation). 
@@ -102,6 +109,9 @@
 		Requires the free matplotlib library. 
 		At this point, more than one subjects are needed for this script to work. 
 
+	timeline_view_movement.py
+		Creates a timeline for every subject, for every ‘audioholder’/page, corresponding with any of the output XML files found in ‘/saves’. It shows the marker movements of the different fragments, along with when each fragment was played (red regions). Automatically takes fragment names, rating axis title, rating axis labels, and audioholder name from the XML file (if available). 
+
 	timeline_view.py
 		Creates a timeline for every subject, for every ‘audioholder’/page, corresponding with any of the output XML files found in ‘/saves’. It shows when and for how long the subject listened to each of the fragments. 
 
--- a/scripts/timeline_view.py	Wed Aug 12 10:31:10 2015 +0200
+++ b/scripts/timeline_view.py	Mon Aug 17 18:20:30 2015 +0200
@@ -73,6 +73,7 @@
         # get list of all page names
         for audioholder in root.findall("./audioholder"):   # iterate over pages
             page_name = audioholder.get('id')               # get page name
+            plot_empty = True                               # check if any data is plotted
             
             if page_name is None: # ignore 'empty' audio_holders
                 break
@@ -96,7 +97,7 @@
             
             # for page [page_name], print comments related to fragment [id]
             for tuple in data:
-            	audioelement = tuple[1]
+                audioelement = tuple[1]
                 if audioelement is not None: # Check it exists
                     audio_id = str(audioelement.get('id'))
                     audioelements_names.append(audio_id)
@@ -104,6 +105,9 @@
                     # for this audioelement, loop over all listen events
                     listen_events = audioelement.findall("./metric/metricresult/[@name='elementListenTracker']/event")
                     for event in listen_events:
+                        # mark this plot as not empty
+                        plot_empty = False
+                    
                         # get testtime: start and stop
                         start_time = float(event.find('testtime').get('start'))-time_offset
                         stop_time  = float(event.find('testtime').get('stop'))-time_offset
@@ -133,21 +137,22 @@
             if audioholder_time is not None and show_audioholder_time: 
                 time_offset = float(audioholder_time.text)
             
-            # set plot parameters
-            plt.title('Timeline ' + file + ": "+page_name)
-            plt.xlabel('Time [seconds]')
-            plt.ylabel('Fragment')
-            plt.ylim(0, N_audioelements+1)
+            if not plot_empty:
+                # set plot parameters
+                plt.title('Timeline ' + file + ": "+page_name)
+                plt.xlabel('Time [seconds]')
+                plt.ylabel('Fragment')
+                plt.ylim(0, N_audioelements+1)
             
-            #y-ticks: fragment IDs, top to bottom
-            plt.yticks(range(N_audioelements, 0, -1), audioelements_names) # show fragment names
+                #y-ticks: fragment IDs, top to bottom
+                plt.yticks(range(N_audioelements, 0, -1), audioelements_names) # show fragment names
 
 
-            #plt.show() # uncomment to show plot; comment when just saving
-            #exit()
+                #plt.show() # uncomment to show plot; comment when just saving
+                #exit()
             
-            plt.savefig(timeline_folder+subject_id+"-"+page_name+".pdf", bbox_inches='tight')
-            plt.close()
+                plt.savefig(timeline_folder+subject_id+"-"+page_name+".pdf", bbox_inches='tight')
+                plt.close()
             
             #TODO: if 'nonsensical' or unknown: dashed line until next event
             #TODO: Vertical lines for fragment looping point
--- a/scripts/timeline_view_movement.py	Wed Aug 12 10:31:10 2015 +0200
+++ b/scripts/timeline_view_movement.py	Mon Aug 17 18:20:30 2015 +0200
@@ -69,6 +69,7 @@
         # get list of all page names
         for audioholder in root.findall("./audioholder"):   # iterate over pages
             page_name = audioholder.get('id')               # get page name
+            plot_empty = True                               # check if any data is plotted
             
             if page_name is None: # ignore 'empty' audio_holders
                 print "Skipping empty audioholder name from "+subject_id+"."
@@ -139,6 +140,9 @@
                     
                     # draw all segments except final one
                     for event in move_events: 
+                        # mark this plot as not empty
+                        plot_empty = False
+                    
                         # get time and final position of move event
                         new_time = float(event.find("./time").text)-time_offset
                         new_position = float(event.find("./position").text)
@@ -223,31 +227,31 @@
             last_audioholder_duration = audioholder_time-time_offset
             time_offset = audioholder_time
             
-
-            # set plot parameters
-            plt.title('Timeline ' + file + ": "+page_name)
-            plt.xlabel('Time [seconds]')
-            plt.xlim(0, last_audioholder_duration)
-            plt.ylabel('Rating') # default
-            plt.ylim(0, 1) # rating between 0 and 1
+            if not plot_empty: # if plot is not empty, show or store
+                # set plot parameters
+                plt.title('Timeline ' + file + ": "+page_name)
+                plt.xlabel('Time [seconds]')
+                plt.xlim(0, last_audioholder_duration)
+                plt.ylabel('Rating') # default
+                plt.ylim(0, 1) # rating between 0 and 1
             
-            #y-ticks: labels on rating axis
-            label_positions = []
-            label_text = []
-            scale_tags = root.findall("./BrowserEvalProjectDocument/audioHolder/interface/scale")
-            scale_title = root.find("./BrowserEvalProjectDocument/audioHolder/interface/title")
-            for tag in scale_tags:
-                label_positions.append(float(tag.get('position'))/100) # on a scale from 0 to 100
-                label_text.append(tag.text)
-            if len(label_positions) > 0: # if any labels available
-                plt.yticks(label_positions, label_text) # show rating axis labels
-            # set label Y-axis
-            if scale_title is not None: 
-                plt.ylabel(scale_title.text)
+                #y-ticks: labels on rating axis
+                label_positions = []
+                label_text = []
+                scale_tags = root.findall("./BrowserEvalProjectDocument/audioHolder/interface/scale")
+                scale_title = root.find("./BrowserEvalProjectDocument/audioHolder/interface/title")
+                for tag in scale_tags:
+                    label_positions.append(float(tag.get('position'))/100) # on a scale from 0 to 100
+                    label_text.append(tag.text)
+                if len(label_positions) > 0: # if any labels available
+                    plt.yticks(label_positions, label_text) # show rating axis labels
+                # set label Y-axis
+                if scale_title is not None: 
+                    plt.ylabel(scale_title.text)
             
-            #plt.show() # uncomment to show plot; comment when just saving
-            #exit()
+                #plt.show() # uncomment to show plot; comment when just saving
+                #exit()
             
-            plt.savefig(timeline_folder+subject_id+"-"+page_name+".pdf", bbox_inches='tight')
-            plt.close()
+                plt.savefig(timeline_folder+subject_id+"-"+page_name+".pdf", bbox_inches='tight')
+                plt.close()
             
\ No newline at end of file