Skip to content

Commit

Permalink
Merge pull request #21 from Munroe-Meyer-Institute-VR-Laboratory/v1.1…
Browse files Browse the repository at this point in the history
….0_wip

V1.1.0 wip
  • Loading branch information
wsarce authored Jun 26, 2022
2 parents 86ee392 + 725dd8a commit d233f31
Show file tree
Hide file tree
Showing 33 changed files with 1,663 additions and 131 deletions.
21 changes: 16 additions & 5 deletions cometrics.py
Original file line number Diff line number Diff line change
@@ -1,7 +1,11 @@
import datetime
import os
import sys
import gc
# Custom library imports
import traceback
from tkinter import messagebox

import imageio_ffmpeg

from config_utils import ConfigUtils
Expand Down Expand Up @@ -37,16 +41,23 @@ def main(config_file, first_time_user):
config = ConfigUtils()
config.set_cwd(cwd)
config.set_logs_dir(os.path.join(cometrics_ver_root, 'logs'))
if not os.path.exists(f"{cometrics_ver_root}/Projects"):
os.mkdir(f"{cometrics_ver_root}/Projects")
while True:
first_time = config.get_first_time()
setup = ProjectSetupWindow(config, first_time)
if setup.setup_complete:
while True:
manager = SessionManagerWindow(config, setup)
if manager.setup_again:
break
elif manager.close_program:
break
try:
manager = SessionManagerWindow(config, setup)
if manager.setup_again:
break
elif manager.close_program:
break
del manager
gc.collect()
except Exception as e:
messagebox.showerror("Error", f"Exception encountered:\n{str(e)}\n{traceback.print_exc()}")
if manager.close_program:
break
else:
Expand Down
2 changes: 2 additions & 0 deletions config.yml
Original file line number Diff line number Diff line change
Expand Up @@ -16,3 +16,5 @@ phases:
- Treatment
recent-projects: []
window-size: []
woodway-a-sn: FTHCUWVAA
woodway-b-sn: FTHCUQ9IA
18 changes: 18 additions & 0 deletions config_utils.py
Original file line number Diff line number Diff line change
Expand Up @@ -113,3 +113,21 @@ def set_ble(self, set_ble):
if self.config:
self.config['enable-ble'] = set_ble
self.save_config()

def get_woodway_a(self):
if self.config:
return str(self.config['woodway-a-sn'])

def set_woodway_a(self, woodway_sn):
if self.config:
self.config['woodway-a-sn'] = woodway_sn
self.save_config()

def get_woodway_b(self):
if self.config:
return str(self.config['woodway-b-sn'])

def set_woodway_b(self, woodway_sn):
if self.config:
self.config['woodway-b-sn'] = woodway_sn
self.save_config()
Binary file removed gui_images/bugsnag.png
Binary file not shown.
Binary file modified gui_images/condition_dropdown.jpg
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added gui_images/config_settings.jpg
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file modified gui_images/e4_data.jpg
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added gui_images/event_viewer.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file removed gui_images/loaded_video.jpg
Binary file not shown.
Binary file modified gui_images/pdf_page_2.jpg
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added gui_images/pdf_panel_1.jpg
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added gui_images/pdf_panel_2.jpg
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added gui_images/pdf_panel_3.jpg
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added gui_images/pdf_panels.jpg
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file removed gui_images/pdf_populated.jpg
Binary file not shown.
Binary file removed gui_images/project_name.jpg
Binary file not shown.
Binary file removed gui_images/session_events.jpg
Binary file not shown.
Binary file removed gui_images/session_started.jpg
Binary file not shown.
Binary file added gui_images/session_window.jpg
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added images/folder.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
2 changes: 1 addition & 1 deletion ksf_utils.py
Original file line number Diff line number Diff line change
Expand Up @@ -103,7 +103,7 @@ def cal_acc(prim_filename, reli_filename, window_size, output_dir):
dur_bindings = []
for dur in dur_b:
dur_bindings.append(dur[1])
prim_num, reli_num = int(prim_session["Session Number"]), int(reli_session["Session Number"])
prim_num, reli_num = prim_session["Session Number"], reli_session["Session Number"]
warning = ""
# Perform error checking before causing errors
if prim_num != reli_num:
Expand Down
865 changes: 827 additions & 38 deletions output_view_ui.py

Large diffs are not rendered by default.

97 changes: 92 additions & 5 deletions patient_data_fields.py
Original file line number Diff line number Diff line change
Expand Up @@ -85,6 +85,20 @@ def __init__(self, parent, x, y, height, width, patient_file, prim_session_numbe
self.patient_name = self.patient.name
if self.patient.medical_record_number:
self.patient_vars[PatientDataVar.MRN].set(self.patient.medical_record_number)
if self.patient.data_recorder:
self.patient_vars[PatientDataVar.DATA_REC].set(self.patient.data_recorder)
if self.patient.session_therapist:
self.patient_vars[PatientDataVar.SESS_THER].set(self.patient.session_therapist)
if self.patient.case_manager:
self.patient_vars[PatientDataVar.CASE_MGR].set(self.patient.case_manager)
if self.patient.primary_therapist:
self.patient_vars[PatientDataVar.PRIM_THER].set(self.patient.primary_therapist)
# if self.patient.condition_name:
# self.patient_vars[PatientDataVar.COND_NAME].set(self.patient.condition_name)
if self.patient.assessment_name:
self.patient_vars[PatientDataVar.ASSESS_NAME].set(self.patient.assessment_name)
if self.patient.session_location:
self.patient_vars[PatientDataVar.SESS_LOC].set(self.patient.session_location)
self.session_number = prim_session_number
self.patient_entries, self.patient_labels = [], []

Expand Down Expand Up @@ -245,9 +259,17 @@ def check_radio(self):
print(f"ERROR: Something went wrong assigning the session type "
f"{self.patient_vars[PatientDataVar.PRIM_DATA].get()}")

def save_patient_fields(self):
def save_patient_fields(self, ble_thresh_r, ble_thresh_l, woodway_thresh):
self.patient.save_patient(self.patient_vars[PatientDataVar.PATIENT_NAME].get(),
self.patient_vars[PatientDataVar.MRN].get())
self.patient_vars[PatientDataVar.MRN].get(),
self.patient_vars[PatientDataVar.SESS_LOC].get(),
self.patient_vars[PatientDataVar.ASSESS_NAME].get(),
self.patient_vars[PatientDataVar.COND_NAME].get(),
self.patient_vars[PatientDataVar.PRIM_THER].get(),
self.patient_vars[PatientDataVar.CASE_MGR].get(),
self.patient_vars[PatientDataVar.SESS_THER].get(),
self.patient_vars[PatientDataVar.DATA_REC].get(),
ble_thresh_r, ble_thresh_l, woodway_thresh)

def check_session_fields(self):
if self.patient_vars[PatientDataVar.SESS_LOC].get() == "":
Expand Down Expand Up @@ -302,19 +324,84 @@ def __init__(self, patient_file):
self.patient_path = None
self.name = None
self.medical_record_number = None
self.medical_record_number = None
self.session_location = None
self.assessment_name = None
self.condition_name = None
self.primary_therapist = None
self.case_manager = None
self.session_therapist = None
self.data_recorder = None
self.left_ble_thresh = None
self.right_ble_thresh = None
self.woodway_thresh = None
if patient_file:
self.update_fields(patient_file)
try:
self.update_fields(patient_file)
except KeyError or FileNotFoundError:
self.populate_defaults()

def update_fields(self, filepath):
f = open(filepath)
self.patient_json = json.load(f)
self.name = self.patient_json["Name"]
self.medical_record_number = self.patient_json["MRN"]
self.session_location = self.patient_json["Session Location"]
self.assessment_name = self.patient_json["Assessment Name"]
self.condition_name = self.patient_json["Condition Name"]
self.primary_therapist = self.patient_json["Primary Therapist"]
self.case_manager = self.patient_json["Case Manager"]
self.session_therapist = self.patient_json["Session Therapist"]
self.data_recorder = self.patient_json["Data Recorder"]
self.left_ble_thresh = self.patient_json["Left BLE Thresh"]
self.right_ble_thresh = self.patient_json["Right BLE Thresh"]
self.woodway_thresh = self.patient_json["Woodway Thresh"]

def populate_defaults(self):
if not self.name:
self.name = ""
if not self.medical_record_number:
self.medical_record_number = ""
if not self.session_location:
self.session_location = ""
if not self.assessment_name:
self.assessment_name = ""
if not self.condition_name:
self.condition_name = ""
if not self.primary_therapist:
self.primary_therapist = ""
if not self.case_manager:
self.case_manager = ""
if not self.session_therapist:
self.session_therapist = ""
if not self.data_recorder:
self.data_recorder = ""
if not self.right_ble_thresh:
self.right_ble_thresh = ""
if not self.left_ble_thresh:
self.left_ble_thresh = ""
if not self.woodway_thresh:
self.woodway_thresh = ""
self.save_patient(self.name, self.medical_record_number, self.session_location,
self.assessment_name, self.condition_name, self.primary_therapist,
self.case_manager, self.session_therapist, self.data_recorder,
self.right_ble_thresh, self.left_ble_thresh, self.woodway_thresh)

def save_patient(self, name, mrn):
def save_patient(self, name, mrn, sess_loc, assess_name, cond_name, prim_ther, case_mgr, sess_ther, data_rec,
right_ble_thresh, left_ble_thresh, woodway_thresh):
with open(self.source_file, 'w') as f:
x = {
"Name": name,
"MRN": mrn
"MRN": mrn,
"Session Location": sess_loc,
"Assessment Name": assess_name,
"Condition Name": cond_name,
"Primary Therapist": prim_ther,
"Case Manager": case_mgr,
"Session Therapist": sess_ther,
"Data Recorder": data_rec,
"Left BLE Thresh": left_ble_thresh,
"Right BLE Thresh": right_ble_thresh,
"Woodway Thresh": woodway_thresh
}
json.dump(x, f)
75 changes: 51 additions & 24 deletions project_setup_ui.py
Original file line number Diff line number Diff line change
Expand Up @@ -9,8 +9,9 @@
from tkinter.ttk import Combobox

from ksf_utils import import_ksf, create_new_ksf_revision, compare_keystrokes
from patient_data_fields import PatientContainer
from tkinter_utils import center, get_display_size, get_treeview_style, build_treeview, EntryPopup, select_focus, \
NewKeyPopup, clear_treeview, get_slider_style
NewKeyPopup, clear_treeview, get_slider_style, ProjectPopup
from ui_params import project_treeview_params as ptp, treeview_tags, window_ratio, large_field_font, medium_field_font, \
small_field_font, large_treeview_font, \
medium_treeview_font, small_treeview_font, large_treeview_rowheight, medium_treeview_rowheight, \
Expand Down Expand Up @@ -73,7 +74,8 @@ def __init__(self, config, first_time_user):
project_treeview_height,
treeview_width,
project_heading_dict,
double_bind=self.select_project)
double_bind=self.select_project,
button_3_bind=self.delete_project)
self.recent_projects = config.get_recent_projects()
self.populate_recent_projects()
patient_treeview_height = int(self.window_height * 0.2)
Expand Down Expand Up @@ -192,19 +194,22 @@ def popup_return(self, data, caller):
return
if caller == 0:
# Update path to project and create if it doesn't exist
self.project_dir = os.path.join(self.top_dir, data)
self.project_name = data[0]
self.project_dir = os.path.join(data[1], data[0])
if not os.path.exists(self.project_dir):
os.mkdir(self.project_dir)
if not os.path.exists(os.path.join(self.project_dir, '.cometrics')):
open(os.path.join(self.project_dir, '.cometrics'), 'w')
# Add to treeview
self.project_treeview_parents.append(
self.project_treeview.insert("", 'end', str((int(self.project_treeview_parents[-1]) + 1)), text=data,
self.project_treeview.insert("", 'end', str((int(self.project_treeview_parents[-1]) + 1)), text=self.project_name,
tags=treeview_tags[(int(self.project_treeview_parents[-1]) + 1) % 2]))
select_focus(self.project_treeview, self.project_treeview_parents[-1])
# Save recent path to config
if not self.recent_projects:
self.recent_projects = []
self.recent_projects.append(self.project_dir)
self.config.set_recent_projects(self.recent_projects[-20:])
self.config.set_recent_projects(self.recent_projects)
# Load the project
self.load_project(self.project_dir)
elif caller == 1:
Expand All @@ -224,7 +229,6 @@ def popup_return(self, data, caller):
tags=treeview_tags[(int(self.concern_treeview_parents[-1]) + 1) % 2]))
select_focus(self.concern_treeview, self.concern_treeview_parents[-1])
self.load_concern(len(self.concerns))

# endregion

# region Project UI Controls
Expand All @@ -235,22 +239,38 @@ def select_project(self, event):
self.create_new_project()
else:
try:
self.load_project(self.recent_projects[int(selection) - 1])
self.selected_project = int(selection) - 1
self.load_project(self.recent_projects[self.selected_project])
except IndexError as e:
print(f"ERROR: Error encountered when selecting project:\n{str(e)}\n{traceback.print_exc()}\n"
f"{self.recent_projects}\n{selection}")

def delete_project(self, event):
selection = self.project_treeview.identify_row(event.y)
if selection:
if selection == '0':
return
else:
try:
response = messagebox.askyesno("Delete Project?",
f"Delete {pathlib.Path(self.recent_projects[int(selection) - 1]).name} from Recent Projects?")
if response:
self.recent_projects.pop(int(selection) - 1)
self.config.set_recent_projects(self.recent_projects)
clear_treeview(self.project_treeview)
clear_treeview(self.patient_treeview)
clear_treeview(self.concern_treeview)
self.reset_ksf()
self.populate_recent_projects()
except IndexError as e:
print(
f"ERROR: Error encountered when deleting project: \n{str(e)}\n{traceback.print_exc()}\n{self.recent_projects}\n{selection}")

def create_new_project(self):
self.top_dir = filedialog.askdirectory(title='Select root directory to save files')
print("INFO:", self.top_dir)
if not self.top_dir:
messagebox.showwarning("Warning", "No root filepath chosen! Please try again.")
return
else:
self.top_dir = os.path.normpath(self.top_dir)
EntryPopup(self, self.main_root, "Enter New Project Name", 0)
ProjectPopup(self, self.main_root, "Create or Import New Project", 0)

def populate_recent_projects(self):
self.project_treeview_parents = []
self.project_treeview_parents.append(
self.project_treeview.insert("", 'end', str(0), text="Create or Import New Project",
tags=treeview_tags[2]))
Expand All @@ -266,18 +286,26 @@ def load_project(self, directory):
try:
_, self.patients, _ = next(os.walk(directory))
except StopIteration:
messagebox.showerror("Error", "Selected project cannot be found!")
response = messagebox.askyesno("Error", "Selected project cannot be found!\nDelete from Recent Projects?")
if response:
self.recent_projects.pop(self.selected_project)
self.config.set_recent_projects(self.recent_projects)
clear_treeview(self.project_treeview)
clear_treeview(self.patient_treeview)
clear_treeview(self.concern_treeview)
self.reset_ksf()
self.populate_recent_projects()
return
clear_treeview(self.patient_treeview)
clear_treeview(self.concern_treeview)
self.reset_ksf()
self.patient_treeview_parents = []
self.populate_patients()

# endregion

# region Patient UI Controls
def populate_patients(self):
self.patient_treeview_parents = []
self.patient_treeview_parents.append(self.patient_treeview.insert("", 'end', str(0), text="Create New Patient",
tags=treeview_tags[2]))
if self.patients:
Expand All @@ -296,6 +324,8 @@ def select_patient(self, event):
self.create_new_patient()
else:
self.patient_dir = os.path.join(self.project_dir, self.patients[int(selection) - 1])
if not os.path.exists(self.patient_dir):
os.mkdir(self.patient_dir)
self.load_patient(self.patients[int(selection) - 1])

def patient_creation_check(self):
Expand All @@ -317,19 +347,14 @@ def load_patient(self, directory):
self.populate_patient_concerns()
self.patient_data_file = os.path.normpath(
os.path.join(self.patient_dir, pathlib.Path(self.patient_dir).stem + '.json'))
if not os.path.exists(self.patient_data_file):
with open(self.patient_data_file, 'w') as f:
x = {
"Name": pathlib.Path(self.patient_dir).stem,
"MRN": ""
}
json.dump(x, f)
self.patient_container = PatientContainer(self.patient_data_file)

# endregion

# region Concern UI Controls
def populate_patient_concerns(self):
self.read_concern_file()
self.concern_treeview_parents = []
self.concern_treeview_parents.append(self.concern_treeview.insert("", 'end', str(0), text="Create New Concern",
tags=treeview_tags[2]))
if self.concerns:
Expand Down Expand Up @@ -475,6 +500,7 @@ def import_concern_ksf(self):

def populate_frequency_treeview(self):
self.clear_frequency_treeview()
self.frequency_treeview_parents = []
self.frequency_treeview_parents.append(
self.frequency_key_treeview.insert("", 'end', str(0), text="Create New Frequency Key",
tags=treeview_tags[2]))
Expand All @@ -495,6 +521,7 @@ def clear_duration_treeview(self):

def populate_duration_treeview(self):
self.clear_duration_treeview()
self.duration_treeview_parents = []
self.duration_treeview_parents.append(
self.duration_key_treeview.insert("", 'end', str(0), text="Create New Duration Key",
tags=treeview_tags[2]))
Expand Down
Binary file modified reference/Cometrics User Guide.pdf
Binary file not shown.
6 changes: 5 additions & 1 deletion requirements.txt
Original file line number Diff line number Diff line change
Expand Up @@ -9,4 +9,8 @@ PyYAML~=6.0
pyEmpatica~=0.5.7
openpyxl~=3.0.9
matplotlib==3.4.3
logger-util~=0.2
logger-util~=0.2
future~=0.18.2
ttkwidgets~=0.12.1
pyWoodway~=0.2.3
pyTactor~=0.1.4
Loading

0 comments on commit d233f31

Please sign in to comment.