-
-
Notifications
You must be signed in to change notification settings - Fork 315
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Added feature to export the evaluation summary table in csv format #229
base: master
Are you sure you want to change the base?
Changes from 3 commits
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change | ||||||||||||
---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
|
@@ -209,6 +209,9 @@ def process_files( | |||||||||||||
for file_path in omr_files: | ||||||||||||||
files_counter += 1 | ||||||||||||||
file_name = file_path.name | ||||||||||||||
evaluation_path = os.path.join( | ||||||||||||||
outputs_namespace.paths.evaluation_dir, file_path.stem | ||||||||||||||
) | ||||||||||||||
|
||||||||||||||
in_omr = cv2.imread(str(file_path), cv2.IMREAD_GRAYSCALE) | ||||||||||||||
|
||||||||||||||
|
@@ -273,7 +276,9 @@ def process_files( | |||||||||||||
|
||||||||||||||
score = 0 | ||||||||||||||
if evaluation_config is not None: | ||||||||||||||
score = evaluate_concatenated_response(omr_response, evaluation_config) | ||||||||||||||
score = evaluate_concatenated_response( | ||||||||||||||
omr_response, evaluation_config, evaluation_path | ||||||||||||||
) | ||||||||||||||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
Suggested change
|
||||||||||||||
logger.info( | ||||||||||||||
f"(/{files_counter}) Graded with score: {round(score, 2)}\t for file: '{file_id}'" | ||||||||||||||
) | ||||||||||||||
|
@@ -342,25 +347,25 @@ def print_stats(start_time, files_counter, tuning_config): | |||||||||||||
time_checking = max(1, round(time() - start_time, 2)) | ||||||||||||||
log = logger.info | ||||||||||||||
log("") | ||||||||||||||
log(f"{'Total file(s) moved':<27}: {STATS.files_moved}") | ||||||||||||||
log(f"{'Total file(s) not moved':<27}: {STATS.files_not_moved}") | ||||||||||||||
log(f"{'Total file(s) moved': <27}: {STATS.files_moved}") | ||||||||||||||
log(f"{'Total file(s) not moved': <27}: {STATS.files_not_moved}") | ||||||||||||||
log("--------------------------------") | ||||||||||||||
log( | ||||||||||||||
f"{'Total file(s) processed':<27}: {files_counter} ({'Sum Tallied!' if files_counter == (STATS.files_moved + STATS.files_not_moved) else 'Not Tallying!'})" | ||||||||||||||
f"{'Total file(s) processed': <27}: {files_counter} ({'Sum Tallied!' if files_counter == (STATS.files_moved + STATS.files_not_moved) else 'Not Tallying!'})" | ||||||||||||||
) | ||||||||||||||
|
||||||||||||||
if tuning_config.outputs.show_image_level <= 0: | ||||||||||||||
log( | ||||||||||||||
f"\nFinished Checking {files_counter} file(s) in {round(time_checking, 1)} seconds i.e. ~{round(time_checking/60, 1)} minute(s)." | ||||||||||||||
f"\nFinished Checking {files_counter} file(s) in {round(time_checking, 1)} seconds i.e. ~{round(time_checking / 60, 1)} minute(s)." | ||||||||||||||
) | ||||||||||||||
log( | ||||||||||||||
f"{'OMR Processing Rate':<27}:\t ~ {round(time_checking/files_counter,2)} seconds/OMR" | ||||||||||||||
f"{'OMR Processing Rate': <27}: \t ~ {round(time_checking / files_counter, 2)} seconds/OMR" | ||||||||||||||
) | ||||||||||||||
log( | ||||||||||||||
f"{'OMR Processing Speed':<27}:\t ~ {round((files_counter * 60) / time_checking, 2)} OMRs/minute" | ||||||||||||||
f"{'OMR Processing Speed': <27}: \t ~ {round((files_counter * 60) / time_checking, 2)} OMRs/minute" | ||||||||||||||
) | ||||||||||||||
else: | ||||||||||||||
log(f"\n{'Total script time':<27}: {time_checking} seconds") | ||||||||||||||
log(f"\n{'Total script time': <27}: {time_checking} seconds") | ||||||||||||||
|
||||||||||||||
if tuning_config.outputs.show_image_level <= 1: | ||||||||||||||
log( | ||||||||||||||
|
Original file line number | Diff line number | Diff line change | ||||||||||||||||||||||||||||||||
---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
|
@@ -2,6 +2,7 @@ | |||||||||||||||||||||||||||||||||
import os | ||||||||||||||||||||||||||||||||||
import re | ||||||||||||||||||||||||||||||||||
from copy import deepcopy | ||||||||||||||||||||||||||||||||||
from csv import QUOTE_NONNUMERIC | ||||||||||||||||||||||||||||||||||
|
||||||||||||||||||||||||||||||||||
import cv2 | ||||||||||||||||||||||||||||||||||
import pandas as pd | ||||||||||||||||||||||||||||||||||
|
@@ -197,6 +198,9 @@ def __init__(self, curr_dir, evaluation_path, template, tuning_config): | |||||||||||||||||||||||||||||||||
self.should_explain_scoring = options.get("should_explain_scoring", False) | ||||||||||||||||||||||||||||||||||
self.has_non_default_section = False | ||||||||||||||||||||||||||||||||||
self.exclude_files = [] | ||||||||||||||||||||||||||||||||||
self.enable_evaluation_table_to_csv = options.get( | ||||||||||||||||||||||||||||||||||
"enable_evaluation_table_to_csv", False | ||||||||||||||||||||||||||||||||||
) | ||||||||||||||||||||||||||||||||||
|
||||||||||||||||||||||||||||||||||
if source_type == "csv": | ||||||||||||||||||||||||||||||||||
csv_path = curr_dir.joinpath(options["answer_key_csv_path"]) | ||||||||||||||||||||||||||||||||||
|
@@ -356,6 +360,23 @@ def conditionally_print_explanation(self): | |||||||||||||||||||||||||||||||||
if self.should_explain_scoring: | ||||||||||||||||||||||||||||||||||
console.print(self.explanation_table, justify="center") | ||||||||||||||||||||||||||||||||||
|
||||||||||||||||||||||||||||||||||
# Explanation Table to CSV | ||||||||||||||||||||||||||||||||||
def conditionally_save_explanation_csv(self, evaluation_path): | ||||||||||||||||||||||||||||||||||
if self.enable_evaluation_table_to_csv: | ||||||||||||||||||||||||||||||||||
data = {col.header: col._cells for col in self.explanation_table.columns} | ||||||||||||||||||||||||||||||||||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Nice. Can you add a screenshot of what the output csv looks like now? There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. |
||||||||||||||||||||||||||||||||||
|
||||||||||||||||||||||||||||||||||
output_dir = os.path.join( | ||||||||||||||||||||||||||||||||||
os.getcwd(), | ||||||||||||||||||||||||||||||||||
f"{evaluation_path}.csv", | ||||||||||||||||||||||||||||||||||
) | ||||||||||||||||||||||||||||||||||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. let's use evaluation_output_dir here
Suggested change
|
||||||||||||||||||||||||||||||||||
|
||||||||||||||||||||||||||||||||||
pd.DataFrame(data, dtype=str).to_csv( | ||||||||||||||||||||||||||||||||||
output_dir, | ||||||||||||||||||||||||||||||||||
mode="a", | ||||||||||||||||||||||||||||||||||
quoting=QUOTE_NONNUMERIC, | ||||||||||||||||||||||||||||||||||
index=False, | ||||||||||||||||||||||||||||||||||
) | ||||||||||||||||||||||||||||||||||
|
||||||||||||||||||||||||||||||||||
def get_should_explain_scoring(self): | ||||||||||||||||||||||||||||||||||
return self.should_explain_scoring | ||||||||||||||||||||||||||||||||||
|
||||||||||||||||||||||||||||||||||
|
@@ -507,7 +528,9 @@ def conditionally_add_explanation( | |||||||||||||||||||||||||||||||||
self.explanation_table.add_row(*row) | ||||||||||||||||||||||||||||||||||
|
||||||||||||||||||||||||||||||||||
|
||||||||||||||||||||||||||||||||||
def evaluate_concatenated_response(concatenated_response, evaluation_config): | ||||||||||||||||||||||||||||||||||
def evaluate_concatenated_response( | ||||||||||||||||||||||||||||||||||
concatenated_response, evaluation_config, evaluation_path | ||||||||||||||||||||||||||||||||||
): | ||||||||||||||||||||||||||||||||||
evaluation_config.prepare_and_validate_omr_response(concatenated_response) | ||||||||||||||||||||||||||||||||||
current_score = 0.0 | ||||||||||||||||||||||||||||||||||
for question in evaluation_config.questions_in_order: | ||||||||||||||||||||||||||||||||||
|
@@ -518,5 +541,6 @@ def evaluate_concatenated_response(concatenated_response, evaluation_config): | |||||||||||||||||||||||||||||||||
current_score += delta | ||||||||||||||||||||||||||||||||||
|
||||||||||||||||||||||||||||||||||
evaluation_config.conditionally_print_explanation() | ||||||||||||||||||||||||||||||||||
evaluation_config.conditionally_save_explanation_csv(evaluation_path) | ||||||||||||||||||||||||||||||||||
|
||||||||||||||||||||||||||||||||||
return current_score |
Original file line number | Diff line number | Diff line change | ||||||||||||||||||
---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
|
@@ -25,6 +25,7 @@ def __init__(self, output_dir): | |||||||||||||||||||
self.save_marked_dir = output_dir.joinpath("CheckedOMRs") | ||||||||||||||||||||
self.results_dir = output_dir.joinpath("Results") | ||||||||||||||||||||
self.manual_dir = output_dir.joinpath("Manual") | ||||||||||||||||||||
self.evaluation_dir = output_dir.joinpath("Evaluation") | ||||||||||||||||||||
self.errors_dir = self.manual_dir.joinpath("ErrorFiles") | ||||||||||||||||||||
self.multi_marked_dir = self.manual_dir.joinpath("MultiMarkedFiles") | ||||||||||||||||||||
|
||||||||||||||||||||
|
@@ -44,6 +45,11 @@ def setup_dirs_for_paths(paths): | |||||||||||||||||||
logger.info(f"Created : {save_output_dir}") | ||||||||||||||||||||
os.makedirs(save_output_dir) | ||||||||||||||||||||
|
||||||||||||||||||||
for save_output_dir in [paths.evaluation_dir]: | ||||||||||||||||||||
if not os.path.exists(save_output_dir): | ||||||||||||||||||||
logger.info(f"Created : {save_output_dir}") | ||||||||||||||||||||
os.makedirs(save_output_dir) | ||||||||||||||||||||
|
||||||||||||||||||||
for save_output_dir in [paths.multi_marked_dir, paths.errors_dir]: | ||||||||||||||||||||
if not os.path.exists(save_output_dir): | ||||||||||||||||||||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
Suggested change
|
||||||||||||||||||||
logger.info(f"Created : {save_output_dir}") | ||||||||||||||||||||
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
let's directly pass
evaluation_output_dir
(= outputs_namespace.paths.evaluation_dir) into the function below