Skip to content
Snippets Groups Projects
Commit ef25a1dd authored by Alfen, T. van (Tanja)'s avatar Alfen, T. van (Tanja)
Browse files

Merge branch 'refactoring/IO_2'

parents 6e3e8041 6e9e61d0
No related branches found
No related tags found
1 merge request!42Refactoring/io 2
from filereader import FileReader, CSVReader, TxtReader # , FileWriter
# Disabled the FileWriter import since it does not exist yet.
from filereader import FileReader, CSVReader, TxtReader
from filereader import FileWriter, CSVWriter, TxtWriter
class Controller:
......@@ -11,8 +11,9 @@ class Controller:
self._model = model
self._view = view
self._view.actionlistener = self.actionlistener
self._filereader = CSVReader(None, None) # TODO: Deal with csv OR txt
# self._filewriter = FileWriter()
self._filereader = CSVReader("","") # TODO: Deal with csv OR txt
self._filewriter = CSVWriter()
# Lists of paths, represented as string
self._source_files = []
......@@ -38,6 +39,11 @@ class Controller:
self._compare_files()
elif action == 'save':
self._save_results()
elif action == 'save_csv':
self._filewriter = CSVWriter()
elif action == 'save_txt':
self._filewriter = TxtWriter()
def _select_files(self, type):
"""Select files and add them to files list corresponding to type.
......@@ -73,7 +79,8 @@ class Controller:
self._view.update_message('no shadow')
else:
self._view.update_message('files ok')
self._read_files(None) # TODO: Adapt to future implementation
self._read_files("source")
self._read_files("shadow")
self._model.compare()
self._view.update_message('comparison complete')
......@@ -83,8 +90,9 @@ class Controller:
self._view.update_message('no comparison')
else:
path = self._view.ask_save_location()
results = self._model.results # TODO: Check exact syntax when implemented
results = self._model._analysis_results
self._filewriter.write(path, results)
# results are of form sc, sh, info
self._view.update_message('saved')
def _read_files(self, type):
......@@ -94,12 +102,12 @@ class Controller:
type (str): Role of file ('source' or 'shadow')
"""
# TODO
# data = filereader.read(path, type)
# data_property = getattr(self._model, 'data_{}'.format(type))
# data_property(data)
# Temporary 'solution' for testing below
self._filereader = CSVReader(self._source_files[0],
self._shadow_files[0])
self._model.data_source, self._model.data_shadow =\
self._filereader.read()
path = self._source_files[0]
print(path)
self._filereader = CSVReader(path, type)
data = self._filereader.read()
if type == "source": # Fix is dirtier than I can talk
self._model._data_source = data
else:
self._model._data_shadow = data
import pandas as pd
import numpy as np
from abc import ABC, abstractmethod
from words import SourceWord, ShadowWord, Sentence
import csv
class FileReader (ABC):
......@@ -36,65 +38,154 @@ class FileReader (ABC):
kind of word it should be converted.
Returns:
words: list of the created Word instances.
words: type Sentence, object containing list of words.
"""
words = []
ws = []
for row in df.itertuples(name="Words"):
if word_type == "source":
word = SourceWord(row.Word.lower(), row.Onset, row.Offset)
else:
word = ShadowWord(row.Word.lower(), row.Onset, row.Offset)
words.append(word)
ws.append(word)
words = Sentence(ws)
return words
class CSVReader(FileReader):
def __init__(self, path_source, path_shadow):
"""Constructor
def __init__(self, path, type):
"""
Args:
path_source: the internal path to the source file
path_shadow: the internal path to the shadow file
path: string, the internal path to the source file
"""
self._path_source = path_source
self._path_shadow = path_shadow
self._path = path
self._type = type # Very dirty fix
def read(self):
"""Method that is used to read the data into a workable format"""
source_df = pd.read_csv(self._path_source, header=None, sep='\n')
source_df = source_df[0].str.split('\t', expand=True)
shadow_df = pd.read_csv(self._path_shadow, header=None, sep='\n')
shadow_df = shadow_df[0].str.split('\t', expand=True)
source_df = self.extract_task_data(source_df)
shadow_df = self.extract_task_data(shadow_df)
source_words = Sentence(self.df_to_words(source_df, "source"))
shadow_words = Sentence(self.df_to_words(shadow_df, "shadow"))
return source_words, shadow_words
df = pd.read_csv(self._path, header=None, sep='\n')
df = df[0].str.split('\t', expand=True)
data = self.extract_task_data(df)
words = self.df_to_words(data, self._type)
return words
class TxtReader(FileReader):
def __init__(self, path_source, path_shadow):
def __init__(self, path):
"""Constructor
Args:
path_source: the internal path to the source file
path_shadow: the internal path to the shadow file
path: path to file
"""
self._path_source = path_source
self._path_shadow = path_shadow
self._path = path
self._words = None
def read(self):
"""Method that is used to read the data into a workable format"""
with open(self._path_source, 'r') as source,\
open(self._path_shadow, 'r') as shadow:
# Does this even work? See warning:
source_df = self.extract_task_data(source)
shadow_df = self.extract_task_data(shadow)
source_words = Sentence(self.df_to_words(source_df,
"source"))
shadow_words = Sentence(self.df_to_words(shadow_df,
"shadow"))
return source_words, shadow_words
"""
Read data into Sentences.
Returns:
words: Sentence containing Words.
"""
with open(self._path, 'r') as data:
self._words = self.extract_task_data(data)
self._words = self.df_to_words(self._words, "header")
return self._words
class FileWriter(ABC):
def __init__(self):
pass
@abstractmethod
def write(self):
pass
def write_per_part(self):
"""
Write result per participant.
"""
for pn, pr in self.data:
results, stats = _format_results(pn, pr)
self.path = _participant_path(pn)
self.write()
@abstractmethod
def _participant_path(self, number):
pass
class TxtWriter(FileWriter):
def __init__(self):
super().__init__()
def write(self, path, results):
"""
Write a .txt file of analysis results.
Args:
path: string of paths
result: the results, type unknown
"""
# For now assume source, shadow, stat format
source_results, shadow_results, info = results
final = np.empty(0)
for i in range(len(source_results)):
source_word = source_results.words[i]
res = (str(source_word), str(source_word.shadowed)+"\n")
final = np.append(final, res)
final = np.append(final, "Total: "+str(info[0]))
final = np.append(final, "Correct: "+str(info[1]))
final = np.append(final, "Skips: "+str(info[2]))
np.savetxt(path, final, fmt="%s", header="Word|Shadowed")
# Untested
def _participant_path(part_number):
"""
Create a path for the appropriate participant.
Args: part_number: int of participant number
Returns:
participath: string, a path towards a directory for participant
part_number
"""
pth = self.path+"/"+part_number
os.mkdir(pth)
participath = pth+"/"+part_number+".txt"
return participath
class CSVWriter(FileWriter):
def __init__(self):
super().__init__()
def write(self, path, results):
"""
Write a CSV file of the results.
Args: path: string of path
results: results, type unknown
"""
source, shadow, info = results
info = "Total " + str(info[0]), "Shadowed " + str(info[1]), "Skipped"\
" " + str(info[2])
sc = []
for entry in source.words:
sc.append([entry.word, entry.onset, entry.offset, entry.shadowed])
with open(path+'.csv', 'w') as f:
writer = csv.writer(f)
writer.writerow(["Word", "Onset", "Offset", "Shadowed"])
writer.writerows(sc)
writer.writerow(info)
# TODO: Test per-participant writing
def _participant_path(part_number):
"""
Create a path for the appropriate participant.
Args: int part_number, participant number.
Returns:
participath: string, a path towards a directory for participant part_number
"""
pth = self.path+"/"+part_number
os.mkdir(pth)
participath = pth+"/"+part_number
return participath
......@@ -52,5 +52,8 @@ class Model:
def compare(self):
""""Run the analyses and saves the results."""
self._analysis_results = self._stats.analyze(self._data_source,
if self.has_source() and self.has_shadow():
self._analysis_results = self._stats.analyze(self._data_source,
self._data_shadow)
else:
print("This needs fixing")
......@@ -138,12 +138,9 @@ class SaaRomeo(AlignmentStrategy):
alignment_source.reverse()
alignment_shadow.reverse()
for source_word, shadow_word in zip(alignment_source,alignment_shadow):
for source_word, shadow_word in zip(alignment_source, alignment_shadow):
if type(source_word) is not Gap and type(shadow_word) is not Gap:
if source_word == shadow_word:
source_word.shadowed = True
return Sentence(alignment_source), Sentence(alignment_shadow)
......@@ -56,9 +56,9 @@ class View:
# TODO: Deal with multiple files at once
for path in paths:
if path == "": # Do not assign an empty file path
# TODO: Error message and close
select_files(type) #prompt again
if path == "": # Do not assign an empty file path
# TODO: Error message and close
select_files(type) # prompt again
return paths
def update_files(self, paths, type):
......@@ -123,12 +123,12 @@ class View:
'delete shadow',
'compare',
'save',
]
if key in controllerkeys:
self._actionlistener(key)
@staticmethod
def ask_save_location():
def ask_save_location(self):
"""Ask user for location to save file."""
path = filedialog.asksaveasfilename(title="Save file",
parent=self._window,
......@@ -136,7 +136,7 @@ class View:
("all files", "*.*")))
if ".txt" not in path:
path += ".txt"
if save_path == ".txt":
if path == ".txt":
# TODO: Error message & close
self.ask_save_location() # Prompt again
return path
......@@ -271,6 +271,7 @@ class View:
else:
return selected
class Options(View):
"""GUI control of program options."""
......
......@@ -14,6 +14,7 @@ class Word:
def __eq__(self, word):
return self._word == word.word
@property
def word(self):
"""Getter for the word.
......@@ -67,6 +68,14 @@ class Word:
"""
self._anchor = anchor
def get_difference(self, other):
"""Get the difference between the onset of this word and the other.
Args:
other: the other Word instance
"""
return other.onset - self._onset
class ShadowWord(Word):
def __init__(self, word, onset, offset):
......@@ -165,6 +174,13 @@ class SourceWord(Word):
class Sentence(list):
def __init__(self, words):
list.__init__(self, words)
self.words = words # I am not sure if this is the 'proper' fix
def __str__(self):
return " ".join([str(w) for w in self])
return " ".join([str(w) for w in self.words])
def __len__(self):
return len(self.words)
def __iter__(self):
return iter(self.words)
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment