"""
Frontend Data Collection Page File for AGE-ABM Visual Interface
@Author Meghan Ireland
@Co-Authors Max Hall and Matthew Fleischman
"""
import tkinter as tk
from tkinter import ttk
import customtkinter
[docs]
class DataCollection:
"""Defines widgets and functionality of data collection page.
"""
def __init__(self, ec_app_ui):
"""Creates widgets for the Data Collector class.
"""
self.ec_app_ui = ec_app_ui
self.ids = tk.BooleanVar(self.ec_app_ui.root)
self.collect_all_agents = tk.BooleanVar(self.ec_app_ui.root)
self.radio_var_mean = tk.BooleanVar(self.ec_app_ui.root)
self.radio_var_total = tk.BooleanVar(self.ec_app_ui.root)
self.radio_var_min = tk.BooleanVar(self.ec_app_ui.root)
self.radio_var_max = tk.BooleanVar(self.ec_app_ui.root)
self.radio_var_var = tk.BooleanVar(self.ec_app_ui.root)
self.radio_var_std = tk.BooleanVar(self.ec_app_ui.root)
self.radio_var_med = tk.BooleanVar(self.ec_app_ui.root)
self.pos = tk.BooleanVar(self.ec_app_ui.root)
self.added_components = []
self.temp_components = []
### Label frames ###
self.labelframe_collectors_components = tk.LabelFrame(self.ec_app_ui.page_frame
, font=self.ec_app_ui.font2, text="Add Components", height = self.ec_app_ui.entry_width
, width = 4*self.ec_app_ui.entry_width, bg=self.ec_app_ui.frame_colour
, fg = self.ec_app_ui.button_font_colour)
self.labelframe_collectors_agents = tk.LabelFrame(self.ec_app_ui.page_frame
, font=self.ec_app_ui.font2, text="Agent", height = 3*self.ec_app_ui.entry_width//5
, width = 4*self.ec_app_ui.entry_width, bg=self.ec_app_ui.frame_colour
, fg = self.ec_app_ui.button_font_colour)
### Frames ###
self.frame_small = tk.Frame(master = self.ec_app_ui.page_frame, bg=self.ec_app_ui.frame_colour
, height = self.ec_app_ui.button_height
, width = 3*self.ec_app_ui.button_width//2)
### Title ###
self.label_collectors_title = tk.Label(self.ec_app_ui.title_frame, text="Data Collector"
, font=self.ec_app_ui.font1, bg=self.ec_app_ui.title_colour
, fg=self.ec_app_ui.label_text_colour)
self.label_collectors_add_agent_title = tk.Label(self.ec_app_ui.title_frame
, text="Add Agent of Interest", font=self.ec_app_ui.font1
, bg=self.ec_app_ui.title_colour, fg=self.ec_app_ui.label_text_colour)
### Labels ###
self.label_collectors_agent = tk.Label(self.labelframe_collectors_agents
, text="Select Agent", font=self.ec_app_ui.font2, justify="left"
, bg=self.ec_app_ui.frame_colour, fg=self.ec_app_ui.label_text_colour)
self.label_collectors_all_agents = tk.Label(self.labelframe_collectors_agents
, text="Collect Total Count?", font=self.ec_app_ui.font2, justify="left"
, bg=self.ec_app_ui.frame_colour, fg=self.ec_app_ui.label_text_colour)
self.label_collectors_positions = tk.Label(self.labelframe_collectors_agents
, text="Collect Positions?", font=self.ec_app_ui.font2, justify="left"
, bg=self.ec_app_ui.frame_colour, fg=self.ec_app_ui.label_text_colour)
self.label_collectors_collection_method = tk.Label(self.labelframe_collectors_agents
, text="Select Collection Methods:", font=self.ec_app_ui.font2, justify="left"
, bg=self.ec_app_ui.frame_colour, fg=self.ec_app_ui.label_text_colour)
self.label_collectors_individual = tk.Label(self.labelframe_collectors_agents
, text="Collect Component Values Per Individual Agent ID",font=self.ec_app_ui.font2
, justify="left",bg=self.ec_app_ui.frame_colour,fg=self.ec_app_ui.label_text_colour)
self.label_collectors_component = tk.Label(self.labelframe_collectors_components
, text="Select Component of Interest", font=self.ec_app_ui.font2
, justify="left",bg=self.ec_app_ui.frame_colour,fg=self.ec_app_ui.label_text_colour)
### Buttons ###
self.button_collectors_add = customtkinter.CTkButton(self.frame_small
, hover_color=self.ec_app_ui.highlight_colour,text="Add"
, command=self.btn_collectors_add,fg_color=self.ec_app_ui.comp_btn_colour
, font = self.ec_app_ui.font2, height=self.ec_app_ui.button_height
, width=self.ec_app_ui.button_width/2)
self.button_collectors_remove = customtkinter.CTkButton(self.frame_small
, hover_color=self.ec_app_ui.highlight_colour,text="Remove"
, command=self.btn_collectors_remove, fg_color=self.ec_app_ui.comp_btn_colour
, font = self.ec_app_ui.font2, height=self.ec_app_ui.button_height
, width=self.ec_app_ui.button_width/2)
self.button_collectors_save_component = customtkinter.CTkButton(self.labelframe_collectors_components
, text="Add", command=self.btn_collectors_component_save
, fg_color=self.ec_app_ui.comp_btn_colour, font = self.ec_app_ui.font2
, hover_color=self.ec_app_ui.highlight_colour
, height = self.ec_app_ui.entry_height, width=self.ec_app_ui.entry_width)
self.button_collectors_save = customtkinter.CTkButton(self.ec_app_ui.page_frame,text="Save"
, command=self.btn_collectors_save, fg_color=self.ec_app_ui.comp_btn_colour
, hover_color=self.ec_app_ui.highlight_colour
, font = self.ec_app_ui.font2, height = self.ec_app_ui.entry_height
, width=self.ec_app_ui.entry_width)
### Check Buttons ###
self.checkbox_collectors_agent_id = customtkinter.CTkCheckBox(self.labelframe_collectors_agents
, border_color=self.ec_app_ui.tbl_colour,hover_color=self.ec_app_ui.highlight_colour
, variable=self.collect_all_agents, text = "", fg_color = self.ec_app_ui.check_color)
self.checkbox_collectors_all_agents = customtkinter.CTkCheckBox(self.labelframe_collectors_agents
, border_color=self.ec_app_ui.tbl_colour,hover_color=self.ec_app_ui.highlight_colour
, variable=self.ids, text = "", fg_color = self.ec_app_ui.check_color)
self.checkbox_collectors_positions = customtkinter.CTkCheckBox(self.labelframe_collectors_agents
, border_color=self.ec_app_ui.tbl_colour,hover_color=self.ec_app_ui.highlight_colour
, variable=self.pos, text = "", fg_color = self.ec_app_ui.check_color)
### Switch Buttons ###
self.switch_collectors_mean = customtkinter.CTkSwitch(self.labelframe_collectors_agents
, progress_color=self.ec_app_ui.tbl_colour, variable=self.radio_var_mean, text = "Mean"
, font = self.ec_app_ui.font2, text_color = self.ec_app_ui.button_font_colour
, fg_color = self.ec_app_ui.off_switch)
self.switch_collectors_total = customtkinter.CTkSwitch(self.labelframe_collectors_agents
, progress_color=self.ec_app_ui.tbl_colour, variable=self.radio_var_total
, text = "Total", font = self.ec_app_ui.font2
, text_color = self.ec_app_ui.button_font_colour, fg_color = self.ec_app_ui.off_switch)
self.switch_collectors_min = customtkinter.CTkSwitch(self.labelframe_collectors_agents
, progress_color=self.ec_app_ui.tbl_colour
, variable=self.radio_var_min, text = "Min"
, font = self.ec_app_ui.font2, text_color = self.ec_app_ui.button_font_colour
, fg_color = self.ec_app_ui.off_switch)
self.switch_collectors_max = customtkinter.CTkSwitch(self.labelframe_collectors_agents
, progress_color=self.ec_app_ui.tbl_colour, variable=self.radio_var_max
, text = "Max", font = self.ec_app_ui.font2
, text_color = self.ec_app_ui.button_font_colour, fg_color = self.ec_app_ui.off_switch)
self.switch_collectors_var = customtkinter.CTkSwitch(self.labelframe_collectors_agents
, progress_color=self.ec_app_ui.tbl_colour, variable=self.radio_var_var
, text = "Variance", font = self.ec_app_ui.font2
, text_color = self.ec_app_ui.button_font_colour, fg_color = self.ec_app_ui.off_switch)
self.switch_collectors_std = customtkinter.CTkSwitch(self.labelframe_collectors_agents
, progress_color=self.ec_app_ui.tbl_colour, variable=self.radio_var_std
, text = "Std Dev", font = self.ec_app_ui.font2
, text_color = self.ec_app_ui.button_font_colour, fg_color = self.ec_app_ui.off_switch)
self.switch_collectors_median = customtkinter.CTkSwitch(self.labelframe_collectors_agents
, progress_color=self.ec_app_ui.tbl_colour, variable=self.radio_var_med
, text = "Median", font = self.ec_app_ui.font2
, text_color = self.ec_app_ui.button_font_colour, fg_color = self.ec_app_ui.off_switch)
### Drop down ###
self.dropdown_collectors_agents = customtkinter.CTkOptionMenu(self.labelframe_collectors_agents
, values = [], fg_color = self.ec_app_ui.dropdown_menu_color
, button_color=self.ec_app_ui.comp_btn_colour, command = self.on_selected_agent
, button_hover_color= self.ec_app_ui.highlight_colour
, height = self.ec_app_ui.entry_height, width=self.ec_app_ui.entry_width
, font = self.ec_app_ui.font2)
self.dropdown_collectors_agents.set("Select Agent")
self.dropdown_collectors_components = customtkinter.CTkOptionMenu(self.labelframe_collectors_components
, values = [], fg_color = self.ec_app_ui.dropdown_menu_color
, button_color=self.ec_app_ui.comp_btn_colour
, button_hover_color= self.ec_app_ui.highlight_colour
, height = self.ec_app_ui.entry_height, width=self.ec_app_ui.entry_width
, font = self.ec_app_ui.font2)
self.dropdown_collectors_components.set("Select Component")
self.dropdown_collectors_components.bind("<<ComboboxSelected>>", self.on_selected_component)
### Table for collector systems ###
self.collectors_arr = []
self.collectors_frame = customtkinter.CTkFrame(self.ec_app_ui.page_frame
, fg_color=self.ec_app_ui.tbl_colour
, height = 300, width = 580)
self.vertical_scroll3 = tk.Scrollbar(self.collectors_frame)
self.collectors_tbl = ttk.Treeview(self.collectors_frame, padding = 5, height = 8
, yscrollcommand=self.vertical_scroll3.set)
self.collectors_tbl['columns'] = ('Name', 'Reason for Collection')
self.collectors_tbl.column("#0", width=0, stretch='NO')
self.collectors_tbl.column("Name",anchor='center', width=190)
self.collectors_tbl.column("Reason for Collection",anchor='center',width=380)
self.collectors_tbl.heading("#0",text="",anchor='center')
self.collectors_tbl.heading("Name",text="Name",anchor='center')
self.collectors_tbl.heading("Reason for Collection",
text="Collected Components",anchor='center')
self.collectors_tbl.bind("<<TreeviewSelect>>", self.display_selected_collectors)
### Table for components ###
self.ad_comp_frame = customtkinter.CTkFrame(self.ec_app_ui.page_frame
, fg_color=self.ec_app_ui.tbl_colour
, height = 150
, width = self.ec_app_ui.window_width/5)
self.vertical_scroll = tk.Scrollbar(self.ad_comp_frame)
self.ad_comp_tbl = ttk.Treeview(self.ad_comp_frame,padding = 5,height=4
, yscrollcommand=self.vertical_scroll.set)
self.ad_comp_tbl['columns'] = 'Name'
self.ad_comp_tbl.column("#0", width=0, stretch='NO')
self.ad_comp_tbl.column("Name",anchor='center', width=250)
self.ad_comp_tbl.heading("#0",text="",anchor='center')
self.ad_comp_tbl.heading("Name",text="Components",anchor='center')
self.selected_collector = ""
### Data Tab ###
[docs]
def clear_collectors(self):
"""Clears the data collection page
"""
self.collectors_frame.grid_forget()
self.collectors_tbl.pack_forget()
self.dropdown_collectors_agents.grid_forget()
self.dropdown_collectors_components.grid_forget()
self.switch_collectors_max.grid_forget()
self.switch_collectors_min.grid_forget()
self.switch_collectors_total.grid_forget()
self.switch_collectors_mean.grid_forget()
self.labelframe_collectors_components.grid_forget()
self.labelframe_collectors_agents.grid_forget()
self.label_collectors_title.grid_forget()
self.label_collectors_add_agent_title.grid_forget()
self.label_collectors_agent.grid_forget()
self.label_collectors_all_agents.grid_forget()
self.label_collectors_collection_method.grid_forget()
self.label_collectors_individual.grid_forget()
self.label_collectors_component.grid_forget()
self.button_collectors_add.grid_forget()
self.button_collectors_remove.grid_forget()
self.button_collectors_save_component.grid_forget()
self.checkbox_collectors_agent_id.grid_forget()
self.checkbox_collectors_all_agents.grid_forget()
self.ad_comp_tbl.grid_forget()
self.ad_comp_frame.grid_forget()
self.button_collectors_save.grid_forget()
self.frame_small.grid_forget()
[docs]
def data_tab_btn(self):
"""This method is called when the user clicks on the Data Collection button
"""
self.ec_app_ui.clear_all()
self.added_components = []
self.temp_components = []
self.selected_collector = ""
### Reset switches ###
self.switch_collectors_mean.deselect()
self.switch_collectors_total.deselect()
self.switch_collectors_min.deselect()
self.switch_collectors_max.deselect()
self.switch_collectors_std.deselect()
self.switch_collectors_var.deselect()
self.checkbox_collectors_positions.deselect()
### Table ###
self.update_tbl_collectors()
self.collectors_frame.grid(row = 0, column = 0, columnspan=3
, pady = (40,5))
self.vertical_scroll3.pack(side="right", fill="y", padx=(0,5), pady=5)
self.collectors_tbl.pack(fill = "x", padx = (5,0), pady = 5)
### Add, edit, remove buttons ###
self.frame_small.grid(row = 1, column = 0, columnspan=3)
self.button_collectors_add.grid(row = 0,column = 0, sticky = "W", padx = 120)
self.button_collectors_remove.grid(row = 0, column = 1, sticky = "E", padx = 120)
### Title ###
self.label_collectors_title.grid(row = 0, column = 0)
[docs]
def btn_collectors_add(self):
"""Method called when user clicks the add button.
"""
self.update_tbl()
self.ec_app_ui.clear_all()
self.checkbox_collectors_all_agents.deselect()
self.checkbox_collectors_agent_id.deselect()
self.dropdown_collectors_agents.configure(self
, values = self.ec_app_ui.new_model.get_list_agents())
### Page title ###
self.label_collectors_add_agent_title.grid(row = 0, column = 0)
### Page Frame ###
self.labelframe_collectors_agents.grid_propagate(0)
self.labelframe_collectors_agents.configure(height = self.ec_app_ui.entry_width
, width = 4*self.ec_app_ui.entry_width)
self.labelframe_collectors_agents.grid(row = 0, column = 0, columnspan=3)
### Select Agent ###
agents = self.ec_app_ui.new_model.get_list_agents()
self.label_collectors_agent.grid(row = 0, column = 0, pady = 5, sticky="W", columnspan=6
, padx = 5)
self.dropdown_collectors_agents.configure(values = agents)
self.dropdown_collectors_agents.set("Select Agent")
self.dropdown_collectors_agents.grid(row = 0, column = 6, pady = 5, sticky="E", columnspan=1
, padx = 13 )
### Collect count ###
self.label_collectors_all_agents.grid(row = 1, column = 0, pady = 5, sticky="W", padx = 5
, columnspan=6)
self.checkbox_collectors_all_agents.grid(row = 1, column = 6, pady = 5, sticky="W"
, padx=16)
### Grid World ###
if self.ec_app_ui.new_model.get_model_details().get_gridworld():
self.label_collectors_positions.grid(row = 2, column = 0, pady = 5, sticky="W", padx = 5
, columnspan=6)
self.checkbox_collectors_positions.grid(row = 2, column = 6, pady = 5, sticky="W"
, padx=16)
self.labelframe_collectors_agents.configure(height = 9*self.ec_app_ui.entry_width/8)
### Collection Method ###
self.label_collectors_collection_method.grid(row = 3, column = 0, pady = 5, sticky="W"
, columnspan=5, padx = 5)
self.switch_collectors_mean.grid(row = 4, column = 0, padx = 5, pady = 5, sticky="W")
self.switch_collectors_total.grid(row = 4, column = 1, padx = 5, pady = 5, sticky="W")
self.switch_collectors_min.grid(row = 4, column = 2, padx = 5, pady = 5, sticky="W")
self.switch_collectors_max.grid(row = 4, column = 3, padx = 5, pady = 5, sticky="W")
self.switch_collectors_var.grid(row = 4, column = 4, padx = 5, pady = 5, sticky="W")
self.switch_collectors_std.grid(row = 4, column = 5, padx = 5, pady = 5, sticky="W")
self.switch_collectors_median.grid(row = 4, column = 6, padx = 5, pady = 5, sticky="W")
### Collect data per ID ###
self.label_collectors_individual.grid(row = 5, column = 0, pady = 5, sticky="W"
, columnspan=5, padx = 5)
self.checkbox_collectors_agent_id.grid(row = 5, column = 6, columnspan = 1, pady = 5
, sticky="W", padx=16)
### Frame ###
self.labelframe_collectors_components.configure(height = self.ec_app_ui.entry_width//2
, width = 4*self.ec_app_ui.entry_width)
self.labelframe_collectors_components.grid_propagate(0)
self.labelframe_collectors_components.grid(row = 1, column = 0, columnspan=3)
### Select Component ###
self.dropdown_collectors_components.configure(self
, values = self.ec_app_ui.new_model.get_list_components())
self.dropdown_collectors_components.set("Select Components")
self.label_collectors_component.grid(row = 1, column = 0, pady = 5, sticky="W"
, columnspan=1, padx = 5)
self.dropdown_collectors_components.grid(row = 1, column = 1, columnspan = 1, pady = 5
, sticky="W", padx = (428,5))
### Add Button ###
self.button_collectors_save_component.grid(row = 5, column = 1, columnspan = 1, sticky="W"
, padx = (428,5))
### Save Button ###
self.button_collectors_save.grid(row = 2, column = 2,pady = 5, sticky = "NW")
### Table ###
self.ad_comp_frame.grid(row = 2, column = 0, pady = 5,sticky="E")
self.vertical_scroll.pack(side="right", fill="y", padx=(0,5), pady=5)
self.ad_comp_tbl.pack(fill = "both", padx = (5,0), pady = 5)
[docs]
def btn_collectors_component_save(self):
"""Saves the information about a component being saved
"""
# Reset drop down
self.temp_components.remove(self.dropdown_collectors_components.get())
self.added_components.append(self.dropdown_collectors_components.get())
self.dropdown_collectors_components.set("Select Component")
self.dropdown_collectors_components.configure(values = self.temp_components)
self.update_tbl()
[docs]
def btn_collectors_save(self):
"""Saves the data collector
"""
if self.checkbox_collectors_all_agents.get():
count = True
else:
count = False
if self.checkbox_collectors_agent_id.get():
ids = True
else:
ids = False
if self.checkbox_collectors_positions.get():
pos = True
else:
pos = False
self.ec_app_ui.new_model.add_agent_of_interest(self.dropdown_collectors_agents.get(),
self.added_components, count, pos, ids, self.radio_var_mean.get(),
self.radio_var_med.get(), self.radio_var_total.get(),
self.radio_var_max.get(), self.radio_var_min.get(),
self.radio_var_var.get(), self.radio_var_std.get())
self.data_tab_btn()
[docs]
def btn_collectors_edit(self):
"""Method called when user clicks the edit button.
"""
[docs]
def display_selected_collectors(self, *args):
"""Gets the collector in the table that was selected
"""
selected_items = self.collectors_tbl.selection()
if selected_items:
selected_item = self.collectors_tbl.selection()[0]
self.selected_collector = self.collectors_tbl.item(selected_item)['values'][0]
[docs]
def btn_collectors_remove(self):
"""Method called when user clicks the remove button.
"""
self.ec_app_ui.new_model.remove_agent_of_interest(self.selected_collector)
self.update_tbl_collectors()
[docs]
def on_selected_agent(self,*args):
"""When user selects the agent
"""
agent = self.dropdown_collectors_agents.get()
self.dropdown_collectors_components.configure(values = [])
self.dropdown_collectors_components.set("Select Component")
self.temp_components = self.ec_app_ui.new_model.get_agent(agent).get_given_components()
agent_given_components = self.ec_app_ui.new_model.get_agent(agent).get_given_components()
self.dropdown_collectors_components.configure(values = agent_given_components)
[docs]
def on_selected_component(self,*args):
"""Required method
"""
[docs]
def update_tbl(self):
"""Updates the component table
"""
id7 = 0
components = self.added_components
for comp in self.ad_comp_tbl.get_children():
self.ad_comp_tbl.delete(comp)
for compo in components:
self.ad_comp_tbl.insert(parent='',index='end',iid=id7,text='',values=(compo,))
id7+=1
[docs]
def update_tbl_collectors(self):
"""Updates the data collectors table
"""
agnet_tbl_id = 0
agents = self.ec_app_ui.new_model.get_list_agents_of_interest()
for child in self.collectors_tbl.get_children():
self.collectors_tbl.delete(child)
for agent in agents:
comps = self.ec_app_ui.new_model.get_agent_of_interest(agent).get_comp_of_interest()
str_comps = ""
number_of_comps = len(comps)
for i in range(number_of_comps):
if i != 0:
str_comps = str_comps +", " + comps[i]
else:
str_comps = comps[i]
self.collectors_tbl.insert(parent='',index='end',iid=agnet_tbl_id,text=''
, values=(agent,str_comps))
agnet_tbl_id+=1