<html><head><meta name="color-scheme" content="light dark"></head><body><pre style="word-wrap: break-word; white-space: pre-wrap;">"""

Description:
This script was written to extract desired data quickly from a user selected set of MULTIS trials. A report will be
generated to show the average and standard deviation of all the collected data, the user may choose to save the
generated report if desired. The numbers

Relevant variables include:
    age
    gender
    ethnicity
    height
    weight
    BMI - body mass index
    activity level

    Separated by segment (UA - Upper Arm, LA - Lower Arm, UL - Upper Leg, LL - Lower Leg):
    l - Segment length
    dc - Distal circumference
    cc - Central circumference
    pc - Proximal circumference


Getting started:
    Simply run the script and the MULTIS trials with available subject xml files will populate a list where you can
    check the ones you would like to include in the report. You may also hit the 'Select All' button to automatically
    select all the trials. Hit 'Okay' and the report will be generated for you to view. You may choose to save the
    report by clicking on the save button within the matplotlib figure.
    See data file contents on project Wiki for description of each category number (page 7-8)
    https://simtk.org/plugins/moinmoin/multis/Infrastructure/InstrumentedUltrasound?action=AttachFile&amp;do=view&amp;target
    =2015CB-047-001.B+Data+File+Contents_MULTIS.pdf

    Original Author:
        Erica Morrill
        Department of Biomedical Engineering
        Lerner Research Institute
        Cleveland Clinic
        Cleveland, OH
        morrile2@ccf.org

"""

import matplotlib
matplotlib.use("TkAgg")
from matplotlib.backends.backend_tkagg import FigureCanvasTkAgg, NavigationToolbar2TkAgg
import xml.etree.ElementTree as ET
import os
import Tkinter as tk
import pandas
import tkMessageBox
import tkFileDialog
import matplotlib.pyplot as plt
from matplotlib.ticker import MaxNLocator
import numpy as np

# class ResizingCanvas(tk.Canvas):
#     def __init__(self,parent,**kwargs):
#         tk.Canvas.__init__(self,parent,**kwargs)
#         print self.winfo_reqwidth(),self.winfo_reqheight() #&gt;&gt;&gt;854, 404
#         self.bind("&lt;Configure&gt;", self.on_resize)
#
#     def on_resize(self,event):
#         self.width = event.width   #&gt;&gt;&gt;854
#         self.height = event.height #&gt;&gt;&gt;404
#         self.config(width=self.width, height=self.height)

class DisplayGraphApp(tk.Tk):
    def __init__(self):
        tk.Tk.__init__(self)
        self.withdraw()
        self.protocol("WM_DELETE_WINDOW", self.on_exit)
        app = FileSelectionApp()
        app.mainloop()

        self.columnconfigure(0, weight=1)
        self.rowconfigure(0, weight=1)

        self.minsize(600, 600)

        self.DF_both = app.df

        self.DF_male = app.df.query('Gender == 0')
        self.DF_female = app.df.query('Gender == 1')
        self.DF = self.DF_both
        self.displayscrollbar()

    def displayscrollbar(self):
        self.deiconify()
        OPTIONS = self.DF.columns.values
        # OPTIONS = ["one", "two", "three"]

        variable = tk.StringVar(self)
        variable.set(str(OPTIONS[0]))  # default value

        frame = tk.Frame(self)
        frame.grid(row=0, column=0, rowspan=10, columnspan=7)
        frame.columnconfigure(0, weight=1)

        for i in range(10):
            if i != 5 and i != 9:
                frame.rowconfigure(i, weight=1)
            else:
                frame.rowconfigure(i, weight=2)

        self.fig = plt.figure(figsize=(12, 12))

        self.title("Select Desired Variable to Display")

        self.canvas = FigureCanvasTkAgg(self.fig, master=frame)

        self.canvas._tkcanvas.grid(row=0, column=0)

        w = tk.OptionMenu(self, variable, *(OPTIONS))
        w.configure(font=('timesnewroman', 20))
        w.grid(row=0, column=7, columnspan=2, sticky='ne')

        btn1 = tk.Button(self, text='Bin Adjust', command = self.adjust_bins)
        btn1.grid(row=8, column=7, columnspan=2, pady=(20, 100))

        self.plot_data(variable.get())
        tk.Label(self, text='Minimum').grid(row=5, column=7, sticky='e')
        self.bin_min = tk.Entry(self)
        self.bin_min.insert(0, str(min(self.info[1])))
        self.bin_min.grid(row=5, column=8)
        tk.Label(self, text='Maximum').grid(row=6, column=7, sticky='e')
        self.bin_max = tk.Entry(self)
        self.bin_max.insert(0, str(max(self.info[1])))
        self.bin_max.grid(row=6, column=8)
        tk.Label(self, text='Spacing').grid(row=7, column=7, sticky='e')
        self.bin_spc = tk.Entry(self)
        self.bin_spc.insert(0, str(self.info[1][1]-self.info[1][0]))
        self.bin_spc.grid(row=7, column=8)

        MODES = [("Male", "1"), ("Female", "2"), ("Both", "3")]
        v = tk.StringVar()
        v.set("3")

        c = 1
        pad = [(0,0), (100, 0), (0,0), (0, 100)]
        for text, mode in MODES:
            b = tk.Radiobutton(self, text = text, variable = v, value = mode, command = lambda var=v: self.gender_selection(v))
            b.grid(row = c, column = 7, columnspan=2, pady=pad[c])
            c+=1
        # tk.Radiobutton(self, text = [])

        variable.trace('w', lambda name, index, mode, var=variable: self.OptionMenu_SelectionEvent(variable))

    def gender_selection(self, v):
        self.fig.clf()
        ax = plt.gca()
        if v.get() == '1':
            self.DF = self.DF_male
        elif v.get() == '2':
            self.DF = self.DF_female
        elif v.get() == '3':
            self.DF = self.DF_both

        self.plot_data(self.v)

    def OptionMenu_SelectionEvent(self, variable):
        self.fig.clf()
        self.plot_data(variable.get())

        self.bin_min.delete(0, 'end')
        self.bin_min.insert(0, str("%.2f" % round(min(self.info[1]), 2)))
        self.bin_max.delete(0, 'end')
        self.bin_max.insert(0, str("%.2f" % round(max(self.info[1]), 2)))
        self.bin_spc.delete(0, 'end')
        self.bin_spc.insert(0, str("%.2f" % round(self.info[1][1]-self.info[1][0], 2)))


    def plot_data(self, v):

        ax = plt.gca()

        if self.DF[v].dtypes == 'int64':
            if v == 'Activity' or v == 'Race':
                bins = [-0.5, 0.5, 1.5, 2.5, 3.5, 4.5]
                ticks = [0, 1, 2, 3, 4]
            else:
                bins = [-0.5, 0.5, 1.5]
                ticks = [0, 1]
            self.info = ax.hist(self.DF[v], bins=bins, align='mid')
            ax.set_title(v)
            ax.set_xticks(ticks)
            yy = ax.get_ylim()
            ax.set_ylim([yy[0], yy[1] + np.max(self.info[0]) * 1 / 3])
            ax.yaxis.set_major_locator(MaxNLocator(integer=True))
            ax.locator_params(axis='y', nbins=3)

            for count, x in zip(self.info[0], self.info[1]):
                percent = '%0.0f%%' % (100 * float(count) / self.info[0].sum())
                ax.annotate(percent, xy=(x+0.5, count), va='bottom', ha='center')

        else:
            self.info = ax.hist(self.DF[v])
            ax.set_title(v+'\nAvg = %.2f +/- %.2f' % (self.DF[v].mean(), self.DF[v].std()))
            ax.yaxis.set_major_locator(MaxNLocator(integer=True))
            ax.locator_params(axis='y', nbins=3)
            ax.xaxis.set_major_locator(MaxNLocator(5))


        toolbar = NavigationToolbar2TkAgg(self.canvas, self)
        toolbar.update()
        toolbar.grid(row=10, column=0, sticky='ewns', columnspan=7)

        self.v = v
        self.canvas.draw()

    def adjust_bins(self):

        bins = np.arange(float(self.bin_min.get()), float(self.bin_max.get())+1, float(self.bin_spc.get()))
        print("New Bins", bins)
        self.fig.clf()
        ax = plt.gca()
        self.info = ax.hist(self.DF[self.v], bins=bins)
        ax.set_title(self.v + '\nAvg = %.2f +/- %.2f' % (self.DF[self.v].mean(), self.DF[self.v].std()))
        ax.yaxis.set_major_locator(MaxNLocator(integer=True))
        ax.locator_params(axis='y', nbins=3)
        ax.xaxis.set_major_locator(MaxNLocator(5))
        self.canvas.draw()

    def on_exit(self):
        """Closes all windows if the user selects okay, does not pretty print the xml file"""
        self.destroy()
        app.quit()

class FileSelectionApp(tk.Tk):
    """Application to display all of the trials in a list"""

    def __init__(self):
        tk.Tk.__init__(self)
        self.app_data = {'name': tk.StringVar}
        home = os.path.expanduser('~')
        for dirname, subdirList, fileList in os.walk(home):
            for dir in subdirList:
                if "MULTIS_test" in dir and "studies" not in dirname:
                    print(dirname + dir)
                    multis_dir = dirname + '/' + dir

        try:
            multis_dir
        except NameError:
            multis_dir = tkFileDialog.askdirectory(title='Locate MULTIS_test directory')

        self.directory = multis_dir
        self.getSubjects()
        self.title('Select Files')
        self.df = pandas.DataFrame(data=None, columns=('Age (yrs)', 'Gender', 'Ethnicity', 'Race', 'Height (cm)', 'Mass (kg)', 'BMI', 'Activity', 'UA_l (cm)', 'UA_dc (cm)', 'UA_cc (cm)', 'UA_pc (cm)', 'LA_l (cm)', 'LA_dc (cm)', 'LA_cc (cm)', 'LA_pc (cm)', 'UL_l (cm)', 'UL_dc (cm)', 'UL_cc (cm)', 'UL_pc (cm)', 'LL_l (cm)', 'LL_dc (cm)', 'LL_cc (cm)', 'LL_pc (cm)'))

        self.columnconfigure(0, weight=1)

        self.var = []
        self.cbuts = []
        self.i = 0
        for item in self.subFiles:
            self.var.append(tk.IntVar())
            self.cbuts.append(tk.Checkbutton(self, text=item[0:-4], variable=self.var[self.i]))
            self.cbuts[-1].grid(column = 0, row=self.i, sticky='w')
            self.i +=1

        self.minsize(200, 100/(self.i))
        tk.Button(self, text="Okay", command=self.checkBoxes).grid(row=1, column =1, sticky='ens')
        tk.Button(self, text="Select All", command=self.SelectAll).grid(row=0, column=1, sticky='ens')

    def yview(self, *args):
        apply(self.yview, args)

    def checkBoxes(self):
        count = 0
        for bb in self.var:
            if bb.get() == 1:
                self.saveData(count)
            count += 1

        #Build Function to create report
        self.avg = self.df.mean()
        self.stdDev = self.df.std()
        self.df[["Gender", "Ethnicity", "Race", "Activity"]] = self.df[["Gender", "Ethnicity", "Race", "Activity"]].astype(int)
        # self.df.to_csv('/home/morrile2/Documents/MULTIS Data/MULTIS_test/ThickSumFigsNew/001_Demographics_anthropometrics064.csv')
        # print(self.df.dtypes)
        # print('Results')
        # print(self.avg, self.stdDev)

        self.destroy()
        # self.plot_data()
        self.quit()

    def saveData(self, count):
        xml_name = self.dir[count]+'/'+self.subFiles[count]
        doc = ET.parse(xml_name)
        root = doc.getroot()

        subjData = root.find("Subject_Data")
        Anatomical = subjData.find("Anatomical_Measurements")
        demographics = subjData.find("Demographics")
        HeightMass = subjData.find("Height_and_Mass")
        Activity = subjData.find("Activity_Level")

        age = int(demographics.find("Age").text)
        gender = int(demographics.find("Gender").text)
        ethnicity = int(demographics.find("Ethnicity").text)
        race = int(demographics.find("Race").text)

        height = float((HeightMass.find("Height")).find("Magnitude").text)
        mass = float((HeightMass.find("Mass")).find("Magnitude").text)

        if (HeightMass.find("Height")).find("Units").text == '31' and (HeightMass.find("Mass")).find("Units").text == '20':
            BMI = mass/((height/100)**2)
        else:
            tkMessageBox.showerror("Error", "BMI could not be calculated because either height or mass had the wrong units")

        activity = int((Activity.find("Lifestyle")).text)

        column_names = ['Age (yrs)', 'Gender', 'Ethnicity', 'Race', 'Height (cm)', 'Mass (kg)', 'BMI', 'Activity']
        df_demo = pandas.DataFrame([[age, gender, ethnicity, race, height, mass, BMI, activity]], columns=column_names)

        for child in Anatomical:
            if child.attrib['type'] == 'Cluster':
                for cl in child.findall("Cluster"):
                    if cl._children[0].text == 'Length':
                        length = float(cl._children[1].text)
                    elif cl._children[0].text == 'Distal Circumference':
                        circ_d = float(cl._children[1].text)
                    elif cl._children[0].text == 'Central Circumference':
                        circ_c = float(cl._children[1].text)
                    elif cl._children[0].text == 'Proximal Circumference':
                        circ_p = float(cl._children[1].text)

                if child.tag == 'Upper_Arm':
                    column_names = ['UA_l (cm)', 'UA_dc (cm)', 'UA_cc (cm)', 'UA_pc (cm)']
                    df_UA = pandas.DataFrame([[length, circ_d, circ_c, circ_p]], columns=column_names)
                elif child.tag == 'Lower_Arm':
                    column_names = ['LA_l (cm)', 'LA_dc (cm)', 'LA_cc (cm)', 'LA_pc (cm)']
                    df_LA = pandas.DataFrame([[length, circ_d, circ_c, circ_p]], columns=column_names)
                elif child.tag == 'Upper_Leg':
                    column_names = ['UL_l (cm)', 'UL_dc (cm)', 'UL_cc (cm)', 'UL_pc (cm)']
                    df_UL = pandas.DataFrame([[length, circ_d, circ_c, circ_p]], columns=column_names)
                elif child.tag == 'Lower_Leg':
                    column_names = ['LL_l (cm)', 'LL_dc (cm)', 'LL_cc (cm)', 'LL_pc (cm)']
                    df_LL = pandas.DataFrame([[length, circ_d, circ_c, circ_p]], columns=column_names)

        self.df = self.df.append(pandas.concat([df_demo, df_UA, df_LA, df_UL, df_LL], axis=1), ignore_index=True)
        return self.df


    def SelectAll(self):
        print("Select ALL")
        for bb in self.var:
            bb.set(1)
        for c in self.cbuts:
            c.select()


    def getSubjects(self):
        self.subFiles = []
        self.dir = []
        for dirname,subdirList,fileList in os.walk(self.directory):
            for filename in fileList:
                if ".xml" in filename.lower() and len(filename) == 15 and filename[0:6] == "MULTIS":
                    self.subFiles.append(filename)
                    self.dir.append(dirname)
        sortedTrials = sorted(zip(self.subFiles, self.dir))
        self.subFiles, self.dir = zip(*sortedTrials)



if __name__ == "__main__":

    app = DisplayGraphApp()
    app.mainloop()
</pre></body></html>