Spaces:
Runtime error
Runtime error
achterbrain
commited on
Commit
•
d79174d
1
Parent(s):
54b89ad
updated hosted version to v0.0.3
Browse files- Dashboard.py +6 -18
- Dashboard_automation_setup.py +7 -0
- Dashboard_setup.py +4 -0
- pages/1_⚙️Manual assessment.py +2 -43
- pages/2_🤖Automated assessment.py +21 -36
- pages/3_📊Assessment summary.py +1 -85
- pages/Functions/Dashboard_functions.py +150 -0
Dashboard.py
CHANGED
@@ -1,22 +1,14 @@
|
|
1 |
import streamlit as st
|
2 |
import pandas as pd
|
3 |
import numpy as np
|
4 |
-
|
5 |
-
|
6 |
-
def prompt_to_csv(df):
|
7 |
-
# IMPORTANT: Cache the conversion to prevent computation on every rerun
|
8 |
-
df_download = df
|
9 |
-
df_download['Filename']='p'+df_download['ID'].astype('str')+'_1.png'
|
10 |
-
df_download = df[['Prompt','Filename']].drop_duplicates(subset='Filename')
|
11 |
-
return df_download.to_csv().encode('utf-8')
|
12 |
-
|
13 |
|
14 |
# Setup
|
15 |
-
##
|
16 |
-
prompt_dir = pd.read_csv('Data/Prompt_dir_221216.csv') #second version of prompt_dir
|
17 |
st.session_state['prompt_dir'] = prompt_dir
|
18 |
## Create lists of prompts for manual and automated assessments
|
19 |
-
st.session_state['automated_tasks'] =
|
20 |
automated_prompts = prompt_dir.loc[
|
21 |
(prompt_dir['Auto_assessment']==True)&
|
22 |
(prompt_dir['Task']).isin(st.session_state['automated_tasks'])].ID.tolist()
|
@@ -29,7 +21,6 @@ st.subheader('User guide')
|
|
29 |
st.write('To assess a generative image algorithm, download a set of prompts using the prompt downloader below. Generate one image per prompt and use the file names provided to name your images. Upload these generated images in the data upload section below. The pages for manual assessment and automated assessment allow you to systematically assess the generated images. The results will be presented and ready for download on the assessment summary page.')
|
30 |
st.sidebar.image('Graphics/IL_Logo.png')
|
31 |
|
32 |
-
|
33 |
# Add prompt downloading functions
|
34 |
prompt_download_dict = {}
|
35 |
## Count how many prompts are in database to allow for max value in selection
|
@@ -73,7 +64,6 @@ with st.expander("Prompt downloader"):
|
|
73 |
)
|
74 |
|
75 |
|
76 |
-
|
77 |
# Generate empty dataset for results, if it does not exist yet
|
78 |
try:
|
79 |
num_uploaded_images = st.session_state['eval_df'].shape[0]
|
@@ -88,6 +78,7 @@ try:
|
|
88 |
except KeyError:
|
89 |
st.session_state['results_dict'] = {}
|
90 |
|
|
|
91 |
# Data upload setup
|
92 |
st.subheader('Data upload')
|
93 |
#uploaded_files = st.file_uploader('Upload generated images', accept_multiple_files=True)
|
@@ -102,6 +93,7 @@ with st.form("my-form", clear_on_submit=True):
|
|
102 |
st.session_state['uploaded_img'] = st.session_state['uploaded_img']+uploaded_files
|
103 |
|
104 |
|
|
|
105 |
# Add new uploaded images to session state
|
106 |
## Try to append it to pre-existing list, else create new list in session state
|
107 |
## Always reset uploaded files to empty list after they have been added to state
|
@@ -150,7 +142,3 @@ if eval_df.shape[0]!=0:
|
|
150 |
st.write("- Available for automated assessment: ", str(sum(eval_df.automated_eval)))
|
151 |
else:
|
152 |
st.write("Upload files to start the assessment.")
|
153 |
-
|
154 |
-
#st.write(eval_df)
|
155 |
-
#st.write(prompt_dir)
|
156 |
-
#st.session_state['eval_df']
|
|
|
1 |
import streamlit as st
|
2 |
import pandas as pd
|
3 |
import numpy as np
|
4 |
+
from Dashboard_setup import prompt_dir, automated_task_list
|
5 |
+
from pages.Functions.Dashboard_functions import prompt_to_csv
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
6 |
|
7 |
# Setup
|
8 |
+
## Add prompt directory to session state
|
|
|
9 |
st.session_state['prompt_dir'] = prompt_dir
|
10 |
## Create lists of prompts for manual and automated assessments
|
11 |
+
st.session_state['automated_tasks'] = automated_task_list
|
12 |
automated_prompts = prompt_dir.loc[
|
13 |
(prompt_dir['Auto_assessment']==True)&
|
14 |
(prompt_dir['Task']).isin(st.session_state['automated_tasks'])].ID.tolist()
|
|
|
21 |
st.write('To assess a generative image algorithm, download a set of prompts using the prompt downloader below. Generate one image per prompt and use the file names provided to name your images. Upload these generated images in the data upload section below. The pages for manual assessment and automated assessment allow you to systematically assess the generated images. The results will be presented and ready for download on the assessment summary page.')
|
22 |
st.sidebar.image('Graphics/IL_Logo.png')
|
23 |
|
|
|
24 |
# Add prompt downloading functions
|
25 |
prompt_download_dict = {}
|
26 |
## Count how many prompts are in database to allow for max value in selection
|
|
|
64 |
)
|
65 |
|
66 |
|
|
|
67 |
# Generate empty dataset for results, if it does not exist yet
|
68 |
try:
|
69 |
num_uploaded_images = st.session_state['eval_df'].shape[0]
|
|
|
78 |
except KeyError:
|
79 |
st.session_state['results_dict'] = {}
|
80 |
|
81 |
+
|
82 |
# Data upload setup
|
83 |
st.subheader('Data upload')
|
84 |
#uploaded_files = st.file_uploader('Upload generated images', accept_multiple_files=True)
|
|
|
93 |
st.session_state['uploaded_img'] = st.session_state['uploaded_img']+uploaded_files
|
94 |
|
95 |
|
96 |
+
|
97 |
# Add new uploaded images to session state
|
98 |
## Try to append it to pre-existing list, else create new list in session state
|
99 |
## Always reset uploaded files to empty list after they have been added to state
|
|
|
142 |
st.write("- Available for automated assessment: ", str(sum(eval_df.automated_eval)))
|
143 |
else:
|
144 |
st.write("Upload files to start the assessment.")
|
|
|
|
|
|
|
|
Dashboard_automation_setup.py
ADDED
@@ -0,0 +1,7 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
from pages.Functions.Assessment_functions import CLIP_single_object_classifier, CLIP_multi_object_recognition_DSwrapper, CLIP_object_negation, DETR_multi_object_counting_DSwrapper
|
2 |
+
|
3 |
+
# Create dictionary to hold functions
|
4 |
+
fun_dict = {
|
5 |
+
'Multiple object types':CLIP_multi_object_recognition_DSwrapper,
|
6 |
+
'Single object':CLIP_single_object_classifier,
|
7 |
+
'Negation':CLIP_object_negation}
|
Dashboard_setup.py
ADDED
@@ -0,0 +1,4 @@
|
|
|
|
|
|
|
|
|
|
|
1 |
+
import pandas as pd
|
2 |
+
|
3 |
+
automated_task_list = ['Multiple object types', 'Single object','Negation']
|
4 |
+
prompt_dir = pd.read_csv('Data/Prompt_dir_221216.csv')
|
pages/1_⚙️Manual assessment.py
CHANGED
@@ -2,45 +2,7 @@ import streamlit as st
|
|
2 |
import numpy as np
|
3 |
import pandas as pd
|
4 |
from PIL import Image
|
5 |
-
|
6 |
-
def add_previous_manual_assessments():
|
7 |
-
'''
|
8 |
-
This is a routine to allow the user to upload prior manual ratings and override
|
9 |
-
current ratings. This way the user can restart a manual assessment.
|
10 |
-
'''
|
11 |
-
# Create dict to translate uploaded score into str format used during manual assessment
|
12 |
-
Bool_str_dict = {True:'Yes',False:'No'}
|
13 |
-
|
14 |
-
st.subheader('Add previous assessments')
|
15 |
-
st.write('Upload results of previous assessment (as downloaded from summary page) to add these results and skip these images in your current manual assessment. Note that you can only add results for images which you have uploaded using the same file name.')
|
16 |
-
|
17 |
-
uploaded_ratings = st.file_uploader('Select .csv for upload', accept_multiple_files=False)
|
18 |
-
if uploaded_ratings != None:
|
19 |
-
try:
|
20 |
-
uploaded_ratings_df = pd.read_csv(uploaded_ratings)
|
21 |
-
overlapping_files_df =pd.merge(st.session_state['eval_df'],uploaded_ratings_df,on='File_name',how='inner')
|
22 |
-
st.write('Number of matching file names found: '+ str(len(overlapping_files_df)))
|
23 |
-
st.write('Click "Add results" button to add / override current ratings with uploaded ratings.')
|
24 |
-
except UnicodeDecodeError:
|
25 |
-
st.write('WARNING: The uploaded file has to be a .csv downloaded from the "Assessment summary" page.')
|
26 |
-
|
27 |
-
|
28 |
-
submitted = st.button("Add results")
|
29 |
-
if submitted:
|
30 |
-
try:
|
31 |
-
for row in uploaded_ratings_df.itertuples():
|
32 |
-
st.session_state['eval_df'].loc[
|
33 |
-
st.session_state['eval_df']['File_name']==row.File_name,'manual_eval']=True
|
34 |
-
st.session_state['eval_df'].loc[
|
35 |
-
st.session_state['eval_df']['File_name']==row.File_name,'manual_eval_completed']=True
|
36 |
-
st.session_state['eval_df'].loc[
|
37 |
-
st.session_state['eval_df']['File_name']==row.File_name,'manual_eval_task_score']=Bool_str_dict[row.Score]
|
38 |
-
|
39 |
-
# Reset page after ratings were submitted
|
40 |
-
st.experimental_rerun()
|
41 |
-
except NameError:
|
42 |
-
st.write('You need to upload a .csv file before you can add results.')
|
43 |
-
|
44 |
|
45 |
st.title('Manual assessment')
|
46 |
st.write('On this page you can rate all uploaded images with regards to how good they match their respective prompts. You can see the outcome of your assessment on the summary page.')
|
@@ -172,6 +134,7 @@ if manual_eval_available > 0:
|
|
172 |
# Reset page after ratings were submitted
|
173 |
st.experimental_rerun()
|
174 |
|
|
|
175 |
add_previous_manual_assessments()
|
176 |
|
177 |
# If no files are uploaded
|
@@ -183,8 +146,4 @@ else:
|
|
183 |
|
184 |
|
185 |
|
186 |
-
#st.session_state['eval_df'].loc[curr_manual_eval,'manual_eval_completed']=True
|
187 |
-
#st.write(st.session_state['eval_df'])
|
188 |
-
|
189 |
-
|
190 |
|
|
|
2 |
import numpy as np
|
3 |
import pandas as pd
|
4 |
from PIL import Image
|
5 |
+
from pages.Functions.Dashboard_functions import add_previous_manual_assessments
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
6 |
|
7 |
st.title('Manual assessment')
|
8 |
st.write('On this page you can rate all uploaded images with regards to how good they match their respective prompts. You can see the outcome of your assessment on the summary page.')
|
|
|
134 |
# Reset page after ratings were submitted
|
135 |
st.experimental_rerun()
|
136 |
|
137 |
+
# Add option to add previous manual assessments
|
138 |
add_previous_manual_assessments()
|
139 |
|
140 |
# If no files are uploaded
|
|
|
146 |
|
147 |
|
148 |
|
|
|
|
|
|
|
|
|
149 |
|
pages/2_🤖Automated assessment.py
CHANGED
@@ -2,15 +2,7 @@ import streamlit as st
|
|
2 |
import numpy as np
|
3 |
from itertools import compress
|
4 |
from PIL import Image
|
5 |
-
from
|
6 |
-
|
7 |
-
|
8 |
-
# Create dictionary to hold functions
|
9 |
-
fun_dict = {
|
10 |
-
'Multiple object types':CLIP_multi_object_recognition_DSwrapper,
|
11 |
-
'Single object':CLIP_single_object_classifier,
|
12 |
-
'Negation':CLIP_object_negation}
|
13 |
-
|
14 |
|
15 |
st.title('Automated Assessment')
|
16 |
st.write('On this page you can use automated assessment algorithms to assess how good uploaded images match their respective prompts.')
|
@@ -30,6 +22,9 @@ try:
|
|
30 |
temp_prompt_dir=prompt_dir[['ID','Representations','Task_specific_label']]
|
31 |
temp_prompt_dir['Prompt_no']=temp_prompt_dir['ID'].astype('str')
|
32 |
curr_eval_df = curr_eval_df.merge(temp_prompt_dir,on='Prompt_no')
|
|
|
|
|
|
|
33 |
except KeyError:
|
34 |
automated_eval_available = 0
|
35 |
|
@@ -38,38 +33,30 @@ except KeyError:
|
|
38 |
# Else: Note to upload images for assessment
|
39 |
if automated_eval_available > 0:
|
40 |
|
|
|
|
|
|
|
|
|
|
|
41 |
with st.form("auto_assessment_form",clear_on_submit=True):
|
42 |
# Form info statment
|
43 |
st.write('Select tasks to assess with the automated assessment:')
|
44 |
|
45 |
-
#
|
46 |
-
|
47 |
-
|
48 |
-
|
49 |
-
|
50 |
-
|
51 |
-
|
52 |
-
|
53 |
-
'Single object type ({0} images available)'.format(
|
54 |
-
len(curr_eval_df.loc[
|
55 |
-
(curr_eval_df['automated_eval']==True)&
|
56 |
-
(curr_eval_df['Task']=='Single object')])
|
57 |
-
))
|
58 |
|
59 |
-
negation = st.checkbox(
|
60 |
-
'Negation ({0} images available)'.format(
|
61 |
-
len(curr_eval_df.loc[
|
62 |
-
(curr_eval_df['automated_eval']==True)&
|
63 |
-
(curr_eval_df['Task']=='Negation')])
|
64 |
-
))
|
65 |
-
|
66 |
submitted = st.form_submit_button("Start automated assessment")
|
67 |
-
if submitted:
|
68 |
# Create list for tasks which were selected for assessment
|
69 |
-
selected_tasks = list(
|
70 |
-
|
71 |
-
|
72 |
-
[assess_multi_object,assess_single_object,negation]))
|
73 |
# Create dataset to loop over with assessment
|
74 |
assessed_df = curr_eval_df.loc[
|
75 |
(curr_eval_df['automated_eval']==True)&
|
@@ -88,5 +75,3 @@ if automated_eval_available > 0:
|
|
88 |
st.write('Completed assessment. Access results on the summary page.')
|
89 |
else:
|
90 |
st.write('Upload files on dashboard starting page to start automated assessment.')
|
91 |
-
|
92 |
-
#st.write(st.session_state['auto_eval_df'])
|
|
|
2 |
import numpy as np
|
3 |
from itertools import compress
|
4 |
from PIL import Image
|
5 |
+
from Dashboard_automation_setup import fun_dict
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
6 |
|
7 |
st.title('Automated Assessment')
|
8 |
st.write('On this page you can use automated assessment algorithms to assess how good uploaded images match their respective prompts.')
|
|
|
22 |
temp_prompt_dir=prompt_dir[['ID','Representations','Task_specific_label']]
|
23 |
temp_prompt_dir['Prompt_no']=temp_prompt_dir['ID'].astype('str')
|
24 |
curr_eval_df = curr_eval_df.merge(temp_prompt_dir,on='Prompt_no')
|
25 |
+
|
26 |
+
# Check that user correctly filled out the automation setup file
|
27 |
+
assert list(fun_dict.keys())==st.session_state['automated_tasks'], 'Unsure that the list of automated tasks in Dashboard_setup.py is the same as the keys of the function dict in Dashboard_automation_setup.py'
|
28 |
except KeyError:
|
29 |
automated_eval_available = 0
|
30 |
|
|
|
33 |
# Else: Note to upload images for assessment
|
34 |
if automated_eval_available > 0:
|
35 |
|
36 |
+
# Create objects to hold selections of tasks for automated assessment
|
37 |
+
task_list = list(fun_dict.keys())
|
38 |
+
task_list_len = len(task_list)
|
39 |
+
task_list_selected = task_list.copy()
|
40 |
+
|
41 |
with st.form("auto_assessment_form",clear_on_submit=True):
|
42 |
# Form info statment
|
43 |
st.write('Select tasks to assess with the automated assessment:')
|
44 |
|
45 |
+
# Create list of bool selection buttons, one for every task
|
46 |
+
for i_task in range(task_list_len):
|
47 |
+
curr_task = task_list[i_task]
|
48 |
+
curr_task_count = len(curr_eval_df.loc[
|
49 |
+
(curr_eval_df['automated_eval']==True)&
|
50 |
+
(curr_eval_df['Task']==curr_task)])
|
51 |
+
task_list_selected[i_task] = st.checkbox(
|
52 |
+
'{0} ({1} images available)'.format(curr_task, str(curr_task_count)))
|
|
|
|
|
|
|
|
|
|
|
53 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
54 |
submitted = st.form_submit_button("Start automated assessment")
|
55 |
+
if submitted:
|
56 |
# Create list for tasks which were selected for assessment
|
57 |
+
selected_tasks = list(compress(task_list,task_list_selected))
|
58 |
+
|
59 |
+
|
|
|
60 |
# Create dataset to loop over with assessment
|
61 |
assessed_df = curr_eval_df.loc[
|
62 |
(curr_eval_df['automated_eval']==True)&
|
|
|
75 |
st.write('Completed assessment. Access results on the summary page.')
|
76 |
else:
|
77 |
st.write('Upload files on dashboard starting page to start automated assessment.')
|
|
|
|
pages/3_📊Assessment summary.py
CHANGED
@@ -3,6 +3,7 @@ import pandas as pd
|
|
3 |
import seaborn as sns
|
4 |
import matplotlib.pyplot as plt
|
5 |
from PIL import Image
|
|
|
6 |
side_image = Image.open('Graphics/IL_Logo.png')
|
7 |
st.sidebar.image(side_image)
|
8 |
|
@@ -11,89 +12,6 @@ def convert_df_to_csv(df):
|
|
11 |
# IMPORTANT: Cache the conversion to prevent computation on every rerun
|
12 |
return df[['File_name','Prompt_no','Task','Score']].to_csv().encode('utf-8')
|
13 |
|
14 |
-
def plot_style_simple(results_df, return_table = False):
|
15 |
-
|
16 |
-
|
17 |
-
eval_sum = results_df.groupby('Task')['Score'].sum()
|
18 |
-
eval_count = results_df.groupby('Task')['Score'].count()
|
19 |
-
eval_share = (eval_sum/eval_count)*100
|
20 |
-
|
21 |
-
if return_table:
|
22 |
-
return_series = results_df.groupby('Task')['Score'].sum()/results_df.groupby('Task')['Score'].count()*100
|
23 |
-
return_series = return_series.rename('Percentage correct')
|
24 |
-
return return_series
|
25 |
-
|
26 |
-
# Add small amount to make the bars on plot not disappear
|
27 |
-
eval_share = eval_share+1
|
28 |
-
|
29 |
-
fig = plt.figure(figsize=(12, 3))
|
30 |
-
sns.barplot(x=eval_share.index, y=eval_share.values, palette='GnBu')
|
31 |
-
plt.xticks(rotation=-45)
|
32 |
-
plt.ylabel('Percentage correct')
|
33 |
-
plt.xlabel(' ')
|
34 |
-
return fig
|
35 |
-
|
36 |
-
def plot_style_combined(results_df, uploaded_df = None, return_table=False):
|
37 |
-
# Create joined dataframe of results and uploadd_df
|
38 |
-
uploaded_results_df = uploaded_df
|
39 |
-
manual_results_df['Model']='Current'
|
40 |
-
uploaded_results_df['Model']='Uploaded'
|
41 |
-
results_df = pd.concat([manual_results_df,uploaded_results_df])
|
42 |
-
|
43 |
-
# Create scores for plot
|
44 |
-
eval_sum = results_df.groupby(['Model','Task'])['Score'].sum()
|
45 |
-
eval_count = results_df.groupby(['Model','Task'])['Score'].count()
|
46 |
-
eval_share = (eval_sum/eval_count)*100
|
47 |
-
eval_share = eval_share.reset_index()
|
48 |
-
|
49 |
-
if return_table:
|
50 |
-
return_series = results_df.groupby(['Task','Model'])['Score'].sum()/results_df.groupby(['Task','Model'])['Score'].count()*100
|
51 |
-
return_series = return_series.rename('Percentage correct')
|
52 |
-
return return_series
|
53 |
-
|
54 |
-
# Add small amount to make the bars on plot not disappear
|
55 |
-
eval_share['Score'] = eval_share['Score']+1
|
56 |
-
|
57 |
-
# Create plot
|
58 |
-
fig = plt.figure(figsize=(12, 3))
|
59 |
-
sns.barplot(data=eval_share,x='Task',y='Score',hue='Model', palette='GnBu')
|
60 |
-
plt.xticks(rotation=-45)
|
61 |
-
plt.ylabel('Percentage correct')
|
62 |
-
plt.xlabel(' ')
|
63 |
-
return fig
|
64 |
-
|
65 |
-
|
66 |
-
def print_results_tabs(file_upload, results_df, file_upload_df=None):
|
67 |
-
# Create a tab for bar chart and one for table data
|
68 |
-
tab1, tab2 = st.tabs(["Bar chart", "Data table"])
|
69 |
-
with tab1:
|
70 |
-
# If df was uploaded for comparison, we create comparison plot, else simple plot
|
71 |
-
if file_upload == None:
|
72 |
-
fig = plot_style_simple(results_df)
|
73 |
-
st.pyplot(fig)
|
74 |
-
else:
|
75 |
-
fig = plot_style_combined(results_df,file_upload_df)
|
76 |
-
st.pyplot(fig)
|
77 |
-
|
78 |
-
with tab2:
|
79 |
-
# If df was uploaded for comparison, we create comparison table, else simple table
|
80 |
-
if file_upload == None:
|
81 |
-
table = plot_style_simple(results_df, return_table=True)
|
82 |
-
st.write(table)
|
83 |
-
else:
|
84 |
-
table = plot_style_combined(results_df,file_upload_df, return_table=True)
|
85 |
-
st.write(table)
|
86 |
-
|
87 |
-
|
88 |
-
def pre_assessment_visualisation(type_str):
|
89 |
-
st.write('Complete {0} assessment or upload .csv with saved {0} assessment to generate summary.'.format(type_str))
|
90 |
-
|
91 |
-
# Display file uploader
|
92 |
-
file_upload = st.file_uploader("Upload .csv with saved {0} assessment to plot prior results.".format(type_str))
|
93 |
-
if file_upload != None:
|
94 |
-
file_upload_df = pd.read_csv(file_upload).copy()
|
95 |
-
print_results_tabs(file_upload=None, results_df=file_upload_df)
|
96 |
-
|
97 |
assessment_result_frames = {}
|
98 |
|
99 |
|
@@ -134,8 +52,6 @@ except KeyError:
|
|
134 |
|
135 |
|
136 |
|
137 |
-
|
138 |
-
|
139 |
st.write(' ')
|
140 |
st.header('Automated assessment')
|
141 |
try:
|
|
|
3 |
import seaborn as sns
|
4 |
import matplotlib.pyplot as plt
|
5 |
from PIL import Image
|
6 |
+
from pages.Functions.Dashboard_functions import plot_style_simple, plot_style_combined, print_results_tabs, pre_assessment_visualisation
|
7 |
side_image = Image.open('Graphics/IL_Logo.png')
|
8 |
st.sidebar.image(side_image)
|
9 |
|
|
|
12 |
# IMPORTANT: Cache the conversion to prevent computation on every rerun
|
13 |
return df[['File_name','Prompt_no','Task','Score']].to_csv().encode('utf-8')
|
14 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
15 |
assessment_result_frames = {}
|
16 |
|
17 |
|
|
|
52 |
|
53 |
|
54 |
|
|
|
|
|
55 |
st.write(' ')
|
56 |
st.header('Automated assessment')
|
57 |
try:
|
pages/Functions/Dashboard_functions.py
ADDED
@@ -0,0 +1,150 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
# General functions and routines used in the dashboard
|
2 |
+
|
3 |
+
import streamlit as st
|
4 |
+
import pandas as pd
|
5 |
+
import seaborn as sns
|
6 |
+
import matplotlib.pyplot as plt
|
7 |
+
from PIL import Image
|
8 |
+
|
9 |
+
|
10 |
+
##### Dashboard main page
|
11 |
+
def prompt_to_csv(df):
|
12 |
+
df_download = df
|
13 |
+
df_download['Filename']='p'+df_download['ID'].astype('str')+'_1.png'
|
14 |
+
df_download = df[['Prompt','Filename']].drop_duplicates(subset='Filename')
|
15 |
+
return df_download.to_csv().encode('utf-8')
|
16 |
+
|
17 |
+
##### Manual assessment
|
18 |
+
|
19 |
+
def add_previous_manual_assessments():
|
20 |
+
'''
|
21 |
+
This is a routine to allow the user to upload prior manual ratings and override
|
22 |
+
current ratings. This way the user can restart a manual assessment.
|
23 |
+
'''
|
24 |
+
# Create dict to translate uploaded score into str format used during manual assessment
|
25 |
+
Bool_str_dict = {True:'Yes',False:'No'}
|
26 |
+
|
27 |
+
st.subheader('Add previous assessments')
|
28 |
+
st.write('Upload results of previous assessment (as downloaded from summary page) to add these results and skip these images in your current manual assessment. Note that you can only add results for images which you have uploaded using the same file name.')
|
29 |
+
|
30 |
+
uploaded_ratings = st.file_uploader('Select .csv for upload', accept_multiple_files=False)
|
31 |
+
if uploaded_ratings != None:
|
32 |
+
try:
|
33 |
+
uploaded_ratings_df = pd.read_csv(uploaded_ratings)
|
34 |
+
overlapping_files_df =pd.merge(st.session_state['eval_df'],uploaded_ratings_df,on='File_name',how='inner')
|
35 |
+
st.write('Number of matching file names found: '+ str(len(overlapping_files_df)))
|
36 |
+
st.write('Click "Add results" button to add / override current ratings with uploaded ratings.')
|
37 |
+
except UnicodeDecodeError:
|
38 |
+
st.write('WARNING: The uploaded file has to be a .csv downloaded from the "Assessment summary" page.')
|
39 |
+
|
40 |
+
|
41 |
+
submitted = st.button("Add results")
|
42 |
+
if submitted:
|
43 |
+
try:
|
44 |
+
for row in uploaded_ratings_df.itertuples():
|
45 |
+
st.session_state['eval_df'].loc[
|
46 |
+
st.session_state['eval_df']['File_name']==row.File_name,'manual_eval']=True
|
47 |
+
st.session_state['eval_df'].loc[
|
48 |
+
st.session_state['eval_df']['File_name']==row.File_name,'manual_eval_completed']=True
|
49 |
+
st.session_state['eval_df'].loc[
|
50 |
+
st.session_state['eval_df']['File_name']==row.File_name,'manual_eval_task_score']=Bool_str_dict[row.Score]
|
51 |
+
|
52 |
+
# Reset page after ratings were submitted
|
53 |
+
st.experimental_rerun()
|
54 |
+
except NameError:
|
55 |
+
st.write('You need to upload a .csv file before you can add results.')
|
56 |
+
|
57 |
+
|
58 |
+
##### Assessment summary
|
59 |
+
def plot_style_simple(results_df, return_table = False):
|
60 |
+
'''
|
61 |
+
Simple plot function for plotting just one dataframe of results
|
62 |
+
'''
|
63 |
+
eval_sum = results_df.groupby('Task')['Score'].sum()
|
64 |
+
eval_count = results_df.groupby('Task')['Score'].count()
|
65 |
+
eval_share = (eval_sum/eval_count)*100
|
66 |
+
|
67 |
+
if return_table:
|
68 |
+
return_series = results_df.groupby('Task')['Score'].sum()/results_df.groupby('Task')['Score'].count()*100
|
69 |
+
return_series = return_series.rename('Percentage correct')
|
70 |
+
return return_series
|
71 |
+
|
72 |
+
# Add small amount to make the bars on plot not disappear
|
73 |
+
eval_share = eval_share+1
|
74 |
+
|
75 |
+
fig = plt.figure(figsize=(12, 3))
|
76 |
+
sns.barplot(x=eval_share.index, y=eval_share.values, palette='GnBu')
|
77 |
+
plt.xticks(rotation=-65)
|
78 |
+
plt.ylabel('Percentage correct')
|
79 |
+
plt.xlabel(' ')
|
80 |
+
return fig
|
81 |
+
|
82 |
+
def plot_style_combined(results_df, uploaded_df = None, return_table=False):
|
83 |
+
'''
|
84 |
+
Plot function which can plot to dataframe for comparison
|
85 |
+
'''
|
86 |
+
# Create joined dataframe of results and uploadd_df
|
87 |
+
uploaded_results_df = uploaded_df
|
88 |
+
manual_results_df['Model']='Current'
|
89 |
+
uploaded_results_df['Model']='Uploaded'
|
90 |
+
results_df = pd.concat([manual_results_df,uploaded_results_df])
|
91 |
+
|
92 |
+
# Create scores for plot
|
93 |
+
eval_sum = results_df.groupby(['Model','Task'])['Score'].sum()
|
94 |
+
eval_count = results_df.groupby(['Model','Task'])['Score'].count()
|
95 |
+
eval_share = (eval_sum/eval_count)*100
|
96 |
+
eval_share = eval_share.reset_index()
|
97 |
+
|
98 |
+
if return_table:
|
99 |
+
return_series = results_df.groupby(['Task','Model'])['Score'].sum()/results_df.groupby(['Task','Model'])['Score'].count()*100
|
100 |
+
return_series = return_series.rename('Percentage correct')
|
101 |
+
return return_series
|
102 |
+
|
103 |
+
# Add small amount to make the bars on plot not disappear
|
104 |
+
eval_share['Score'] = eval_share['Score']+1
|
105 |
+
|
106 |
+
# Create plot
|
107 |
+
fig = plt.figure(figsize=(12, 3))
|
108 |
+
sns.barplot(data=eval_share,x='Task',y='Score',hue='Model', palette='GnBu')
|
109 |
+
plt.xticks(rotation=-65)
|
110 |
+
plt.ylabel('Percentage correct')
|
111 |
+
plt.xlabel(' ')
|
112 |
+
return fig
|
113 |
+
|
114 |
+
|
115 |
+
def print_results_tabs(file_upload, results_df, file_upload_df=None):
|
116 |
+
'''
|
117 |
+
Routine used to give user the choice between showing results as bar chart or table
|
118 |
+
'''
|
119 |
+
# Create a tab for bar chart and one for table data
|
120 |
+
tab1, tab2 = st.tabs(["Bar chart", "Data table"])
|
121 |
+
with tab1:
|
122 |
+
# If df was uploaded for comparison, we create comparison plot, else simple plot
|
123 |
+
if file_upload == None:
|
124 |
+
fig = plot_style_simple(results_df)
|
125 |
+
st.pyplot(fig)
|
126 |
+
else:
|
127 |
+
fig = plot_style_combined(results_df,file_upload_df)
|
128 |
+
st.pyplot(fig)
|
129 |
+
|
130 |
+
with tab2:
|
131 |
+
# If df was uploaded for comparison, we create comparison table, else simple table
|
132 |
+
if file_upload == None:
|
133 |
+
table = plot_style_simple(results_df, return_table=True)
|
134 |
+
st.write(table)
|
135 |
+
else:
|
136 |
+
table = plot_style_combined(results_df,file_upload_df, return_table=True)
|
137 |
+
st.write(table)
|
138 |
+
|
139 |
+
|
140 |
+
def pre_assessment_visualisation(type_str):
|
141 |
+
'''
|
142 |
+
Routine used to allow user to visualise uploaded results before completing any assessments
|
143 |
+
'''
|
144 |
+
st.write('Complete {0} assessment or upload .csv with saved {0} assessment to generate summary.'.format(type_str))
|
145 |
+
|
146 |
+
# Display file uploader
|
147 |
+
file_upload = st.file_uploader("Upload .csv with saved {0} assessment to plot prior results.".format(type_str))
|
148 |
+
if file_upload != None:
|
149 |
+
file_upload_df = pd.read_csv(file_upload).copy()
|
150 |
+
print_results_tabs(file_upload=None, results_df=file_upload_df)
|