Skip to content
Snippets Groups Projects

Review window functionality

Merged Verbeek, J.M. (Janneke) requested to merge review-window-functionality into master
10 files
+ 488
124
Compare changes
  • Side-by-side
  • Inline
Files
10
+ 188
22
@@ -4,18 +4,19 @@ import os
from filereader import CSVReader, CSVWriter
from utils import id_regex, shadow_regex
from time import localtime, strftime
from mistake_enum import *
class Controller:
def __init__(self, view, model):
self._model = model
self._view = view
self._view.actionlistener = self.actionlistener
self._view.action_listener = self.action_listener
# File reading and writing supported for .csv only
self._filereader = CSVReader()
self._filewriter = CSVWriter()
self._file_reader = CSVReader()
self._file_writer = CSVWriter()
# Lists of paths, represented as string
self._source_files = []
@@ -41,13 +42,13 @@ class Controller:
"""Start program user interface."""
self._view.display()
def actionlistener(self, key):
def action_listener(self, key):
"""Action listener for view events. Called by View class.
Args:
key: Identifier for View functionality
"""
action, *type_code = key.split(' ') # type_code is a (possibly empty) list
action, *type_code = key.split(' ')
if action == 'select':
self._select_files(type_code[0])
elif action == 'delete':
@@ -57,7 +58,7 @@ class Controller:
elif action == 'save':
self._save_results()
elif action == 'save_csv':
self._filewriter = CSVWriter()
self._file_writer = CSVWriter()
elif action == 'select_folder':
self._select_folder(type_code[0])
elif action == 'rm_all':
@@ -66,6 +67,16 @@ class Controller:
self._toggle_new()
elif action == 'anchor' or action == 'nw':
self._model.change_algorithm(action)
elif action == 'review':
self._review_files()
elif action == 'save_review':
self.save_review()
elif action == 'cancel_review':
self._view.close_review()
elif action == 'combobox_review':
self._select_review()
elif action == 'build_tree':
self.insert_participants()
def _select_folder(self, type_code='shadow'):
"""Select a folder from which multiple files can be read.
@@ -79,7 +90,7 @@ class Controller:
file_paths = [folder_path + '/' + x
for x in file_names if '.csv' in x]
self._set_path(file_paths, type_code)
self._view.update_files(file_paths, type_code)
self._view.update_file_list(file_paths, type_code)
self._toggle_new()
else:
self._view.update_message('no_file')
@@ -88,7 +99,7 @@ class Controller:
"""Set the file paths.
Args:
paths: Filepaths.
paths: File paths
type_code: Role of files ('source' or 'shadow')
"""
if type_code == 'source':
@@ -106,7 +117,7 @@ class Controller:
files = getattr(self, '_{}_files'.format(type_code))
selection = self._view.select_files(type_code)
files.extend(selection)
self._view.update_files(files, type_code)
self._view.update_file_list(files, type_code)
self._toggle_new()
def _delete_files(self, type_code, remove_all=False):
@@ -134,7 +145,7 @@ class Controller:
self._model.remove_task(selection)
self._view.button_status('select_folder {}'.format(type_code),
'normal')
self._view.update_files(files, type_code)
self._view.update_file_list(files, type_code)
self._toggle_new()
def _compare_files(self):
@@ -153,6 +164,7 @@ class Controller:
if self._model.analysis_complete:
self._view.update_message('comparison complete')
self._view.button_status('save', 'normal')
self._view.button_status('review', 'normal')
else:
self._view.update_message('no read')
@@ -168,12 +180,12 @@ class Controller:
mistake_title = self._compose_csv_title('mistakes')
delay_title = self._compose_csv_title('delay')
self._view.update_message('saved')
self._filewriter.write_frame(path,
mistake_results,
mistake_title)
self._filewriter.write_frame(path,
delay_results,
delay_title)
self._file_writer.write_frame(path,
mistake_results,
mistake_title)
self._file_writer.write_frame(path,
delay_results,
delay_title)
self._view.update_message('saved')
except PermissionError:
self._view.update_message('no_dir')
@@ -195,17 +207,17 @@ class Controller:
success = False
else:
success = True
source_data = self._filereader.read(file_path, 'source')
source_data = self._file_reader.read(file_path, 'source')
shadows = np.array([])
source_success.append(success)
for shadow_candidate in non_matched_shadows:
participant, task = shadow_regex(shadow_candidate, video)
if task is not None:
shadow_data = self._filereader.read(shadow_candidate,
participant, condition = shadow_regex(shadow_candidate, video)
if condition is not None:
shadow_data = self._file_reader.read(shadow_candidate,
'shadow')
self._model.add_task(participant,
video,
task,
condition,
source_data,
shadow_data)
np.append(shadows, shadow_candidate)
@@ -238,3 +250,157 @@ class Controller:
time = strftime("%d%m%y_%H%M%S", localtime())
title = "{}_{}_{}.csv".format(file_name, algorithm, time)
return title
def _review_files(self):
"""Open the result review window."""
task_names = [str(repr(task)) for task in self._model.shadow_tasks]
task_names.sort()
self._view.display_review(task_names)
def _select_review(self):
"""Change mistake in Treeview"""
tree = self._view._review._elements['tree']
selection = tree.selection()
mistake_string = self._view._review._elements['mistake_box'].get()
new_mistake = None
# Mistakes retrieved from Treeview are strings, therefore:
for m in Mistake:
if mistake_string.lower() == m.value:
new_mistake = m
# Change into selected mistake
for item in selection:
source, onset_src, shadow, onset_shd, mistake, review = tree.item(item)['values']
newvals = (source, onset_src, shadow, onset_shd, mistake, new_mistake.name)
tree.item(item, values=newvals)
def retrieve_participants(self, entry):
"""Get all shadow tasks corresponding to participant/condition/video
code.
Args:
entry: the participant/condition/video code
Returns:
participants: all shadow tasks corresponding to the code. """
participants = []
for m in self._model._shadow_tasks:
if m.participant+"_"+m.condition+m.video == entry:
participants.append(m)
return participants
def reset_participants(self, participants):
"""Update mistake information according to reviewed mistakes
by recalculating accuracy"""
for m in self._model._shadow_tasks:
for p in participants:
if m.participant+"_"+m.condition+m.video ==\
p.participant+"_"+p.condition+p.video:
p.results = \
self._model._stats._mistake_counter.\
calculate_accuracy(p.source, p.shadow)
def insert_participants(self):
"""Insert all shadow tasks/mistakes into the Treeview"""
# Retrieve some necessary values
tree = self._view._review._elements['tree']
entries = self._view._review._entries
counter = 1
# Insert shadow tasks into the tree
for e in entries:
part1 = tree.insert("", counter, text="{}".format(e))
parts = self.retrieve_participants(e)
for participant in parts:
# Handle source words
for s in participant.source:
if s.mistake is not None:
source = s.word
onset_src = round(s.onset, 3)
if s.shadow is None:
shadow = "NA"
onset_shd = "NA"
mistake = s.mistake
tree.insert(part1, "end", text="{}".format(e),
values=(source, onset_src, shadow,
onset_shd, mistake.name,
mistake.name))
# Handle shadow words
for s in participant.shadow:
if s.source is None: # Without source word
source = "NA"
onset_src = "NA"
shadow = s.word
onset_shd = round(s.onset, 3)
mistake = s.mistake
if mistake is not None:
tree.insert(part1, "end", text="{}".format(e),
values=(source, onset_src, shadow,
onset_shd, mistake.name,
mistake.name))
else: # Without shadow word
source = s.source.word
onset_src = s.source.onset
shadow = s.word
onset_shd = round(s.onset, 3)
mistake = s.mistake
if mistake is not None:
tree.insert(part1, "end", text="{}".format(e),
values=(source, onset_src, shadow,
onset_shd, mistake.name,
mistake.name))
counter += 1
def save_review(self):
"""Change internal data structure to reviewed mistake"""
# Retrieve some necessary values
tree = self._view._review._elements['tree']
entries = self._view._review._entries
changed = []
# Retrieve string mistake values from tree
for e in entries:
for child in tree.get_children():
for grandchild in tree.get_children(child):
if tree.item(grandchild)['text'] == e:
src, _, shd, _, _, new_mistake = \
tree.item(grandchild)['values']
mistake = None
for m in Mistake:
# Mistakes are strings, therefore:
if new_mistake.lower() == m.value:
mistake = m
changed.append([src, shd, mistake])
parts = self.retrieve_participants(e)
# Set mistakes in source to new mistake
for participant in parts:
for s in participant.source:
for c in changed:
if s.word == c[0] and (s.shadow is None):
new_mistake = c[2]
s.mistake = new_mistake
if new_mistake == Mistake.CORRECT:
s.mistake = None
s.shadowed = True
# Set mistakes in shadow to new mistake
for s in participant.shadow:
for c in changed:
if s.word == c[1] and s.source is None:
new_mistake = c[2]
s.mistake = new_mistake
elif s.word == c[1] and s.source.word == c[0]:
new_mistake = c[2]
if new_mistake == Mistake.CORRECT:
s.mistake = None
s.correct = True
s.mistake = new_mistake
# Really change internal data structure
self.reset_participants(parts)
self._view._review.update_message('review saved')
Loading