GUI for bayes_gp_plain.py

Download script from bayes_gp_gui.py
Related files:
bayes_gp_gui.ini


import sys
import os
import tkinter

from tklib.tkutils import getarg, getintarg, getfloatarg, pint, pfloat, terminate
from tklib.tkparams import tkParams
from tklib.tkgui.tkapplication_gui import tkApplication_GUI
import tklib.tkgui.tktkinter as tktkinter

import bayes_gp_plain as c_engine


"""
GUI for bayes_gp_plain.py
"""



usage_str = '''
"(i) usage: python {}".format(sys.argv[0])
'''[1:-1]


#=============================
# Treat argments
#=============================
def usage(app):
#    cparams = app.get_params()
#    app.usage(infile = cparams.infile)
    for s in app.usage_str.split('\n'):
        cmd = 'print({})'.format(s.rstrip())
        eval(cmd)

def initialize(app, cparams):
#================================
# Global variables
#================================
    ctkvars = app.tkvars
    tkvars = ctkvars.get_param_dict()

# Non-configurable configuration
    app.prm_file_type = [('prm file', '*.prm')]
    app.data_file_type = [('data file', '*.csv')]

# Configurable configuration
    config = tkParams()
    app.configparams = config
    config.debug = 0
    config.print_level = 0
    config.confirm_on_exit = True
    config.inifile = os.path.splitext(app.script_path)[0] + '.ini'
    config.ini_dir = os.path.abspath(os.path.dirname(__file__))
    config.minsize = [200, 200]
    config.geometry = "1000x600"
    config.left_pane_width = 500

# Define var types in config for auto type conversion in config.read_parameters()
    config.editor_path = ''
    config.infile = ''
    config.outfile = ''
    config.score_mode = ''

#    print("")
#    print(f"Read ini file from [config.inifile]")
#    config.read_parameters(path = config.inifile)
#    config.print_parameters(heading = "Configure")


def update_vars(app, cparams):
    argv = app.argv
#    if len(argv) <= 1:
#        app.terminate(usage = usage)

#    cparams.infile = getarg(1, cparams.infile)


def create_menu(app, config, cparams, root_window):
    menu_bar = app.create_menu()

    menu_file = tktkinter.Menu(app, menu_bar, tearoff = 0)
    menu_file.add_command(label = 'Open', accelerator = 'Ctrl+O',
                command = lambda: data_path_button_click(app, tkvars))
    menu_file.add_command(label='exit', accelerator='Alt+E', command = lambda: app.on_closing())
    menu_bar.add_cascade(label = 'File', menu = menu_file)

    menu_tool = tkinter.Menu(menu_bar, tearoff = 0)
    menu_tool.add_command(label = 'Setup', accelerator = 'Ctrl+u',
                command = app.dialog_setup)
    menu_bar.add_cascade(label = 'Tool', menu = menu_tool)

    return menu_bar

def create_toolbar(app, config, cparams, root_window):
    def toolbar_clickevent(event):
        pass

    tool_bar = app.create_toolbar(bg = 'blue')

    setupButton = tktkinter.Button(app, tool_bar, text = "Setup",
                    command = lambda: app.dialog_setup(entry_width = 50, is_print = True))
    setupButton.pack(side = tkinter.LEFT, anchor = 'w', padx = 1, pady = 0)

    exitButton = tktkinter.Button(app, tool_bar, text = 'Exit', command = lambda: app.on_closing(), anchor = tkinter.NW)
    exitButton.pack(side = tkinter.LEFT, anchor = 'w', padx = 1, pady = 0)

def input_path_button_click(app, cparams, tkvars,
                varname = "infile", parameterpath_varname = "prmpath", outputpath_varname = "outfile",
                file_type = [("Excel", "*.xlsx"), ("All", "*.*")], ini_dir = '.'):
    selpath = tkinter.filedialog.askopenfilename(filetypes = file_type, initialdir = ini_dir)

    header, ext = os.path.splitext(selpath)
    filebody = os.path.basename(header)
    cparams.outfile = header + f'-predict.xlsx'
    cparams.parameter_path = header + '.prm'

    tkvars[varname].set(selpath)
    tkvars[outputpath_varname].set(cparams.outfile)
#    tkvars[parameterpath_varname].set(cparams.parameter_path)

def copy_tkvars(app, cparams, tkvars):
    config = app.configparams

#    for key in ["script_path", "prmpath", "infile", "outfile", "max_num_probes", "num_search_each", "num_rand_basis", "interval", "score_mode"]:
    for key in ["program_path", "infile", "outfile",
                "max_num_probes", "num_search_each", "num_rand_basis", "interval", "score_mode",
                "fontsize", "legend_fontsize"]:
        cparams.set_attr(key, tkvars[key].get())

    for key in ["program_path", "infile", "outfile", "fontsize", "legend_fontsize"]:
        config.set_attr(key, tkvars[key].get())

    cparams.set_attr('figsize', [tkvars['fig_width'].get(), tkvars['fig_height'].get()])

def copy_config(app, cparams, config):
    keys0 = config.__dict__.keys()
    for key in cparams.__dict__.keys():
        if key in keys0:
            cparams.set_attr(key, cparams.get(key, None))

def create_frame2(app, config, cparams, parent_notebook):
    config = app.configparams
    ctkvars = app.tkvars
    tkvars = ctkvars.get_param_dict()

    page1_frame = tktkinter.Frame(app, parent_notebook, bg='dim gray')
    page1_frame.pack()
    parent_notebook.add(page1_frame, text = 'Configure')
    notebook_frame = page1_frame

    applications = app.get_external_apps(config.get("editor_path", None))

    path_grid_frame = tkinter.Frame(page1_frame)

# Script path frame
    tkvars["program_path"] = tkinter.StringVar(value = cparams.get("program_path", config.get("program_path", "")))
    prm_path_frame = tktkinter.PathFrame(app, page1_frame,
        frame_args = {'bg': 'white'},
        head_label_args = {'text': 'Script:', 'anchor': tkinter.E},
        entry_args = {'textvariable': ['program_path', tkvars["program_path"]], 'width': 60},
        button_args = {'text': 'open', "width": 4, 'font': ("", 10),
                           'command': lambda: tktkinter.path_button_click(app, tkvars["program_path"],
                                                    file_type = [("python", "*.py"), ("All", "*.*")], ini_dir = '.')
                          },
        edit_button_args = {'text': 'ed', "width": 2, 'font': ("", 10)},
        optionmenu_args = {'textvariable': ['app_path', tkinter.StringVar(value = 'app')],
                             "width": 3, 'font': ("", 10),
                             'values': applications},
        shell_button_args = {'text': 'sh', "width": 2, 'font': ("", 10)},
        gridframe = path_grid_frame,
        grid_args = { "sticky": tkinter.E },
        igridrow = 0
        )
#    prm_path_frame.pack(side = tkinter.TOP, anchor = 'w', padx = 2, pady = 2)

    return notebook_frame

def create_frame(app, config, cparams, parent_notebook):
    config = app.configparams
    ctkvars = app.tkvars
    tkvars = ctkvars.get_param_dict()

    page1_frame = tktkinter.Frame(app, parent_notebook, bg='dim gray')
    page1_frame.pack()
    parent_notebook.add(page1_frame, text = 'Analyze')
    notebook_frame = page1_frame

    applications = app.get_external_apps(config.get("editor_path", None))

    path_grid_frame = tkinter.Frame(page1_frame)


# Parameter path frame
    """
    tkvars["prmpath"] = tkinter.StringVar(value = cparams.get("prmpath", ""))
    prm_path_frame = tktkinter.PathFrame(app, page1_frame,
        frame_args = {'bg': 'white'},
        head_label_args = {'text': 'Parameter:', 'anchor': tkinter.E},
        entry_args = {'textvariable': ['prmpath', tkvars["prmpath"]], 'width': 60},
        button_args = {'text': 'open', "width": 4, 'font': ("", 10),
                            'command': lambda: tktkinter.path_button_click(app, tkvars["prmpath"],
                                                    file_type = [("prm", "*.prm"), ("All", "*.*")], ini_dir = '.')
                          },
        edit_button_args = {'text': 'ed', "width": 2, 'font': ("", 10)},
        optionmenu_args = {'textvariable': ['app_path', tkinter.StringVar(value = 'app')],
                             "width": 3, 'font': ("", 10),
                             'values': applications},
        shell_button_args = {'text': 'sh', "width": 2, 'font': ("", 10)},
        gridframe = path_grid_frame,
        grid_args = { "sticky": tkinter.E },
        igridrow = 1
        )
#    prm_path_frame.pack(side = tkinter.TOP, anchor = 'w', padx = 2, pady = 2)
    """

# Input path frame
    tkvars["infile"] = tkinter.StringVar(value = cparams.get("infile", config.get("infile", "")))
    input_path_frame = tktkinter.PathFrame(app, page1_frame,
        frame_args = {'bg': 'white'},
        head_label_args = {'text': 'Input:', 'anchor': tkinter.E},
        entry_args = {'textvariable': ['inputpath', tkvars["infile"]], 'width': 60},
        button_args = {'text': 'open', "width": 4, 'font': ("", 10),
                            'command': lambda: input_path_button_click(app, cparams, tkvars)
                          },
        edit_button_args = {'text': 'ed', "width": 2, 'font': ("", 10)},
        optionmenu_args = {'textvariable': ['app_path', tkinter.StringVar(value = 'app')],
                             "width": 3, 'font': ("", 10),
                             'values': applications},
        shell_button_args = {'text': 'sh', "width": 2, 'font': ("", 10)},
        gridframe = path_grid_frame,
        grid_args = { "sticky": tkinter.E },
        igridrow = 2
        )
#    input_path_frame.pack(side = tkinter.TOP, anchor = 'w', padx = 2, pady = 2)

# Output path frame
    tkvars["outfile"] = tkinter.StringVar(value = cparams.get("outfile", config.get("outfile", "")))
    output_path_frame = tktkinter.PathFrame(app, page1_frame,
        frame_args = {'bg': 'white'},
        head_label_args = {'text': 'Output:', 'anchor': tkinter.E},
        entry_args = {'textvariable': ['outputpath', tkvars["outfile"]], 'width': 60},
#        button_args = {'text': 'Save as', "width": 10, 'font': ("", 10),
#                            'command': lambda: tktkinter.path_button_click(app, tkvars["outfile"],
#                                                    file_type = [("Excel", "*.xlsx"), ("All", "*.*")], ini_dir = '.')
#                          },
#        save_button_args = {'text': 'Save', "width": 6, 'font': ("", 10),
#                            'command': lambda: tktkinter.path_button_click(app, tkvars["outfile"],
#                                                    file_type = [("Excel", "*.xlsx"), ("All", "*.*")], ini_dir = '.'),
#                            'igridcol': 4,
#                          },
#        edit_button_args = {'text': 'ed', "width": 2, 'font': ("", 10)},
        optionmenu_args = {'textvariable': ['app_path', tkinter.StringVar(value = 'app')],
                             "width": 3, 'font': ("", 10),
                             'values': applications},
        shell_button_args = {'text': 'sh', "width": 2, 'font': ("", 10)},
        gridframe = path_grid_frame,
        grid_args = { "sticky": tkinter.E },
        igridrow = 3
        )
#    output_path_frame.pack(side = tkinter.TOP, anchor = 'w', padx = 2, pady = 2)

    def make_var_box(app, cparams, tkvars, parent, grid_frame,
                    vartype = 'int', varname = 'none', defval = 0,
                    label = 'no label',
                    values = None,
                    from_ = 1, to = 100, increment = 10, box_width = 6, igridrow = 0):
        if vartype == 'int':
            tkvars[varname] = tkinter.IntVar(value = cparams.get("varname", defval))
            textbox_args = {'spinbox_args':
                            {'textvariable': [varname, tkvars[varname]], 'width': box_width,
                             'from': from_, 'to': to, 'increment': increment}
                       }
        elif vartype == 'str':
            tkvars[varname] = tkinter.StringVar(value = cparams.get("varname", defval))
            textbox_args = {'entry_args':
                            {'textvariable': ['score_mode', tkvars["score_mode"]], 'width': box_width}
                       }
        elif vartype == 'double':
            tkvars[varname] = tkinter.DoubleVar(value = cparams.get("varname", defval))
            textbox_args = {'entry_args':
                            {'textvariable': ['score_mode', tkvars["score_mode"]], 'width': box_width}
                       }

        if values is None:
            frame = tktkinter.LabelEntryFrame(app, parent,
                frame_args = {'bg': 'white'},
                label_args = {'text': f'{label}:', 'anchor': tkinter.E},
#                entry_args = {'textvariable': ['score_mode', tkvars["score_mode"]], 'width': box_width},
#                            combobox_args = None,
#                spinbox_args = {'textvariable': [varname, tkvars[varname]], 'width': box_width,
#                            'from': from_, 'to': to, 'increment': increment},
                **textbox_args,
                gridframe = grid_frame,
                grid_args = { "sticky": tkinter.E },
                igridrow = igridrow
                )
        else:
            frame = tktkinter.PathFrame(app, parent,
                frame_args = {'bg': 'white'},
                head_label_args = {'text': f'{label}:', 'anchor': tkinter.E},
                combobox_args = {'textvariable': [varname, tkvars[varname]],
                                 'values': values,
                                 'width': 6},
                gridframe = grid_frame,
                grid_args = { "sticky": tkinter.E },
                igridrow = igridrow
                )

        frame.pack(side = tkinter.TOP, anchor = 'w', padx = 2, pady = 2)

# Button
    def analyze(app, cparams, tkvars):
        copy_tkvars(app, cparams, tkvars)
        print("")
        print("Execute analysis")
        c_engine.execute(app, cparams, wait_by_input = False)

    button_frame = tkinter.Frame(page1_frame)
    button1 = tktkinter.Button(app, button_frame, text = 'analyze', width = 8, font = ("", 16),
                        command = lambda: analyze(app, cparams, tkvars))
    button_frame.pack(side = tkinter.TOP, anchor = 'w', padx = 2, pady = 2)

# Parameter block
    vars_grid_frame = tkinter.Frame(page1_frame)
    varname = "max_num_probes"
    frame = make_var_box(app, cparams, tkvars, page1_frame, vars_grid_frame,
                         vartype = 'int', varname = varname, label = varname,
                         defval = config.get(varname, 1), from_ = 1, to = 100, increment = 5, box_width = 6, igridrow = 0)
    varname = "num_search_each"
    frame = make_var_box(app, cparams, tkvars, page1_frame, vars_grid_frame,
                         vartype = 'int', varname = varname, label = varname,
                         defval = config.get(varname, 1), from_ = 1, to = 100, increment = 5, box_width = 6, igridrow = 1)
    varname = "num_rand_basis"
    frame = make_var_box(app, cparams, tkvars, page1_frame, vars_grid_frame,
                         vartype = 'int', varname = varname, label = varname,
                         defval = config.get(varname, 200), from_ = 1, to = 5000, increment = 50, box_width = 6, igridrow = 2)
    varname = "interval"
    frame = make_var_box(app, cparams, tkvars, page1_frame, vars_grid_frame,
                         vartype = 'int', varname = varname, label = varname,
                         defval = config.get(varname, 0), from_ = 1, to = 5000, increment = 10, box_width = 6, igridrow = 3)
    varname = "score_mode"
    frame = make_var_box(app, cparams, tkvars, page1_frame, vars_grid_frame,
                         vartype = 'str', varname = varname, label = varname,
                         defval = config.get(varname, 'EI'), values = ['EI', 'PI', 'TS'], box_width = 6, igridrow = 4)

# Graph parameter block
    graph_grid_frame = tkinter.Frame(page1_frame)
    varname = "fig_width"
    frame = make_var_box(app, cparams, tkvars, page1_frame, graph_grid_frame,
                         vartype = 'int', varname = varname, label = varname,
                         defval = config.get(varname, 12), from_ = 1, to = 100, increment = 1, box_width = 6, igridrow = 4)
    varname = "fig_height"
    frame = make_var_box(app, cparams, tkvars, page1_frame, graph_grid_frame,
                         vartype = 'int', varname = varname, label = varname,
                         defval = config.get(varname, 8), from_ = 1, to = 100, increment = 1, box_width = 6, igridrow = 5)
    varname = "fontsize"
    frame = make_var_box(app, cparams, tkvars, page1_frame, graph_grid_frame,
                         vartype = 'int', varname = varname, label = varname,
                         defval = config.get(varname, 16), from_ = 1, to = 100, increment = 1, box_width = 6, igridrow = 6)
    varname = "legend_fontsize"
    frame = make_var_box(app, cparams, tkvars, page1_frame, graph_grid_frame,
                         vartype = 'int', varname = varname, label = varname,
                         defval = config.get(varname, 8), from_ = 1, to = 100, increment = 1, box_width = 6, igridrow = 7)

# Maintenance buttons
    def print_tkvars_info(app, cparams, tkvars):
        print("tkvars")
        for key in tkvars.keys():
            if type(tkvars[key]) is list:
                print(f" {key}:", tkvars[key])
            elif tkvars[key] is None:
                pass
            elif type(tkvars[key]) is int or type(tkvars[key]) is float or type(tkvars[key]) is str:
                print(f" {key}:", tkvars[key])
            else:
                print(f" {key}:", tkvars[key].get())

    def print_cparams_info(app, cparams, tkvars):
        print("cparams")
        copy_tkvars(app, cparams, tkvars)
        cparams.print_parameters()

    button_frame2 = tkinter.Frame(page1_frame)
    button1.pack(side = tkinter.LEFT)
    button2 = tktkinter.Button(app, button_frame2, text = 'cparams', width = 8, font = ("", 16),
                        command = lambda: print_cparams_info(app, cparams, tkvars))
    button2.pack(side = tkinter.LEFT)
    button2 = tktkinter.Button(app, button_frame2, text = 'tkvars', width = 8, font = ("", 16),
                        command = lambda: print_tkvars_info(app, cparams, tkvars))
    button2.pack(side = tkinter.LEFT)
    button_frame2.pack(side = tkinter.TOP, anchor = 'w', padx = 2, pady = 2)

    return notebook_frame

def create_window(app, config, cparams):
    ctkvars = app.tkvars
    tkvars = ctkvars.get_param_dict()

    root_window = app.create_window(title = sys.argv[0], geometry = config.geometry, minsize = config.minsize)
    menu_bar = create_menu(app, config, cparams, root_window)
    tool_bar = create_toolbar(app, config, cparams, root_window)
#    panes = app.add_root_panes(root = root_window, type = "pane2", sashwidth = 2, left_pane_width = 600)
#    main_pane, left_notebook, right_notebook = panes
    panes = app.add_root_panes(type = "pane1", sashwidth = 2)
    left_notebook = panes[0]

    ltabframe1 = create_frame(app, config, cparams, left_notebook)
    ltabframe2 = create_frame2(app, config, cparams, left_notebook)

# 起動時引数でデータ/設定ファイル名を受け取る
    """
    argv = sys.argv
    if len(argv) >= 2:
        cparams.path = argv[1]
        cparams.data_file = os.path.splitext(cparams.path)[0] + '.csv'
        cparams.prmpath = os.path.splitext(cparams.path)[0] + '.prm'
        tkvars['prmpath'].set(cparams.prmpath)
        tkvars['datapath'].set(cparams.data_file)
        read_parameter_file(cparams.prmpath, app, tkvars)
        if cparams.get("data_file", None) is not None:
            read_data_file(cparams.data_file, app, tkvars)
            tkvars['x0'].set(cparams.xrange[0])
            tkvars['x1'].set(cparams.xrange[1])
    """

    app.mainloop()

def main():
#==================================================================
# Initialize parameters
#==================================================================
    app = tkApplication_GUI(usage_str = usage_str, globals = globals(), locals = locals())
    cparams = app.get_params()
    ctkvars = app.tkvars
    tkvars = ctkvars.get_param_dict()

# Initialize minimum parameters
    initialize(app, cparams)

# Update vars by command line argments
    update_vars(app, cparams)

    config = app.configparams
    config.read_parameters(path = config.inifile)

    create_window(app, config, cparams)

    copy_tkvars(app, cparams, tkvars)
    copy_tkvars(app, config, tkvars)
    config.geometry = app.root_window_geometry
    print("")
    print(f"Save configuration to [{config.inifile}]")
    config.save_parameters(path = config.inifile, section = 'Configure', sort_by_keys = True, IsPrint = False)

    if tkvars.get("prmpath", None) is not None:
        cparams.prmpath = tkvars["prmpath"].get() #os.path.splitext(cparams.path)[0] + '.prm'
        if cparams.prmpath != '':
            print(f"Save parameters to [{cparams.prmpath}]")
            ret = cparams.save_parameters(cparams.prmpath, section = 'Parameters',
                    sort_by_keys = True, IsPrint = False, update_commandline = False)
            if not ret:
                app.terminate(f"Error in main(): Cannot write to [{cparams.prmpath}]", usage = usage)

    app.terminate()


if __name__ == "__main__":
    main()