Mercurial > hg > webaudioevaluationtool
view python/timeline_view_movement.py @ 2376:c41caaa96633
Some fixes for #90. Also a failsafe loop if the server never responds with meaningul information from saves (for instance, running only on apache or basic http servers). More changes to pythonServer for python 3.5. Please check if still valid on 2.7
author | Nicholas Jillings <nicholas.jillings@mail.bcu.ac.uk> |
---|---|
date | Thu, 19 May 2016 10:44:19 +0100 |
parents | 185232d01324 |
children | b0ef31a58ec5 |
line wrap: on
line source
#!/usr/bin/python import xml.etree.ElementTree as ET import os # list files in directory import sys # command line arguments import matplotlib.pyplot as plt # plots import matplotlib.patches as patches # rectangles # COMMAND LINE ARGUMENTS assert len(sys.argv)<3, "timeline_view_movement takes at most 1 command line argument\n"+\ "Use: python timeline_view_movement.py [XML_files_location]" # 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) 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.") 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+"'.") # CONFIGURATION # Folder where to store timelines timeline_folder = folder_name + '/timelines_movement/' # Stores in 'saves/timelines_movement/' by default # Font settings font = {'weight' : 'bold', 'size' : 16} plt.rc('font', **font) # Colormap for to cycle through colormap = ['b', 'g', 'c', 'm', 'y', 'k'] # figure size fig_width = 25 fig_height = 10 # CODE # create timeline_folder if not yet created if not os.path.exists(timeline_folder): os.makedirs(timeline_folder) # get every XML file in folder for file in os.listdir(folder_name): if file.endswith(".xml"): tree = ET.parse(folder_name + '/' + file) root = tree.getroot() subject_id = file[:-4] # drop '.xml' previous_page_time = 0 # time spent before current page time_offset = 0 # test starts at zero # ONE TIMELINE PER PAGE - make new plot per page # get list of all page names for page in root.findall("./page"): # iterate over pages page_name = page.get('ref') # get page name 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+".") break # subtract total page length from subsequent page event times page_time_temp = page.find("./metric/metricresult/[@id='testTime']") 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+".") break # get audioelements audioelements = page.findall("./audioelement") # sort alphabetically data = [] for elem in audioelements: # from http://effbot.org/zone/element-sort.htm key = elem.get("ref") data.append((key, elem)) data.sort() N_audioelements = len(audioelements) # number of audio elements for this page increment = 0 # increased for every new audioelement # get axes handle fig = plt.figure(figsize=(fig_width, fig_height)) ax = fig.add_subplot(111) # for page [page_name], print comments related to fragment [id] #for tuple in data: # audioelement = tuple[1] for tuple in data: audioelement = tuple[1] if audioelement is not None: # Check it exists audio_id = str(audioelement.get('ref')) # 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.") break # get move events, initial and eventual position initial_position = float(initial_position_temp.text) move_events = audioelement.findall("./metric/metricresult/[@name='elementTrackerFull']/movement") final_position = float(audioelement.find("./value").text) # get listen events start_times_global = [] stop_times_global = [] listen_events = audioelement.findall("./metric/metricresult/[@name='elementListenTracker']/event") for event in listen_events: # get testtime: start and stop start_times_global.append(float(event.find('testtime').get('start'))-time_offset) stop_times_global.append(float(event.find('testtime').get('stop'))-time_offset) # display fragment name at start plt.text(0,initial_position+0.02,audio_id,color=colormap[increment%len(colormap)]) #,rotation=45 # previous position and time previous_position = initial_position previous_time = 0 # assume not playing at start currently_playing = False # keep track of whether fragment is playing during move event # 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.get("time")) #-time_offset # (legacy) new_position = float(event.get("value")) # get play/stop events since last move until current move event stop_times = [] start_times = [] # is there a play and/or stop event between previous_time and new_time? for time in start_times_global: if time>previous_time and time<new_time: start_times.append(time) for time in stop_times_global: if time>previous_time and time<new_time: stop_times.append(time) # if no play/stop events between move events, find out whether playing segment_start = previous_time # first segment starts at previous move event # draw segments (horizontal line) while len(start_times)+len(stop_times)>0: # while still play/stop events left if len(stop_times)<1: # upcoming event is 'play' # draw non-playing segment from segment_start to 'play' currently_playing = False segment_stop = start_times.pop(0) # remove and return first item elif len(start_times)<1: # upcoming event is 'stop' # draw playing segment (red) from segment_start to 'stop' currently_playing = True segment_stop = stop_times.pop(0) # remove and return first item elif start_times[0]<stop_times[0]: # upcoming event is 'play' # draw non-playing segment from segment_start to 'play' currently_playing = False segment_stop = start_times.pop(0) # remove and return first item else: # stop_times[0]<start_times[0]: upcoming event is 'stop' # draw playing segment (red) from segment_start to 'stop' currently_playing = True segment_stop = stop_times.pop(0) # remove and return first item # draw segment plt.plot([segment_start, segment_stop], # x-values [previous_position, previous_position], # y-values color='r' if currently_playing else colormap[increment%len(colormap)], linewidth=3 ) segment_start = segment_stop # move on to next segment currently_playing = not currently_playing # toggle to draw final segment correctly # draw final segment (horizontal line) from last 'segment_start' to current move event time plt.plot([segment_start, new_time], # x-values [previous_position, previous_position], # y-values # color depends on playing during move event or not: color='r' if currently_playing else colormap[increment%len(colormap)], linewidth=3 ) # vertical line from previous to current position plt.plot([new_time, new_time], # x-values [previous_position, new_position], # y-values # color depends on playing during move event or not: color='r' if currently_playing else colormap[increment%len(colormap)], linewidth=3 ) # update previous_position value previous_position = new_position previous_time = new_time # draw final horizontal segment (or only segment if audioelement not moved) # horizontal line from previous time to end of page # get play/stop events since last move until current move event stop_times = [] start_times = [] # is there a play and/or stop event between previous_time and new_time? for time in start_times_global: if time>previous_time and time<page_time: #-time_offset: start_times.append(time) for time in stop_times_global: if time>previous_time and time<page_time: #-time_offset: stop_times.append(time) # if no play/stop events between move events, find out whether playing segment_start = previous_time # first segment starts at previous move event # draw segments (horizontal line) while len(start_times)+len(stop_times)>0: # while still play/stop events left # mark this plot as not empty plot_empty = False if len(stop_times)<1: # upcoming event is 'play' # draw non-playing segment from segment_start to 'play' currently_playing = False segment_stop = start_times.pop(0) # remove and return first item elif len(start_times)<1: # upcoming event is 'stop' # draw playing segment (red) from segment_start to 'stop' currently_playing = True segment_stop = stop_times.pop(0) # remove and return first item elif start_times[0]<stop_times[0]: # upcoming event is 'play' # draw non-playing segment from segment_start to 'play' currently_playing = False segment_stop = start_times.pop(0) # remove and return first item else: # stop_times[0]<start_times[0]: upcoming event is 'stop' # draw playing segment (red) from segment_start to 'stop' currently_playing = True segment_stop = stop_times.pop(0) # remove and return first item # draw segment plt.plot([segment_start, segment_stop], # x-values [previous_position, previous_position], # y-values color='r' if currently_playing else colormap[increment%len(colormap)], linewidth=3 ) segment_start = segment_stop # move on to next segment currently_playing = not currently_playing # toggle to draw final segment correctly # draw final segment (horizontal line) from last 'segment_start' to current move event time plt.plot([segment_start, page_time], # x-values [previous_position, previous_position], # y-values # color depends on playing during move event or not: color='r' if currently_playing else colormap[increment%len(colormap)], linewidth=3 ) # plt.plot([previous_time, page_time-time_offset], # x-values # [previous_position, previous_position], # y-values # color=colormap[increment%len(colormap)], # linewidth=3 # ) # display fragment name at end plt.text(page_time,previous_position,\ audio_id,color=colormap[increment%len(colormap)]) #,rotation=45 increment+=1 # to next audioelement last_page_duration = page_time #-time_offset time_offset = page_time if not plot_empty: # if plot is not empty, show and/or store # set plot parameters plt.title('Timeline ' + file + ": "+page_name) plt.xlabel('Time [seconds]') plt.xlim(0, last_page_duration) plt.ylabel('Rating') # default plt.ylim(0, 1) # rating between 0 and 1 # TO DO: # Y axis title and tick labels as specified in 'setup' for corresponding page # Different plots for different axes #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()