Exemple #1
0
    def update_config(self):

        self.config = PRACMLNConfig()
        self.config["use_emln"] = self.use_emln.get()
        self.config['mln'] = self.mln_container.selected_file.get().strip(
        ).lstrip('*')
        self.config['emln'] = self.emln_container.selected_file.get().strip(
        ).lstrip('*')
        self.config["db"] = self.db_container.selected_file.get().strip(
        ).lstrip('*')
        self.config["method"] = InferenceMethods.id(
            self.selected_method.get().strip())
        self.config["params"] = self.params.get().strip()
        self.config["queries"] = self.query.get()
        self.config["output_filename"] = self.output_filename.get().strip()
        self.config["cw"] = self.closed_world.get()
        self.config["cw_preds"] = self.cwPreds.get()
        self.config['profile'] = self.profile.get()
        self.config['logic'] = self.selected_logic.get()
        self.config['grammar'] = self.selected_grammar.get()
        self.config['multicore'] = self.multicore.get()
        self.config['save'] = self.save.get()
        self.config['ignore_unknown_preds'] = self.ignore_unknown_preds.get()
        self.config['verbose'] = self.verbose.get()
        self.config['window_loc'] = self.master.winfo_geometry()
        self.config['dir'] = self.dir
        self.project.queryconf = PRACMLNConfig()
        self.project.queryconf.update(self.config.config.copy())
Exemple #2
0
    def update_config(self):
        out('update_config')

        self.config = PRACMLNConfig()
        self.config['mln'] = self.mln_container.selected_file.get().strip().lstrip('*')
        self.config["db"] = self.db_container.selected_file.get().strip().lstrip('*')
        self.config["output_filename"] = self.output_filename.get()
        self.config["params"] = self.params.get().strip()
        self.config["method"] = LearningMethods.id(self.selected_method.get().strip())
        self.config["pattern"] = self.pattern.get()
        self.config["use_prior"] = int(self.use_prior.get())
        self.config["prior_mean"] = self.priorMean.get()
        self.config["prior_stdev"] = self.priorStdDev.get()
        self.config["incremental"] = int(self.incremental.get())
        self.config["shuffle"] = int(self.shuffle.get())
        self.config["use_initial_weights"] = int(self.use_initial_weights.get())
        self.config["qpreds"] = self.queryPreds.get().strip()
        self.config["epreds"] = self.evidencePreds.get().strip()
        self.config["discr_preds"] = self.discrPredicates.get()
        self.config['logic'] = self.selected_logic.get()
        self.config['grammar'] = self.selected_grammar.get()
        self.config['multicore'] = self.multicore.get()
        self.config['profile'] = self.profile.get()
        self.config['verbose'] = self.verbose.get()
        self.config['ignore_unknown_preds'] = self.ignore_unknown_preds.get()
        self.config['ignore_zero_weight_formulas'] = self.ignore_zero_weight_formulas.get()
        self.config['save'] = self.save.get()
        self.config["output_filename"] = self.output_filename.get().strip()
        self.project.learnconf = PRACMLNConfig()
        self.project.learnconf.update(self.config.config.copy())
Exemple #3
0
def main():
    logger.level = logs.DEBUG

    usage = 'PRACMLN Learning Tool'

    parser = argparse.ArgumentParser(description=usage)
    parser.add_argument("--run", action="store_true", dest="run", default=False, help="run last configuration without showing gui")
    parser.add_argument("-d", "--dir", dest="directory", action='store', help="the directory to start the tool from", metavar="FILE", type=str)
    parser.add_argument("-i", "--mln-filename", dest="mlnarg", action='store', help="input MLN filename", metavar="FILE", type=str)
    parser.add_argument("-t", "--db-filename", dest="dbarg", action='store', help="training database filename", metavar="FILE", type=str)
    parser.add_argument("-o", "--output-file", dest="outputfile", action='store', help="output MLN filename", metavar="FILE", type=str)

    args = parser.parse_args()
    opts_ = vars(args)

    # run learning task/GUI
    root = Tk()
    conf = PRACMLNConfig(DEFAULT_CONFIG)
    app = MLNLearnGUI(root, conf, directory=os.path.abspath(args.directory) if args.directory is not None else None)

    if args.run:
        logger.debug('running mlnlearn without gui')
        app.learn(savegeometry=False, options=opts_)
    else:
        root.mainloop()
Exemple #4
0
def main():
    logger.level = logs.DEBUG

    usage = 'PRACMLN Query Tool'

    parser = argparse.ArgumentParser(description=usage)
    parser.add_argument("-i", "--mln", dest="mlnarg", help="the MLN model file to use")
    parser.add_argument("-d", "--dir", dest="directory", action='store', help="the directory to start the tool from", metavar="FILE", type=str)
    parser.add_argument("-x", "--emln", dest="emlnarg", help="the MLN model extension file to use")
    parser.add_argument("-q", "--queries", dest="queryarg", help="queries (comma-separated)")
    parser.add_argument("-e", "--evidence", dest="dbarg", help="the evidence database file")
    parser.add_argument("-r", "--results-file", dest="outputfile", help="the results file to save")
    parser.add_argument("--run", action="store_true", dest="run", default=False, help="run with last settings (without showing GUI)")

    args = parser.parse_args()
    opts_ = vars(args)

    root = Tk()
    conf = PRACMLNConfig(DEFAULT_CONFIG)
    app = MLNQueryGUI(root, conf, directory=os.path.abspath(args.directory) if args.directory else None)

    if args.run:
        logger.debug('running mlnlearn without gui')
        app.infer(savegeometry=False, options=opts_)
    else:
        root.mainloop()
Exemple #5
0
    def update_config(self):
        out('update_config')

        self.config = PRACMLNConfig()
        self.config['mln'] = self.mln_container.selected_file.get().strip().lstrip('*')
        self.config["db"] = self.db_container.selected_file.get().strip().lstrip('*')
        self.config["output_filename"] = self.output_filename.get()
        self.config["params"] = self.params.get().strip()
        self.config["method"] = LearningMethods.id(self.selected_method.get().strip())
        self.config["pattern"] = self.pattern.get()
        self.config["use_prior"] = int(self.use_prior.get())
        self.config["prior_mean"] = self.priorMean.get()
        self.config["prior_stdev"] = self.priorStdDev.get()
        self.config["incremental"] = int(self.incremental.get())
        self.config["shuffle"] = int(self.shuffle.get())
        self.config["use_initial_weights"] = int(self.use_initial_weights.get())
        self.config["qpreds"] = self.queryPreds.get().strip()
        self.config["epreds"] = self.evidencePreds.get().strip()
        self.config["discr_preds"] = self.discrPredicates.get()
        self.config['logic'] = self.selected_logic.get()
        self.config['grammar'] = self.selected_grammar.get()
        self.config['multicore'] = self.multicore.get()
        self.config['profile'] = self.profile.get()
        self.config['verbose'] = self.verbose.get()
        self.config['ignore_unknown_preds'] = self.ignore_unknown_preds.get()
        self.config['ignore_zero_weight_formulas'] = self.ignore_zero_weight_formulas.get()
        self.config['save'] = self.save.get()
        self.config["output_filename"] = self.output_filename.get().strip()
        self.project.learnconf = PRACMLNConfig()
        self.project.learnconf.update(self.config.config.copy())
    def activate_model(self,database, mln):
        """
        Returns the learned mln
        --Inputs--
        database and mln objects in MLN format
        """

        DEFAULT_CONFIG = os.path.join(locs.user_data, global_config_filename)
        conf = PRACMLNConfig(DEFAULT_CONFIG)

        config = {}
        config['verbose'] = True
        config['discr_preds'] = 0
        config['db'] = database
        config['mln'] = mln
        config['ignore_zero_weight_formulas'] = 1    #0
        config['ignore_unknown_preds'] = True   #0
        config['incremental'] = 1   #0
        config['grammar'] = 'PRACGrammar' #StandardGrammar
        config['logic'] = 'FirstOrderLogic'
        config['method'] = 'BPLL'    # BPLL (BPLL, 'pseudo-log-likelihood')
        config['optimizer'] = 'bfgs'
        config['multicore'] = False
        config['profile'] = 0
        config['shuffle'] = 0
        config['prior_mean'] = 0
        config['prior_stdev'] = 10   # 5
        config['save'] = True
        config['use_initial_weights'] = 0
        config['use_prior'] = 0


        config['infoInterval'] = 500
        config['resultsInterval'] = 1000
        conf.update(config)

        print('training...')
        learn = MLNLearn(conf, mln=mln, db=database)

        result = learn.run()
        print('finished...')
        return result
Exemple #7
0
    def activate_model(self, database, mln):

        DEFAULT_CONFIG = os.path.join(locs.user_data, global_config_filename)
        conf = PRACMLNConfig(DEFAULT_CONFIG)

        config = {}
        config['verbose'] = True
        config['discr_preds'] = 0
        config['db'] = database
        config['mln'] = mln
        config['ignore_zero_weight_formulas'] = 1  # 0
        config['ignore_unknown_preds'] = True  # 0
        config['incremental'] = 1  # 0
        config['grammar'] = 'StandardGrammar'
        config['logic'] = 'FirstOrderLogic'
        config['method'] = 'BPLL'  # BPLL
        config['multicore'] = False
        config['profile'] = 0
        config['shuffle'] = 0
        config['prior_mean'] = 0
        config['prior_stdev'] = 10  # 5
        config['save'] = True
        config['use_initial_weights'] = 0
        config['use_prior'] = 0
        # config['output_filename'] = 'learnt.dbpll_cg.student-new-train-student-new-2.mln'
        # 亲测无效, 此句没法储存.mln 档案
        config['infoInterval'] = 500
        config['resultsInterval'] = 1000
        conf.update(config)

        print('training...')
        learn = MLNLearn(conf, mln=mln, db=database)
        # learn.output_filename(r'C:\Users\anaconda3 4.2.0\test.mln')
        # 亲测无效, 此句没法储存.mln 档案
        result = learn.run()
        print('finished...')
        return result
Exemple #8
0
    def update_config(self):

        self.config = PRACMLNConfig()
        self.config["use_emln"] = self.use_emln.get()
        self.config['mln'] = self.mln_container.selected_file.get().strip().lstrip('*')
        self.config['emln'] = self.emln_container.selected_file.get().strip().lstrip('*')
        self.config["db"] = self.db_container.selected_file.get().strip().lstrip('*')
        self.config["method"] = InferenceMethods.id(self.selected_method.get().strip())
        self.config["params"] = self.params.get().strip()
        self.config["queries"] = self.query.get()
        self.config["output_filename"] = self.output_filename.get().strip()
        self.config["cw"] = self.closed_world.get()
        self.config["cw_preds"] = self.cwPreds.get()
        self.config['profile'] = self.profile.get()
        self.config['logic'] = self.selected_logic.get()
        self.config['grammar'] = self.selected_grammar.get()
        self.config['multicore'] = self.multicore.get()
        self.config['save'] = self.save.get()
        self.config['ignore_unknown_preds'] = self.ignore_unknown_preds.get()
        self.config['verbose'] = self.verbose.get()
        self.config['window_loc'] = self.master.winfo_geometry()
        self.config['dir'] = self.dir
        self.project.queryconf = PRACMLNConfig()
        self.project.queryconf.update(self.config.config.copy())
Exemple #9
0
class MLNLearnGUI:
    def __init__(self, master, gconf, directory=None):
        self.master = master

        self.initialized = False

        self.master.bind('<Return>', self.learn)
        self.master.bind('<Escape>', lambda a: self.master.quit())
        self.master.protocol('WM_DELETE_WINDOW', self.quit)

        # logo = Label(self.master, image=img)
        # logo.pack(side = "right", anchor='ne')
        self.dir = os.path.abspath(ifnone(directory, ifnone(gconf['prev_learnwts_path'], os.getcwd())))

        self.frame = Frame(master)
        self.frame.pack(fill=BOTH, expand=1)
        self.frame.columnconfigure(1, weight=1)

        row = 0
        # pracmln project options
        Label(self.frame, text='PRACMLN Project: ').grid(row=row, column=0,
                                                         sticky='ES')
        project_container = Frame(self.frame)
        project_container.grid(row=row, column=1, sticky="NEWS")

        # new proj file
        self.btn_newproj = Button(project_container, text='New Project...',
                                  command=self.new_project)
        self.btn_newproj.grid(row=0, column=1, sticky="WS")

        # open proj file
        self.btn_openproj = Button(project_container, text='Open Project...',
                                   command=self.ask_load_project)
        self.btn_openproj.grid(row=0, column=2, sticky="WS")

        # save proj file
        self.btn_saveproj = Button(project_container, text='Save Project',
                                   command=self.noask_save_project)
        self.btn_saveproj.grid(row=0, column=3, sticky="WS")

        # save proj file as...
        self.btn_saveproj = Button(project_container,
                                   text='Save Project as...',
                                   command=self.ask_save_project)
        self.btn_saveproj.grid(row=0, column=4, sticky="WS")

        # grammar selection
        row += 1
        Label(self.frame, text='Grammar: ').grid(row=row, column=0, sticky='E')
        grammars = ['StandardGrammar', 'PRACGrammar']
        self.selected_grammar = StringVar(master)
        self.selected_grammar.trace('w', self.settings_setdirty)
        l = OptionMenu(*(self.frame, self.selected_grammar) + tuple(grammars))
        l.grid(row=row, column=1, sticky='NWE')

        # logic selection
        row += 1
        Label(self.frame, text='Logic: ').grid(row=row, column=0, sticky='E')
        logics = ['FirstOrderLogic', 'FuzzyLogic']
        self.selected_logic = StringVar(master)
        self.selected_logic.trace('w', self.settings_setdirty)
        l = OptionMenu(*(self.frame, self.selected_logic) + tuple(logics))
        l.grid(row=row, column=1, sticky='NWE')

        # mln section
        row += 1
        Label(self.frame, text="MLN: ").grid(row=row, column=0, sticky='NE')
        self.mln_container = FileEditBar(self.frame, directory=self.dir,
                                         filesettings={'extension': '.mln', 'ftypes': [('MLN files', '.mln')]},
                                         defaultname='*unknown{}',
                                         importhook=self.import_mln,
                                         deletehook=self.delete_mln,
                                         projecthook=self.save_proj,
                                         filecontenthook=self.mlnfilecontent,
                                         fileslisthook=self.mlnfiles,
                                         selectfilehook=self.set_outputfilename,
                                         updatehook=self.update_mln,
                                         onchangehook=self.project_setdirty)
        self.mln_container.grid(row=row, column=1, sticky="NEWS")
        self.mln_container.editor.bind("<FocusIn>", self._got_focus)
        self.mln_container.columnconfigure(1, weight=2)
        self.frame.rowconfigure(row, weight=1)

        # method selection
        row += 1
        Label(self.frame, text="Method: ").grid(row=row, column=0, sticky=E)
        self.selected_method = StringVar(master)
        methodnames = sorted(LearningMethods.names())
        self.list_methods = OptionMenu(*(self.frame, self.selected_method) + tuple(methodnames))
        self.list_methods.grid(row=row, column=1, sticky="NWE")
        self.selected_method.trace("w", self.select_method)

        # additional parametrization
        row += 1
        frame = Frame(self.frame)
        frame.grid(row=row, column=1, sticky="NEW")

        # use prior
        self.use_prior = IntVar()
        self.cb_use_prior = Checkbutton(frame, text="use prior with mean of ",
                                        variable=self.use_prior,
                                        command=self.onchange_useprior)
        self.cb_use_prior.pack(side=LEFT)

        # set prior 
        self.priorMean = StringVar(master)
        self.en_prior_mean = Entry(frame, textvariable=self.priorMean, width=5)
        self.en_prior_mean.pack(side=LEFT)
        self.priorMean.trace('w', self.settings_setdirty)
        Label(frame, text="and std dev of").pack(side=LEFT)

        # std. dev.
        self.priorStdDev = StringVar(master)
        self.en_stdev = Entry(frame, textvariable=self.priorStdDev, width=5)
        self.priorStdDev.trace('w', self.settings_setdirty)
        self.en_stdev.pack(side=LEFT)

        # use initial weights in MLN 
        self.use_initial_weights = IntVar()
        self.cb_use_initial_weights = Checkbutton(frame,
                                                  text="use initial weights",
                                                  variable=self.use_initial_weights,
                                                  command=self.settings_setdirty)
        self.cb_use_initial_weights.pack(side=LEFT)

        # use incremental learning
        self.incremental = IntVar()
        self.cb_incremental = Checkbutton(frame, text="learn incrementally",
                                          variable=self.incremental,
                                          command=self.onchange_incremental)
        self.cb_incremental.pack(side=LEFT)

        # shuffle databases
        self.shuffle = IntVar()
        self.cb_shuffle = Checkbutton(frame, text="shuffle databases",
                                      variable=self.shuffle, state='disabled')
        self.cb_shuffle.pack(side=LEFT)

        # discriminative learning settings
        row += 1
        self.discrPredicates = IntVar()
        self.discrPredicates.trace('w', self.change_discr_preds)
        self.discrPredicates.set(1)
        frame = Frame(self.frame)
        frame.grid(row=row, column=1, sticky="NEWS")
        self.rbQueryPreds = Radiobutton(frame, text="Query preds:",
                                        variable=self.discrPredicates,
                                        value=QUERY_PREDS)
        self.rbQueryPreds.grid(row=0, column=0, sticky="NE")

        self.queryPreds = StringVar(master)
        frame.columnconfigure(1, weight=1)
        self.entry_nePreds = Entry(frame, textvariable=self.queryPreds)
        self.entry_nePreds.grid(row=0, column=1, sticky="NEW")

        self.rbEvidencePreds = Radiobutton(frame, text='Evidence preds',
                                           variable=self.discrPredicates,
                                           value=EVIDENCE_PREDS)
        self.rbEvidencePreds.grid(row=0, column=2, sticky='NEWS')

        self.evidencePreds = StringVar(master)
        self.entryEvidencePreds = Entry(frame, textvariable=self.evidencePreds)
        self.entryEvidencePreds.grid(row=0, column=3, sticky='NEWS')

        # db section
        row += 1
        Label(self.frame, text="Evidence: ").grid(row=row, column=0, sticky='NE')
        self.db_container = FileEditBar(self.frame, directory=self.dir,
                                        filesettings={'extension': '.db', 'ftypes': [('Database files', '.db')]},
                                        defaultname='*unknown{}',
                                        importhook=self.import_db,
                                        deletehook=self.delete_db,
                                        projecthook=self.save_proj,
                                        filecontenthook=self.dbfilecontent,
                                        fileslisthook=self.dbfiles,
                                        selectfilehook=self.set_outputfilename,
                                        updatehook=self.update_db,
                                        onchangehook=self.project_setdirty)
        self.db_container.grid(row=row, column=1, sticky="NEWS")
        self.db_container.editor.bind("<FocusIn>", self._got_focus)
        self.db_container.columnconfigure(1, weight=2)
        self.frame.rowconfigure(row, weight=1)

        # file patterns
        row += 1
        frame = Frame(self.frame)
        frame.grid(row=row, column=1, sticky="NEW")
        col = 0
        Label(frame, text="OR file pattern:").grid(row=0, column=col, sticky="W")
        # - pattern entry
        col += 1
        frame.columnconfigure(col, weight=1)
        self.pattern = StringVar(master)
        self.pattern.trace('w', self.onchange_pattern)
        self.entry_pattern = Entry(frame, textvariable=self.pattern)
        self.entry_pattern.grid(row=0, column=col, sticky="NEW")

        # add. parameters
        row += 1
        Label(self.frame, text="Add. Params: ").grid(row=row, column=0, sticky="E")
        self.params = StringVar(master)
        Entry(self.frame, textvariable=self.params).grid(row=row, column=1, sticky="NEW")

        # options
        row += 1
        Label(self.frame, text="Options: ").grid(row=row, column=0, sticky="E")
        option_container = Frame(self.frame)
        option_container.grid(row=row, column=1, sticky="NEWS")

        # multicore
        self.multicore = IntVar()
        self.cb_multicore = Checkbutton(option_container, text="Use all CPUs",
                                        variable=self.multicore,
                                        command=self.settings_setdirty)
        self.cb_multicore.grid(row=0, column=1, sticky=E)

        # profiling
        self.profile = IntVar()
        self.cb_profile = Checkbutton(option_container, text='Use Profiler',
                                      variable=self.profile,
                                      command=self.settings_setdirty)
        self.cb_profile.grid(row=0, column=3, sticky=W)

        # verbose
        self.verbose = IntVar()
        self.cb_verbose = Checkbutton(option_container, text='verbose',
                                      variable=self.verbose, 
                                      command=self.settings_setdirty)
        self.cb_verbose.grid(row=0, column=4, sticky=W)

        self.ignore_zero_weight_formulas = IntVar()
        self.cb_ignore_zero_weight_formulas = Checkbutton(option_container, text='remove 0-weight formulas',
                                                          variable=self.ignore_zero_weight_formulas, command=self.settings_setdirty)
        self.cb_ignore_zero_weight_formulas.grid(row=0, column=5, sticky=W)

        # ignore unknown preds
        self.ignore_unknown_preds = IntVar(master)
        self.ignore_unknown_preds.trace('w', self.settings_setdirty)
        self.cb_ignore_unknown_preds = \
            Checkbutton(option_container, text='ignore unkown predicates', variable=self.ignore_unknown_preds)
        self.cb_ignore_unknown_preds.grid(row=0, column=6, sticky="W")

        row += 1
        output_cont = Frame(self.frame)
        output_cont.grid(row=row, column=1, sticky='NEWS')
        output_cont.columnconfigure(0, weight=1)

        Label(self.frame, text="Output: ").grid(row=row, column=0, sticky="E")
        self.output_filename = StringVar(master)
        self.entry_output_filename = Entry(output_cont, textvariable=self.output_filename)
        self.entry_output_filename.grid(row=0, column=0, sticky="EW")

        self.save = IntVar(self.master)
        self.cb_save = Checkbutton(output_cont, text='save', variable=self.save)
        self.cb_save.grid(row=0, column=1, sticky='W')

        row += 1
        learn_button = Button(self.frame, text=" >> Start Learning << ", command=self.learn)
        learn_button.grid(row=row, column=1, sticky="EW")

        self.settings_dirty = IntVar()
        self.project_dirty = IntVar()

        self.gconf = gconf
        self.project = None
        self.project_dir = os.path.abspath(ifnone(directory, ifnone(gconf['prev_learnwts_path'], os.getcwd())))
        if gconf['prev_learnwts_project': self.project_dir] is not None:
            self.load_project(os.path.join(self.project_dir, gconf['prev_learnwts_project':self.project_dir]))
        else:
            self.new_project()
        self.config = self.project.learnconf
        self.project.addlistener(self.project_setdirty)

        self.mln_container.dirty = False
        self.db_container.dirty = False
        self.project_setdirty(dirty=False)

        self.master.geometry(gconf['window_loc_learn'])

        self.initialized = True

    def _got_focus(self, *_):
        if self.master.focus_get() == self.mln_container.editor:
            if not self.project.mlns and not self.mln_container.file_buffer:
                self.mln_container.new_file()
        elif self.master.focus_get() == self.db_container.editor:
            if not self.project.dbs and not self.db_container.file_buffer:
                self.db_container.new_file()

    def quit(self):
        if self.settings_dirty.get() or self.project_dirty.get():
            savechanges = tkinter.messagebox.askyesnocancel("Save changes", "You have unsaved project changes. Do you want to save them before quitting?")
            if savechanges is None:
                return
            elif savechanges:
                self.noask_save_project()
            self.master.destroy()
        else:
            # write gui settings and destroy
            self.write_gconfig()
            self.master.destroy()


    ####################### PROJECT FUNCTIONS #################################

    def new_project(self):
        self.project = MLNProject()
        self.project.addlistener(self.project_setdirty)
        self.project.name = DEFAULTNAME.format('.pracmln')
        self.reset_gui()
        self.set_config(self.project.learnconf)
        self.mln_container.update_file_choices()
        self.db_container.update_file_choices()
        self.settings_setdirty()


    def project_setdirty(self, dirty=False, *_):
        self.project_dirty.set(
            dirty or self.mln_container.dirty or self.db_container.dirty)
        self.changewindowtitle()


    def settings_setdirty(self, *_):
        self.settings_dirty.set(1)
        self.changewindowtitle()


    def changewindowtitle(self):
        title = (WINDOWTITLEEDITED if (self.settings_dirty.get() or self.project_dirty.get()) else WINDOWTITLE).format(self.project_dir, self.project.name)
        self.master.title(title)


    def ask_load_project(self):
        filename = askopenfilename(initialdir=self.dir, filetypes=[('PRACMLN project files', '.pracmln')], defaultextension=".pracmln")
        if filename and os.path.exists(filename):
            self.load_project(filename)
        else:
            logger.info('No file selected.')
            return


    def load_project(self, filename):
        if filename and os.path.exists(filename):
            projdir, _ = ntpath.split(filename)
            self.dir = os.path.abspath(projdir)
            self.project_dir = os.path.abspath(projdir)
            self.project = MLNProject.open(filename)
            self.project.addlistener(self.project_setdirty)
            self.reset_gui()
            self.set_config(self.project.learnconf.config)
            self.mln_container.update_file_choices()
            self.db_container.update_file_choices()
            if len(self.project.mlns) > 0:
                self.mln_container.selected_file.set(self.project.learnconf['mln'] or list(self.project.mlns.keys())[0])
            self.mln_container.dirty = False
            if len(self.project.dbs) > 0:
                self.db_container.selected_file.set(self.project.learnconf['db'] or list(self.project.dbs.keys())[0])
            self.db_container.dirty = False
            self.write_gconfig(savegeometry=False)
            self.settings_dirty.set(0)
            self.project_setdirty(dirty=False)
            self.changewindowtitle()
        else:
            logger.error(
                'File {} does not exist. Creating new project...'.format(
                    filename))
            self.new_project()


    def noask_save_project(self):
        if self.project.name and not self.project.name == DEFAULTNAME .format('.pracmln'):
            self.save_project(
                os.path.join(self.project_dir, self.project.name))
        else:
            self.ask_save_project()


    def ask_save_project(self):
        fullfilename = asksaveasfilename(initialdir=self.project_dir,
                                         confirmoverwrite=True,
                                         filetypes=[('PRACMLN project files', '.pracmln')],
                                         defaultextension=".pracmln")
        self.save_project(fullfilename)


    def save_project(self, fullfilename):
        if fullfilename:
            fpath, fname = ntpath.split(fullfilename)
            fname = fname.split('.')[0]
            self.project.name = fname
            self.dir = os.path.abspath(fpath)
            self.project_dir = os.path.abspath(fpath)

            self.mln_container.save_all_files()
            self.db_container.save_all_files()

            self.update_config()
            self.project.save(dirpath=self.project_dir)
            self.write_gconfig()

            self.load_project(fullfilename)
            self.settings_dirty.set(0)


    def save_proj(self):
        self.project.save(dirpath=self.project_dir)
        self.write_gconfig()
        self.project_setdirty(dirty=False)

    ####################### MLN FUNCTIONS #####################################

    def import_mln(self, name, content):
        self.project.add_mln(name, content)


    def delete_mln(self, fname):
        if fname in self.project.mlns:
            self.project.rm_mln(fname)
        fnamestr = fname.strip('*')
        if fnamestr in self.project.mlns:
            self.project.rm_mln(fnamestr)


    def update_mln(self, old=None, new=None, content=None, askoverwrite=True):
        if old is None:
            old = self.mln_container.selected_file.get()
        if new is None:
            new = self.mln_container.selected_file.get().strip('*')
        if content is None:
            content = self.mln_container.editor.get("1.0", END).strip()

        if old == new and askoverwrite:
            savechanges = tkinter.messagebox.askyesno("Save changes",
                                                "A file '{}' already exists. "
                                                "Overwrite?".format(new))
            if savechanges:
                self.project.mlns[old] = content
            else:
                logger.error('no name specified!')
                return -1
        elif old == new and not askoverwrite:
            self.project.mlns[old] = content
        else:
            if new in self.project.mlns:
                if askoverwrite:
                    savechanges = tkinter.messagebox.askyesno("Save changes", "A file '{}' already exists. Overwrite?".format(new))
                    if savechanges:
                        self.project.mlns[new] = content
                    else:
                        logger.error('no name specified!')
                        return -1
            else:
                self.project.mlns[new] = content
        return 1


    def mlnfiles(self):
        return list(self.project.mlns.keys())


    def mlnfilecontent(self, filename):
        return self.project.mlns.get(filename, '').strip()


    # /MLN FUNCTIONS ###################################

    ####################### DB FUNCTIONS #####################################

    def import_db(self, name, content):
        self.project.add_db(name, content)


    def delete_db(self, fname):
        if fname in self.project.dbs:
            self.project.rm_db(fname)
        fnamestr = fname.strip('*')
        if fnamestr in self.project.dbs:
            self.project.rm_db(fnamestr)


    def update_db(self, old=None, new=None, content=None, askoverwrite=True):
        if old is None:
            old = self.db_container.selected_file.get()
        if new is None:
            new = self.db_container.selected_file.get().strip('*')
        if content is None:
            content = self.db_container.editor.get("1.0", END).strip()

        if old == new and askoverwrite:
            savechanges = tkinter.messagebox.askyesno("Save changes", "A file '{}' already exists. Overwrite?".format(new))
            if savechanges:
                self.project.dbs[old] = content
            else:
                logger.error('no name specified!')
                return -1
        elif old == new and not askoverwrite:
            self.project.dbs[old] = content
        else:
            if new in self.project.dbs:
                if askoverwrite:
                    savechanges = tkinter.messagebox.askyesno("Save changes", "A file '{}' already exists. Overwrite?".format(new))
                    if savechanges:
                        self.project.dbs[new] = content
                    else:
                        logger.error('no name specified!')
                        return -1
            else:
                self.project.dbs[new] = content
        return 1


    def dbfiles(self):
        return list(self.project.dbs.keys())


    def dbfilecontent(self, filename):
        return self.project.dbs.get(filename, '').strip()


    # /DB FUNCTIONS #####################################

    # GENERAL FUNCTIONS #################################

    def onchange_incremental(self):
        if self.incremental.get() == 1:
            self.cb_shuffle.configure(state="normal")
        else:
            self.cb_shuffle.configure(state="disabled")
            self.cb_shuffle.deselect()
        self.settings_setdirty()


    def onchange_pattern(self, *_):
        self.db_container.editor.disable(self.pattern.get())
        self.db_container.list_files.config(
            state=DISABLED if self.pattern.get() else NORMAL)
        self.settings_setdirty()


    def onchange_useprior(self, *_):
        self.en_prior_mean.configure(
            state=NORMAL if self.use_prior.get() else DISABLED)
        self.en_stdev.configure(
            state=NORMAL if self.use_prior.get() else DISABLED)
        self.settings_setdirty()


    def isfile(self, f):
        return os.path.exists(os.path.join(self.dir, f))


    def set_outputfilename(self):
        mln = self.mln_container.selected_file.get() or 'unknown.mln'
        db = self.db_container.selected_file.get() or 'unknown.db'
        if self.selected_method.get():
            method = LearningMethods.clazz(self.selected_method.get())
            methodid = LearningMethods.id(method)
            filename = config.learnwts_output_filename(mln, methodid.lower(), db)
            self.output_filename.set(filename)


    def select_method(self, *_):
        self.change_discr_preds()
        self.set_outputfilename()
        self.settings_setdirty()


    def change_discr_preds(self, *_):
        methodname = self.selected_method.get()
        if methodname:
            method = LearningMethods.clazz(methodname)
            state = NORMAL if issubclass(method, DiscriminativeLearner) else DISABLED
            self.entry_nePreds.configure(state=state if self.discrPredicates.get() == 0 else DISABLED)
            self.entryEvidencePreds.configure(state=state if self.discrPredicates.get() == 1 else DISABLED)
            self.rbEvidencePreds.configure(state=state)
            self.rbQueryPreds.configure(state=state)


    def reset_gui(self):
        self.set_config({})
        self.db_container.clear()
        self.mln_container.clear()


    def set_config(self, newconf):
        self.config = newconf
        self.selected_grammar.set(ifnone(newconf.get('grammar'), 'PRACGrammar'))
        self.selected_logic.set(ifnone(newconf.get('logic'), 'FirstOrderLogic'))
        self.mln_container.selected_file.set(ifnone(newconf.get('mln'), ''))
        self.db_container.selected_file.set(ifnone(newconf.get('db'), ""))
        self.selected_method.set(ifnone(newconf.get("method"), LearningMethods.name('BPLL'), transform=LearningMethods.name))
        self.pattern.set(ifnone(newconf.get('pattern'), ''))
        self.multicore.set(ifnone(newconf.get('multicore'), 0))
        self.use_prior.set(ifnone(newconf.get('use_prior'), 0))
        self.priorMean.set(ifnone(newconf.get('prior_mean'), 0))
        self.priorStdDev.set(ifnone(newconf.get('prior_stdev'), 5))
        self.incremental.set(ifnone(newconf.get('incremental'), 0))
        self.shuffle.set(ifnone(newconf.get('shuffle'), 0))
        self.use_initial_weights.set(ifnone(newconf.get('use_initial_weights'), 0))
        self.profile.set(ifnone(newconf.get('profile'), 0))
        self.params.set(ifnone(newconf.get('params'), ''))
        self.verbose.set(ifnone(newconf.get('verbose'), 1))
        self.ignore_unknown_preds.set(ifnone(newconf.get('ignore_unknown_preds'), 0))
        self.output_filename.set(ifnone(newconf.get('output_filename'), ''))
        self.queryPreds.set(ifnone(newconf.get('qpreds'), ''))
        self.evidencePreds.set(ifnone(newconf.get('epreds'), ''))
        self.discrPredicates.set(ifnone(newconf.get('discr_preds'), 0))
        self.ignore_zero_weight_formulas.set(ifnone(newconf.get('ignore_zero_weight_formulas'), 0))
        self.save.set(ifnone(newconf.get('save'), 0))


    def get_training_db_paths(self, pattern):
        '''
        determine training databases(s)
        '''
        local = False
        dbs = []
        if pattern is not None and pattern.strip():
            fpath, pat = ntpath.split(pattern)
            if not os.path.exists(fpath):
                logger.debug('{} does not exist. Searching for pattern {} in project {}...'.format(fpath, pat, self.project.name))
                local = True
                dbs = [db for db in self.project.dbs if fnmatch.fnmatch(db, pattern)]
                if len(dbs) == 0:
                    raise Exception("The pattern '{}' matches no files in your project {}".format(pat, self.project.name))
            else:
                local = False
                patternpath = os.path.join(self.dir, pattern)

                d, mask = os.path.split(os.path.abspath(patternpath))
                for fname in os.listdir(d):
                    print(fname)
                    if fnmatch.fnmatch(fname, mask):
                        dbs.append(os.path.join(d, fname))
                if len(dbs) == 0:
                    raise Exception("The pattern '%s' matches no files in %s" % (pat, fpath))
            logger.debug(
                'loading training databases from pattern %s:' % pattern)
            for p in dbs: logger.debug('  %s' % p)
        if not dbs:
            raise Exception("No training data given; A training database must be selected or a pattern must be specified")
        else:
            return local, dbs


    def update_config(self):
        out('update_config')

        self.config = PRACMLNConfig()
        self.config['mln'] = self.mln_container.selected_file.get().strip().lstrip('*')
        self.config["db"] = self.db_container.selected_file.get().strip().lstrip('*')
        self.config["output_filename"] = self.output_filename.get()
        self.config["params"] = self.params.get().strip()
        self.config["method"] = LearningMethods.id(self.selected_method.get().strip())
        self.config["pattern"] = self.pattern.get()
        self.config["use_prior"] = int(self.use_prior.get())
        self.config["prior_mean"] = self.priorMean.get()
        self.config["prior_stdev"] = self.priorStdDev.get()
        self.config["incremental"] = int(self.incremental.get())
        self.config["shuffle"] = int(self.shuffle.get())
        self.config["use_initial_weights"] = int(self.use_initial_weights.get())
        self.config["qpreds"] = self.queryPreds.get().strip()
        self.config["epreds"] = self.evidencePreds.get().strip()
        self.config["discr_preds"] = self.discrPredicates.get()
        self.config['logic'] = self.selected_logic.get()
        self.config['grammar'] = self.selected_grammar.get()
        self.config['multicore'] = self.multicore.get()
        self.config['profile'] = self.profile.get()
        self.config['verbose'] = self.verbose.get()
        self.config['ignore_unknown_preds'] = self.ignore_unknown_preds.get()
        self.config['ignore_zero_weight_formulas'] = self.ignore_zero_weight_formulas.get()
        self.config['save'] = self.save.get()
        self.config["output_filename"] = self.output_filename.get().strip()
        self.project.learnconf = PRACMLNConfig()
        self.project.learnconf.update(self.config.config.copy())


    def write_gconfig(self, savegeometry=True):
        self.gconf['prev_learnwts_path'] = self.project_dir
        self.gconf['prev_learnwts_project': self.project_dir] = self.project.name

        # save geometry
        if savegeometry:
            self.gconf['window_loc_learn'] = self.master.geometry()
        self.gconf.dump()


    def learn(self, savegeometry=True, options=None, *_):
        if options is None:
            options = {}
        mln_content = self.mln_container.editor.get("1.0", END).strip()
        db_content = self.db_container.editor.get("1.0", END).strip()

        # create conf from current gui settings
        self.update_config()

        # write gui settings
        self.write_gconfig(savegeometry=savegeometry)

        # hide gui
        self.master.withdraw()

        try:
            print((headline('PRAC LEARNING TOOL')))
            print()

            if options.get('mlnarg') is not None:
                mlnobj = MLN(mlnfile=os.path.abspath(options.get('mlnarg')),
                             logic=self.config.get('logic', 'FirstOrderLogic'),
                             grammar=self.config.get('grammar', 'PRACGrammar'))
            else:
                mlnobj = parse_mln(mln_content, searchpaths=[self.project_dir],
                                   projectpath=os.path.join(self.project_dir, self.project.name),
                                   logic=self.config.get('logic', 'FirstOrderLogic'),
                                   grammar=self.config.get('grammar', 'PRACGrammar'))

            if options.get('dbarg') is not None:
                dbobj = Database.load(mlnobj, dbfiles=[options.get('dbarg')], ignore_unknown_preds=self.config.get('ignore_unknown_preds', True))
            else:
                if self.config.get('pattern'):
                    local, dblist = self.get_training_db_paths(self.config.get('pattern').strip())
                    dbobj = []
                    # build database list from project dbs
                    if local:
                        for dbname in dblist:
                            dbobj.extend(parse_db(mlnobj, self.project.dbs[dbname].strip(),
                                         ignore_unknown_preds=self.config.get('ignore_unknown_preds', True),
                                         projectpath=os.path.join(self.dir, self.project.name)))
                        out(dbobj)
                    # build database list from filesystem dbs
                    else:
                        for dbpath in dblist:
                            dbobj.extend(Database.load(mlnobj, dbpath, ignore_unknown_preds= self.config.get('ignore_unknown_preds', True)))
                # build single db from currently selected db
                else:
                    dbobj = parse_db(mlnobj, db_content, projectpath=os.path.join(self.dir, self.project.name), dirs=[self.dir])

            learning = MLNLearn(config=self.config, mln=mlnobj, db=dbobj)
            result = learning.run()

            # write to file if run from commandline, otherwise save result
            # to project results
            if options.get('outputfile') is not None:
                output = io.StringIO()
                result.write(output)
                with open(os.path.abspath(options.get('outputfile')), 'w') as f:
                    f.write(output.getvalue())
                logger.info('saved result to {}'.format(os.path.abspath(options.get('outputfile'))))
            elif self.save.get():
                output = io.StringIO()
                result.write(output)
                self.project.add_mln(self.output_filename.get(), output.getvalue())
                self.mln_container.update_file_choices()
                self.project.save(dirpath=self.project_dir)
                logger.info('saved result to file mln/{} in project {}'.format(self.output_filename.get(), self.project.name))
            else:
                logger.debug("No output file given - results have not been saved.")
        except:
            traceback.print_exc()

        # restore gui
        sys.stdout.flush()
        self.master.deiconify()
Exemple #10
0
class MLNQueryGUI(object):
    def __init__(self, master, gconf, directory=None):
        self.master = master

        self.initialized = False

        self.master.bind('<Return>', self.infer)
        self.master.bind('<Escape>', lambda a: self.master.quit())
        self.master.protocol('WM_DELETE_WINDOW', self.quit)

        self.dir = os.path.abspath(
            ifnone(directory, ifnone(gconf['prev_query_path'], os.getcwd())))

        self.frame = Frame(master)
        self.frame.pack(fill=BOTH, expand=1)
        self.frame.columnconfigure(1, weight=1)

        row = 0
        # pracmln project options
        Label(self.frame, text='PRACMLN Project: ').grid(row=row,
                                                         column=0,
                                                         sticky='ES')
        project_container = Frame(self.frame)
        project_container.grid(row=row, column=1, sticky="NEWS")

        # new proj file
        self.btn_newproj = Button(project_container,
                                  text='New Project...',
                                  command=self.new_project)
        self.btn_newproj.grid(row=0, column=1, sticky="WS")

        # open proj file
        self.btn_openproj = Button(project_container,
                                   text='Open Project...',
                                   command=self.ask_load_project)
        self.btn_openproj.grid(row=0, column=2, sticky="WS")

        # save proj file
        self.btn_updateproj = Button(project_container,
                                     text='Save Project...',
                                     command=self.noask_save_project)
        self.btn_updateproj.grid(row=0, column=3, sticky="WS")

        # save proj file as...
        self.btn_saveproj = Button(project_container,
                                   text='Save Project as...',
                                   command=self.ask_save_project)
        self.btn_saveproj.grid(row=0, column=4, sticky="WS")

        # grammar selection
        row += 1
        Label(self.frame, text='Grammar: ').grid(row=row, column=0, sticky='E')
        grammars = ['StandardGrammar', 'PRACGrammar']
        self.selected_grammar = StringVar()
        self.selected_grammar.trace('w', self.settings_setdirty)
        l = OptionMenu(*(self.frame, self.selected_grammar) + tuple(grammars))
        l.grid(row=row, column=1, sticky='NWE')

        # logic selection
        row += 1
        Label(self.frame, text='Logic: ').grid(row=row, column=0, sticky='E')
        logics = ['FirstOrderLogic', 'FuzzyLogic']
        self.selected_logic = StringVar()
        self.selected_logic.trace('w', self.settings_setdirty)
        l = OptionMenu(*(self.frame, self.selected_logic) + tuple(logics))
        l.grid(row=row, column=1, sticky='NWE')

        # mln section
        row += 1
        Label(self.frame, text="MLN: ").grid(row=row, column=0, sticky='NE')
        self.mln_container = FileEditBar(self.frame,
                                         directory=self.dir,
                                         filesettings={
                                             'extension': '.mln',
                                             'ftypes': [('MLN files', '.mln')]
                                         },
                                         defaultname='*unknown{}',
                                         importhook=self.import_mln,
                                         deletehook=self.delete_mln,
                                         projecthook=self.save_proj,
                                         filecontenthook=self.mlnfilecontent,
                                         fileslisthook=self.mlnfiles,
                                         updatehook=self.update_mln,
                                         onchangehook=self.project_setdirty)
        self.mln_container.editor.bind("<FocusIn>", self._got_focus)
        self.mln_container.grid(row=row, column=1, sticky="NEWS")
        self.mln_container.columnconfigure(1, weight=2)
        self.frame.rowconfigure(row, weight=1)

        row += 1
        self.use_emln = IntVar()
        self.use_emln.set(0)
        self.cb_use_emln = Checkbutton(self.frame,
                                       text="use model extension",
                                       variable=self.use_emln,
                                       command=self.onchange_use_emln)
        self.cb_use_emln.grid(row=row, column=1, sticky="W")

        # mln extension section
        row += 1
        self.emlncontainerrow = row
        self.emln_label = Label(self.frame, text="EMLN: ")
        self.emln_label.grid(row=self.emlncontainerrow, column=0, sticky='NE')
        self.emln_container = FileEditBar(self.frame,
                                          directory=self.dir,
                                          filesettings={
                                              'extension':
                                              '.emln',
                                              'ftypes':
                                              [('MLN extension files', '.emln')
                                               ]
                                          },
                                          defaultname='*unknown{}',
                                          importhook=self.import_emln,
                                          deletehook=self.delete_emln,
                                          projecthook=self.save_proj,
                                          filecontenthook=self.emlnfilecontent,
                                          fileslisthook=self.emlnfiles,
                                          updatehook=self.update_emln,
                                          onchangehook=self.project_setdirty)
        self.emln_container.grid(row=self.emlncontainerrow,
                                 column=1,
                                 sticky="NEWS")
        self.emln_container.editor.bind("<FocusIn>", self._got_focus)
        self.emln_container.columnconfigure(1, weight=2)
        self.onchange_use_emln(dirty=False)
        self.frame.rowconfigure(row, weight=1)

        # db section
        row += 1
        Label(self.frame, text="Evidence: ").grid(row=row,
                                                  column=0,
                                                  sticky='NE')
        self.db_container = FileEditBar(self.frame,
                                        directory=self.dir,
                                        filesettings={
                                            'extension': '.db',
                                            'ftypes':
                                            [('Database files', '.db')]
                                        },
                                        defaultname='*unknown{}',
                                        importhook=self.import_db,
                                        deletehook=self.delete_db,
                                        projecthook=self.save_proj,
                                        filecontenthook=self.dbfilecontent,
                                        fileslisthook=self.dbfiles,
                                        updatehook=self.update_db,
                                        onchangehook=self.project_setdirty)
        self.db_container.grid(row=row, column=1, sticky="NEWS")
        self.db_container.editor.bind("<FocusIn>", self._got_focus)
        self.db_container.columnconfigure(1, weight=2)
        self.frame.rowconfigure(row, weight=1)

        # inference method selection
        row += 1
        self.list_methods_row = row
        Label(self.frame, text="Method: ").grid(row=row, column=0, sticky=E)
        self.selected_method = StringVar()
        self.selected_method.trace('w', self.select_method)
        methodnames = sorted(InferenceMethods.names())
        self.list_methods = OptionMenu(*(self.frame, self.selected_method) +
                                       tuple(methodnames))
        self.list_methods.grid(row=self.list_methods_row,
                               column=1,
                               sticky="NWE")

        # options
        row += 1
        option_container = Frame(self.frame)
        option_container.grid(row=row, column=1, sticky="NEWS")

        # Multiprocessing
        self.multicore = IntVar()
        self.cb_multicore = Checkbutton(option_container,
                                        text="Use all CPUs",
                                        variable=self.multicore,
                                        command=self.settings_setdirty)
        self.cb_multicore.grid(row=0, column=2, sticky=W)

        # profiling
        self.profile = IntVar()
        self.cb_profile = Checkbutton(option_container,
                                      text='Use Profiler',
                                      variable=self.profile,
                                      command=self.settings_setdirty)
        self.cb_profile.grid(row=0, column=3, sticky=W)

        # verbose
        self.verbose = IntVar()
        self.cb_verbose = Checkbutton(option_container,
                                      text='verbose',
                                      variable=self.verbose,
                                      command=self.settings_setdirty)
        self.cb_verbose.grid(row=0, column=4, sticky=W)

        # options
        self.ignore_unknown_preds = IntVar()
        self.cb_ignore_unknown_preds = Checkbutton(
            option_container,
            text='ignore unkown predicates',
            variable=self.ignore_unknown_preds,
            command=self.settings_setdirty)
        self.cb_ignore_unknown_preds.grid(row=0, column=5, sticky="W")

        # queries
        row += 1
        Label(self.frame, text="Queries: ").grid(row=row, column=0, sticky=E)
        self.query = StringVar()
        self.query.trace('w', self.settings_setdirty)
        Entry(self.frame, textvariable=self.query).grid(row=row,
                                                        column=1,
                                                        sticky="NEW")

        # additional parameters
        row += 1
        Label(self.frame, text="Add. params: ").grid(row=row,
                                                     column=0,
                                                     sticky="NE")
        self.params = StringVar()
        self.params.trace('w', self.settings_setdirty)
        self.entry_params = Entry(self.frame, textvariable=self.params)
        self.entry_params.grid(row=row, column=1, sticky="NEW")

        # closed-world predicates
        row += 1
        Label(self.frame, text="CW preds: ").grid(row=row,
                                                  column=0,
                                                  sticky="E")

        cw_container = Frame(self.frame)
        cw_container.grid(row=row, column=1, sticky='NEWS')
        cw_container.columnconfigure(0, weight=1)

        self.cwPreds = StringVar()
        self.cwPreds.trace('w', self.settings_setdirty)
        self.entry_cw = Entry(cw_container, textvariable=self.cwPreds)
        self.entry_cw.grid(row=0, column=0, sticky="NEWS")

        self.closed_world = IntVar()
        self.cb_closed_world = Checkbutton(cw_container,
                                           text="CW Assumption",
                                           variable=self.closed_world,
                                           command=self.onchange_cw)
        self.cb_closed_world.grid(row=0, column=1, sticky='W')

        # output filename
        row += 1
        output_cont = Frame(self.frame)
        output_cont.grid(row=row, column=1, sticky='NEWS')
        output_cont.columnconfigure(0, weight=1)

        # - filename
        Label(self.frame, text="Output: ").grid(row=row, column=0, sticky="NE")
        self.output_filename = StringVar()
        self.entry_output_filename = Entry(output_cont,
                                           textvariable=self.output_filename)
        self.entry_output_filename.grid(row=0, column=0, sticky="NEW")

        # - save option
        self.save = IntVar()
        self.cb_save = Checkbutton(output_cont,
                                   text="save",
                                   variable=self.save)
        self.cb_save.grid(row=0, column=1, sticky=W)

        # start button
        row += 1
        start_button = Button(self.frame,
                              text=">> Start Inference <<",
                              command=self.infer)
        start_button.grid(row=row, column=1, sticky="NEW")

        self.settings_dirty = IntVar()
        self.project_dirty = IntVar()

        self.gconf = gconf
        self.project = None
        self.project_dir = os.path.abspath(
            ifnone(directory, ifnone(gconf['prev_query_path'], os.getcwd())))
        if gconf['prev_query_project':self.project_dir] is not None:
            self.load_project(
                os.path.join(self.project_dir,
                             gconf['prev_query_project':self.project_dir]))
        else:
            self.new_project()

        self.config = self.project.queryconf
        self.project.addlistener(self.project_setdirty)

        self.mln_container.dirty = False
        self.emln_container.dirty = False
        self.db_container.dirty = False
        self.project_setdirty(dirty=False)

        self.master.geometry(gconf['window_loc_query'])

        self.initialized = True

    def _got_focus(self, *_):
        if self.master.focus_get() == self.mln_container.editor:
            if not self.project.mlns and not self.mln_container.file_buffer:
                self.mln_container.new_file()
        elif self.master.focus_get() == self.db_container.editor:
            if not self.project.dbs and not self.db_container.file_buffer:
                self.db_container.new_file()
        elif self.master.focus_get() == self.emln_container.editor:
            if not self.project.emlns and not self.emln_container.file_buffer:
                self.emln_container.new_file()

    def quit(self):
        if self.settings_dirty.get() or self.project_dirty.get():
            savechanges = messagebox.askyesnocancel(
                "Save changes",
                "You have unsaved project changes. Do you want to save them before quitting?"
            )
            if savechanges is None:
                return
            elif savechanges:
                self.noask_save_project()
            self.master.destroy()
        else:
            # write gui settings and destroy
            self.write_gconfig()
            self.master.destroy()

    ####################### PROJECT FUNCTIONS #################################

    def new_project(self):
        self.project = MLNProject()
        self.project.addlistener(self.project_setdirty)
        self.project.name = DEFAULTNAME.format('.pracmln')
        self.reset_gui()
        self.set_config(self.project.queryconf)
        self.mln_container.update_file_choices()
        self.emln_container.update_file_choices()
        self.db_container.update_file_choices()
        self.project_setdirty(dirty=True)

    def project_setdirty(self, dirty=False, *args):
        self.project_dirty.set(dirty or self.mln_container.dirty
                               or self.db_container.dirty
                               or self.emln_container.dirty)
        self.changewindowtitle()

    def settings_setdirty(self, *args):
        self.settings_dirty.set(1)
        self.changewindowtitle()

    def changewindowtitle(self):
        title = (WINDOWTITLEEDITED if
                 (self.settings_dirty.get() or self.project_dirty.get()) else
                 WINDOWTITLE).format(self.project_dir, self.project.name)
        self.master.title(title)

    def ask_load_project(self):
        filename = askopenfilename(initialdir=self.dir,
                                   filetypes=[('PRACMLN project files',
                                               '.pracmln')],
                                   defaultextension=".pracmln")
        if filename and os.path.exists(filename):
            self.load_project(filename)
        else:
            logger.info('No file selected.')
            return

    def load_project(self, filename):
        if filename and os.path.exists(filename):
            projdir, _ = ntpath.split(filename)
            self.dir = os.path.abspath(projdir)
            self.project_dir = os.path.abspath(projdir)
            self.project = MLNProject.open(filename)
            self.project.addlistener(self.project_setdirty)
            self.reset_gui()
            self.set_config(self.project.queryconf.config)
            self.mln_container.update_file_choices()
            self.db_container.update_file_choices()
            if len(self.project.mlns) > 0:
                self.mln_container.selected_file.set(
                    self.project.queryconf['mln']
                    or list(self.project.mlns.keys())[0])
            self.mln_container.dirty = False
            if len(self.project.emlns) > 0:
                self.emln_container.selected_file.set(
                    self.project.queryconf['emln']
                    or list(self.project.emlns.keys())[0])
            self.emln_container.dirty = False
            if len(self.project.dbs) > 0:
                self.db_container.selected_file.set(
                    self.project.queryconf['db']
                    or list(self.project.dbs.keys())[0])
            self.db_container.dirty = False
            self.write_gconfig(savegeometry=False)
            self.settings_dirty.set(0)
            self.project_setdirty(dirty=False)
            self.changewindowtitle()
        else:
            logger.error(
                'File {} does not exist. Creating new project...'.format(
                    filename))
            self.new_project()

    def noask_save_project(self):
        if self.project.name and not self.project.name == DEFAULTNAME.format(
                '.pracmln'):
            self.save_project(os.path.join(self.project_dir,
                                           self.project.name))
        else:
            self.ask_save_project()

    def ask_save_project(self):
        fullfilename = asksaveasfilename(initialdir=self.project_dir,
                                         confirmoverwrite=True,
                                         filetypes=[('PRACMLN project files',
                                                     '.pracmln')],
                                         defaultextension=".pracmln")
        self.save_project(fullfilename)

    def save_project(self, fullfilename):
        if fullfilename:
            fpath, fname = ntpath.split(fullfilename)
            fname = fname.split('.')[0]
            self.project.name = fname
            self.dir = os.path.abspath(fpath)
            self.project_dir = os.path.abspath(fpath)

            self.mln_container.save_all_files()
            self.emln_container.save_all_files()
            self.db_container.save_all_files()

            self.update_config()
            self.project.save(dirpath=self.project_dir)
            self.write_gconfig()

            self.load_project(fullfilename)
            self.settings_dirty.set(0)

    def save_proj(self):
        self.project.save(dirpath=self.project_dir)
        self.write_gconfig()
        self.project_setdirty(dirty=False)

    ####################### MLN FUNCTIONS #####################################

    def import_mln(self, name, content):
        self.project.add_mln(name, content)

    def delete_mln(self, fname):
        if fname in self.project.mlns:
            self.project.rm_mln(fname)
        fnamestr = fname.strip('*')
        if fnamestr in self.project.mlns:
            self.project.rm_mln(fnamestr)

    def update_mln(self, old=None, new=None, content=None, askoverwrite=True):
        if old is None:
            old = self.mln_container.selected_file.get()
        if new is None:
            new = self.mln_container.selected_file.get().strip('*')
        if content is None:
            content = self.mln_container.editor.get("1.0", END).strip()

        if old == new and askoverwrite:
            savechanges = messagebox.askyesno(
                "Save changes",
                "A file '{}' already exists. Overwrite?".format(new))
            if savechanges:
                self.project.mlns[old] = content
            else:
                logger.error('no name specified!')
                return -1
        elif old == new and not askoverwrite:
            self.project.mlns[old] = content
        else:
            if new in self.project.mlns:
                if askoverwrite:
                    savechanges = messagebox.askyesno(
                        "Save changes",
                        "A file '{}' already exists. Overwrite?".format(new))
                    if savechanges:
                        self.project.mlns[new] = content
                    else:
                        logger.error('no name specified!')
                        return -1
            else:
                self.project.mlns[new] = content
        return 1

    def mlnfiles(self):
        return list(self.project.mlns.keys())

    def mlnfilecontent(self, filename):
        return self.project.mlns.get(filename, '').strip()

    # /MLN FUNCTIONS #####################################

    ####################### EMLN FUNCTIONS #####################################

    def import_emln(self, name, content):
        self.project.add_emln(name, content)

    def delete_emln(self, fname):
        if fname in self.project.emlns:
            self.project.rm_emln(fname)
        fnamestr = fname.strip('*')
        if fnamestr in self.project.emlns:
            self.project.rm_emln(fnamestr)

    def update_emln(self, old=None, new=None, content=None, askoverwrite=True):
        if old is None:
            old = self.emln_container.selected_file.get()
        if new is None:
            new = self.emln_container.selected_file.get().strip('*')
        if content is None:
            content = self.emln_container.editor.get("1.0", END).strip()

        if old == new and askoverwrite:
            savechanges = messagebox.askyesno(
                "Save changes",
                "A file '{}' already exists. Overwrite?".format(new))
            if savechanges:
                self.project.emlns[old] = content
            else:
                logger.error('no name specified!')
                return -1
        elif old == new and not askoverwrite:
            self.project.emlns[old] = content
        else:
            if new in self.project.emlns:
                if askoverwrite:
                    savechanges = messagebox.askyesno(
                        "Save changes",
                        "A file '{}' already exists. Overwrite?".format(new))
                    if savechanges:
                        self.project.emlns[new] = content
                    else:
                        logger.error('no name specified!')
                        return -1
            else:
                self.project.emlns[new] = content
        return 1

    def emlnfiles(self):
        return list(self.project.emlns.keys())

    def emlnfilecontent(self, filename):
        return self.project.emlns.get(filename, '').strip()

    # /EMLN FUNCTIONS #####################################

    # DB FUNCTIONS #####################################
    def import_db(self, name, content):
        self.project.add_db(name, content)

    def delete_db(self, fname):
        if fname in self.project.dbs:
            self.project.rm_db(fname)
        fnamestr = fname.strip('*')
        if fnamestr in self.project.dbs:
            self.project.rm_db(fnamestr)

    def update_db(self, old=None, new=None, content=None, askoverwrite=True):
        if old is None:
            old = self.db_container.selected_file.get()
        if new is None:
            new = self.db_container.selected_file.get().strip('*')
        if content is None:
            content = self.db_container.editor.get("1.0", END).strip()

        if old == new and askoverwrite:
            savechanges = messagebox.askyesno(
                "Save changes",
                "A file '{}' already exists. Overwrite?".format(new))
            if savechanges:
                self.project.dbs[old] = content
            else:
                logger.error('no name specified!')
                return -1
        elif old == new and not askoverwrite:
            self.project.dbs[old] = content
        else:
            if new in self.project.dbs:
                if askoverwrite:
                    savechanges = messagebox.askyesno(
                        "Save changes",
                        "A file '{}' already exists. Overwrite?".format(new))
                    if savechanges:
                        self.project.dbs[new] = content
                    else:
                        logger.error('no name specified!')
                        return -1
            else:
                self.project.dbs[new] = content
        return 1

    def dbfiles(self):
        return list(self.project.dbs.keys())

    def dbfilecontent(self, filename):
        return self.project.dbs.get(filename, '').strip()

    # /DB FUNCTIONS #####################################

    # GENERAL FUNCTIONS #################################

    def select_method(self, *args):
        self.set_outputfilename()
        self.settings_setdirty()

    def onchange_use_emln(self, dirty=True, *args):
        if not self.use_emln.get():
            self.emln_label.grid_forget()
            self.emln_container.grid_forget()
        else:
            self.emln_label.grid(row=self.emlncontainerrow,
                                 column=0,
                                 sticky="NE")
            self.emln_container.grid(row=self.emlncontainerrow,
                                     column=1,
                                     sticky="NWES")
        if dirty:
            self.settings_setdirty()

    def onchange_cw(self, *args):
        if self.closed_world.get():
            self.entry_cw.configure(state=DISABLED)
        else:
            self.entry_cw.configure(state=NORMAL)
        self.settings_setdirty()

    def reset_gui(self):
        self.set_config({})
        self.db_container.clear()
        self.emln_container.clear()
        self.mln_container.clear()

    def set_config(self, newconf):
        self.config = newconf
        self.selected_grammar.set(ifnone(newconf.get('grammar'),
                                         'PRACGrammar'))
        self.selected_logic.set(ifnone(newconf.get('logic'),
                                       'FirstOrderLogic'))
        self.mln_container.selected_file.set(ifnone(newconf.get('mln'), ''))
        if self.use_emln.get():
            self.emln_container.selected_file.set(
                ifnone(newconf.get('mln'), ''))
        self.db_container.selected_file.set(ifnone(newconf.get('db'), ""))
        self.selected_method.set(
            ifnone(newconf.get("method"),
                   InferenceMethods.name('MCSAT'),
                   transform=InferenceMethods.name))
        self.multicore.set(ifnone(newconf.get('multicore'), 0))
        self.profile.set(ifnone(newconf.get('profile'), 0))
        self.params.set(ifnone(newconf.get('params'), ''))
        self.use_emln.set(ifnone(newconf.get('use_emln'), 0))
        self.verbose.set(ifnone(newconf.get('verbose'), 1))
        self.ignore_unknown_preds.set(
            ifnone(newconf.get('ignore_unknown_preds'), 0))
        self.output_filename.set(ifnone(newconf.get('output_filename'), ''))
        self.cwPreds.set(ifnone(newconf.get('cw_preds'), ''))
        self.closed_world.set(ifnone(newconf.get('cw'), 0))
        self.save.set(ifnone(newconf.get('save'), 0))
        self.query.set(ifnone(newconf.get('queries'), ''))
        self.onchange_cw()

    def set_outputfilename(self):
        if not hasattr(self, "output_filename") or not hasattr(
                self, "db_filename") or not hasattr(self, "mln_filename"):
            return
        mln = self.mln_container.selected_file.get()
        db = self.db_container.selected_file.get()
        if "" in (mln, db):
            return
        if self.selected_method.get():
            method = InferenceMethods.clazz(self.selected_method.get())
            methodid = InferenceMethods.id(method)
            filename = config.query_output_filename(mln, methodid, db)
            self.output_filename.set(filename)

    def update_config(self):

        self.config = PRACMLNConfig()
        self.config["use_emln"] = self.use_emln.get()
        self.config['mln'] = self.mln_container.selected_file.get().strip(
        ).lstrip('*')
        self.config['emln'] = self.emln_container.selected_file.get().strip(
        ).lstrip('*')
        self.config["db"] = self.db_container.selected_file.get().strip(
        ).lstrip('*')
        self.config["method"] = InferenceMethods.id(
            self.selected_method.get().strip())
        self.config["params"] = self.params.get().strip()
        self.config["queries"] = self.query.get()
        self.config["output_filename"] = self.output_filename.get().strip()
        self.config["cw"] = self.closed_world.get()
        self.config["cw_preds"] = self.cwPreds.get()
        self.config['profile'] = self.profile.get()
        self.config['logic'] = self.selected_logic.get()
        self.config['grammar'] = self.selected_grammar.get()
        self.config['multicore'] = self.multicore.get()
        self.config['save'] = self.save.get()
        self.config['ignore_unknown_preds'] = self.ignore_unknown_preds.get()
        self.config['verbose'] = self.verbose.get()
        self.config['window_loc'] = self.master.winfo_geometry()
        self.config['dir'] = self.dir
        self.project.queryconf = PRACMLNConfig()
        self.project.queryconf.update(self.config.config.copy())

    def write_gconfig(self, savegeometry=True):
        self.gconf['prev_query_path'] = self.dir
        self.gconf['prev_query_project':self.dir] = self.project.name

        # save geometry
        if savegeometry:
            self.gconf['window_loc_query'] = self.master.geometry()
        self.gconf.dump()

    def infer(self, savegeometry=True, options={}, *args):
        mln_content = self.mln_container.editor.get("1.0", END).strip()
        db_content = self.db_container.editor.get("1.0", END).strip()

        # create conf from current gui settings
        self.update_config()

        # write gui settings
        self.write_gconfig(savegeometry=savegeometry)

        # hide gui
        self.master.withdraw()

        try:
            print((headline('PRACMLN QUERY TOOL')))
            print()

            if options.get('mlnarg') is not None:
                mlnobj = MLN(mlnfile=os.path.abspath(options.get('mlnarg')),
                             logic=self.config.get('logic', 'FirstOrderLogic'),
                             grammar=self.config.get('grammar', 'PRACGrammar'))
            else:
                mlnobj = parse_mln(
                    mln_content,
                    searchpaths=[self.dir],
                    projectpath=os.path.join(self.dir, self.project.name),
                    logic=self.config.get('logic', 'FirstOrderLogic'),
                    grammar=self.config.get('grammar', 'PRACGrammar'))

            if options.get('emlnarg') is not None:
                emln_content = mlnpath(options.get('emlnarg')).content
            else:
                emln_content = self.emln_container.editor.get("1.0",
                                                              END).strip()

            if options.get('dbarg') is not None:
                dbobj = Database.load(mlnobj,
                                      dbfiles=[options.get('dbarg')],
                                      ignore_unknown_preds=self.config.get(
                                          'ignore_unknown_preds', True))
            else:
                out(self.config.get('ignore_unknown_preds', True))
                dbobj = parse_db(mlnobj,
                                 db_content,
                                 ignore_unknown_preds=self.config.get(
                                     'ignore_unknown_preds', True))

            if options.get('queryarg') is not None:
                self.config["queries"] = options.get('queryarg')

            infer = MLNQuery(config=self.config,
                             mln=mlnobj,
                             db=dbobj,
                             emln=emln_content)
            result = infer.run()

            # write to file if run from commandline, otherwise save result to project results
            if options.get('outputfile') is not None:
                output = io.StringIO()
                result.write(output)
                with open(os.path.abspath(options.get('outputfile')),
                          'w') as f:
                    f.write(output.getvalue())
                logger.info('saved result to {}'.format(
                    os.path.abspath(options.get('outputfile'))))
            elif self.save.get():
                output = io.StringIO()
                result.write(output)
                fname = self.output_filename.get()
                self.project.add_result(fname, output.getvalue())
                self.project.save(dirpath=self.dir)
                logger.info(
                    'saved result to file results/{} in project {}'.format(
                        fname, self.project.name))
            else:
                logger.debug(
                    'No output file given - results have not been saved.')
        except:
            traceback.print_exc()

        # restore main window
        sys.stdout.flush()
        self.master.deiconify()
Exemple #11
0
class MLNLearnGUI:
    def __init__(self, master, gconf, directory=None):
        self.master = master
        # icon = Tkinter.Image("photo", file=os.path.join(PRACMLN_HOME,
        #                                                 'doc',
        #                                                 '_static',
        #                                                 'favicon.ico'))
        # self.master.tk.call('wm', 'iconphoto', self.master._w, icon)

        self.initialized = False

        self.master.bind('<Return>', self.learn)
        self.master.bind('<Escape>', lambda a: self.master.quit())
        self.master.protocol('WM_DELETE_WINDOW', self.quit)

        # logo = Label(self.master, image=img)
        # logo.pack(side = "right", anchor='ne')
        self.dir = os.path.abspath(ifNone(directory, ifNone(gconf['prev_learnwts_path'], os.getcwd())))

        self.frame = Frame(master)
        self.frame.pack(fill=BOTH, expand=1)
        self.frame.columnconfigure(1, weight=1)

        row = 0
        # pracmln project options
        Label(self.frame, text='PRACMLN Project: ').grid(row=row, column=0,
                                                         sticky='ES')
        project_container = Frame(self.frame)
        project_container.grid(row=row, column=1, sticky="NEWS")

        # new proj file
        self.btn_newproj = Button(project_container, text='New Project...',
                                  command=self.new_project)
        self.btn_newproj.grid(row=0, column=1, sticky="WS")

        # open proj file
        self.btn_openproj = Button(project_container, text='Open Project...',
                                   command=self.ask_load_project)
        self.btn_openproj.grid(row=0, column=2, sticky="WS")

        # save proj file
        self.btn_saveproj = Button(project_container, text='Save Project',
                                   command=self.noask_save_project)
        self.btn_saveproj.grid(row=0, column=3, sticky="WS")

        # save proj file as...
        self.btn_saveproj = Button(project_container,
                                   text='Save Project as...',
                                   command=self.ask_save_project)
        self.btn_saveproj.grid(row=0, column=4, sticky="WS")

        # grammar selection
        row += 1
        Label(self.frame, text='Grammar: ').grid(row=row, column=0, sticky='E')
        grammars = ['StandardGrammar', 'PRACGrammar']
        self.selected_grammar = StringVar(master)
        self.selected_grammar.trace('w', self.settings_setdirty)
        l = apply(OptionMenu,
                  (self.frame, self.selected_grammar) + tuple(grammars))
        l.grid(row=row, column=1, sticky='NWE')

        # logic selection
        row += 1
        Label(self.frame, text='Logic: ').grid(row=row, column=0, sticky='E')
        logics = ['FirstOrderLogic', 'FuzzyLogic']
        self.selected_logic = StringVar(master)
        self.selected_logic.trace('w', self.settings_setdirty)
        l = apply(OptionMenu,
                  (self.frame, self.selected_logic) + tuple(logics))
        l.grid(row=row, column=1, sticky='NWE')

        # mln section
        row += 1
        Label(self.frame, text="MLN: ").grid(row=row, column=0, sticky='NE')
        self.mln_container = FileEditBar(self.frame, dir=self.dir,
                                         filesettings={'extension': '.mln', 'ftypes': [('MLN files', '.mln')]},
                                         defaultname='*unknown{}',
                                         importhook=self.import_mln,
                                         deletehook=self.delete_mln,
                                         projecthook=self.save_proj,
                                         filecontenthook=self.mlnfilecontent,
                                         fileslisthook=self.mlnfiles,
                                         updatehook=self.update_mln,
                                         onchangehook=self.project_setdirty)
        self.mln_container.grid(row=row, column=1, sticky="NEWS")
        self.mln_container.columnconfigure(1, weight=2)
        self.frame.rowconfigure(row, weight=1)

        # method selection
        row += 1
        Label(self.frame, text="Method: ").grid(row=row, column=0, sticky=E)
        self.selected_method = StringVar(master)
        methodnames = sorted(LearningMethods.names())
        self.list_methods = apply(OptionMenu, (self.frame, self.selected_method) + tuple(methodnames))
        self.list_methods.grid(row=row, column=1, sticky="NWE")
        self.selected_method.trace("w", self.select_method)

        # additional parametrization
        row += 1
        frame = Frame(self.frame)
        frame.grid(row=row, column=1, sticky="NEW")

        # use prior
        self.use_prior = IntVar()
        self.cb_use_prior = Checkbutton(frame, text="use prior with mean of ",
                                        variable=self.use_prior,
                                        command=self.onchange_useprior)
        self.cb_use_prior.pack(side=LEFT)

        # set prior 
        self.priorMean = StringVar(master)
        self.en_prior_mean = Entry(frame, textvariable=self.priorMean, width=5)
        self.en_prior_mean.pack(side=LEFT)
        self.priorMean.trace('w', self.settings_setdirty)
        Label(frame, text="and std dev of").pack(side=LEFT)

        # std. dev.
        self.priorStdDev = StringVar(master)
        self.en_stdev = Entry(frame, textvariable=self.priorStdDev, width=5)
        self.priorStdDev.trace('w', self.settings_setdirty)
        self.en_stdev.pack(side=LEFT)

        # use initial weights in MLN 
        self.use_initial_weights = IntVar()
        self.cb_use_initial_weights = Checkbutton(frame,
                                                  text="use initial weights",
                                                  variable=self.use_initial_weights,
                                                  command=self.settings_setdirty)
        self.cb_use_initial_weights.pack(side=LEFT)

        # use incremental learning
        self.incremental = IntVar()
        self.cb_incremental = Checkbutton(frame, text="learn incrementally",
                                          variable=self.incremental,
                                          command=self.onchange_incremental)
        self.cb_incremental.pack(side=LEFT)

        # shuffle databases
        self.shuffle = IntVar()
        self.cb_shuffle = Checkbutton(frame, text="shuffle databases",
                                      variable=self.shuffle, state='disabled')
        self.cb_shuffle.pack(side=LEFT)

        # discriminative learning settings
        row += 1
        self.discrPredicates = IntVar()
        self.discrPredicates.trace('w', self.change_discr_preds)
        self.discrPredicates.set(1)
        frame = Frame(self.frame)
        frame.grid(row=row, column=1, sticky="NEWS")
        self.rbQueryPreds = Radiobutton(frame, text="Query preds:",
                                        variable=self.discrPredicates,
                                        value=QUERY_PREDS)
        self.rbQueryPreds.grid(row=0, column=0, sticky="NE")

        self.queryPreds = StringVar(master)
        frame.columnconfigure(1, weight=1)
        self.entry_nePreds = Entry(frame, textvariable=self.queryPreds)
        self.entry_nePreds.grid(row=0, column=1, sticky="NEW")

        self.rbEvidencePreds = Radiobutton(frame, text='Evidence preds',
                                           variable=self.discrPredicates,
                                           value=EVIDENCE_PREDS)
        self.rbEvidencePreds.grid(row=0, column=2, sticky='NEWS')

        self.evidencePreds = StringVar(master)
        self.entryEvidencePreds = Entry(frame, textvariable=self.evidencePreds)
        self.entryEvidencePreds.grid(row=0, column=3, sticky='NEWS')

        # db section
        row += 1
        Label(self.frame, text="Evidence: ").grid(row=row, column=0, sticky='NE')
        self.db_container = FileEditBar(self.frame, dir=self.dir,
                                        filesettings={'extension': '.db', 'ftypes': [('Database files', '.db')]},
                                        defaultname='*unknown{}',
                                        importhook=self.import_db,
                                        deletehook=self.delete_db,
                                        projecthook=self.save_proj,
                                        filecontenthook=self.dbfilecontent,
                                        fileslisthook=self.dbfiles,
                                        updatehook=self.update_db,
                                        onchangehook=self.project_setdirty)
        self.db_container.grid(row=row, column=1, sticky="NEWS")
        self.db_container.columnconfigure(1, weight=2)
        self.frame.rowconfigure(row, weight=1)

        # file patterns
        row += 1
        frame = Frame(self.frame)
        frame.grid(row=row, column=1, sticky="NEW")
        col = 0
        Label(frame, text="OR file pattern:").grid(row=0, column=col, sticky="W")
        # - pattern entry
        col += 1
        frame.columnconfigure(col, weight=1)
        self.pattern = StringVar(master)
        self.pattern.trace('w', self.onchange_pattern)
        self.entry_pattern = Entry(frame, textvariable=self.pattern)
        self.entry_pattern.grid(row=0, column=col, sticky="NEW")

        # add. parameters
        row += 1
        Label(self.frame, text="Add. Params: ").grid(row=row, column=0, sticky="E")
        self.params = StringVar(master)
        Entry(self.frame, textvariable=self.params).grid(row=row, column=1, sticky="NEW")

        # options
        row += 1
        Label(self.frame, text="Options: ").grid(row=row, column=0, sticky="E")
        option_container = Frame(self.frame)
        option_container.grid(row=row, column=1, sticky="NEWS")

        # multicore
        self.multicore = IntVar()
        self.cb_multicore = Checkbutton(option_container, text="Use all CPUs",
                                        variable=self.multicore,
                                        command=self.settings_setdirty)
        self.cb_multicore.grid(row=0, column=1, sticky=E)

        # profiling
        self.profile = IntVar()
        self.cb_profile = Checkbutton(option_container, text='Use Profiler',
                                      variable=self.profile,
                                      command=self.settings_setdirty)
        self.cb_profile.grid(row=0, column=3, sticky=W)

        # verbose
        self.verbose = IntVar()
        self.cb_verbose = Checkbutton(option_container, text='verbose',
                                      variable=self.verbose, 
                                      command=self.settings_setdirty)
        self.cb_verbose.grid(row=0, column=4, sticky=W)

        self.ignore_zero_weight_formulas = IntVar()
        self.cb_ignore_zero_weight_formulas = Checkbutton(option_container, text='remove 0-weight formulas',
                                                          variable=self.ignore_zero_weight_formulas, command=self.settings_setdirty)
        self.cb_ignore_zero_weight_formulas.grid(row=0, column=5, sticky=W)

        # ignore unknown preds
        self.ignore_unknown_preds = IntVar(master)
        self.ignore_unknown_preds.trace('w', self.settings_setdirty)
        self.cb_ignore_unknown_preds = \
            Checkbutton(option_container, text='ignore unkown predicates', variable=self.ignore_unknown_preds)
        self.cb_ignore_unknown_preds.grid(row=0, column=6, sticky="W")

        row += 1
        output_cont = Frame(self.frame)
        output_cont.grid(row=row, column=1, sticky='NEWS')
        output_cont.columnconfigure(0, weight=1)

        Label(self.frame, text="Output: ").grid(row=row, column=0, sticky="E")
        self.output_filename = StringVar(master)
        self.entry_output_filename = Entry(output_cont, textvariable=self.output_filename)
        self.entry_output_filename.grid(row=0, column=0, sticky="EW")

        self.save = IntVar(self.master)
        self.cb_save = Checkbutton(output_cont, text='save', variable=self.save)
        self.cb_save.grid(row=0, column=1, sticky='W')

        row += 1
        learn_button = Button(self.frame, text=" >> Start Learning << ", command=self.learn)
        learn_button.grid(row=row, column=1, sticky="EW")

        self.settings_dirty = IntVar()
        self.project_dirty = IntVar()

        self.gconf = gconf
        self.project = None
        self.project_dir = os.path.abspath(ifNone(directory, ifNone(gconf['prev_learnwts_path'], os.getcwd())))
        if gconf['prev_learnwts_project': self.project_dir] is not None:
            self.load_project(os.path.join(self.project_dir, gconf['prev_learnwts_project':self.project_dir]))
        else:
            self.new_project()
        self.config = self.project.learnconf
        self.project.addlistener(self.project_setdirty)

        self.mln_container.dirty = False
        self.db_container.dirty = False
        self.project_setdirty(dirty=False)

        self.master.geometry(gconf['window_loc_learn'])

        self.initialized = True


    def quit(self):
        if self.settings_dirty.get() or self.project_dirty.get():
            savechanges = tkMessageBox.askyesnocancel("Save changes", "You have unsaved project changes. Do you want to save them before quitting?")
            if savechanges is None:
                return
            elif savechanges:
                self.noask_save_project()
            self.master.destroy()
        else:
            # write gui settings and destroy
            self.write_gconfig()
            self.master.destroy()


    ####################### PROJECT FUNCTIONS #################################

    def new_project(self):
        self.project = MLNProject()
        self.project.addlistener(self.project_setdirty)
        self.project.name = DEFAULTNAME.format('.pracmln')
        self.reset_gui()
        self.set_config(self.project.learnconf)
        self.mln_container.update_file_choices()
        self.db_container.update_file_choices()
        self.settings_setdirty()


    def project_setdirty(self, dirty=False, *args):
        self.project_dirty.set(
            dirty or self.mln_container.dirty or self.db_container.dirty)
        self.changewindowtitle()


    def settings_setdirty(self, *args):
        self.settings_dirty.set(1)
        self.changewindowtitle()


    def changewindowtitle(self):
        title = (WINDOWTITLEEDITED if (self.settings_dirty.get() or self.project_dirty.get()) else WINDOWTITLE).format(self.project_dir, self.project.name)
        self.master.title(title)


    def ask_load_project(self):
        filename = askopenfilename(initialdir=self.dir, filetypes=[('PRACMLN project files', '.pracmln')], defaultextension=".pracmln")
        if filename and os.path.exists(filename):
            self.load_project(filename)
        else:
            logger.info('No file selected.')
            return


    def load_project(self, filename):
        if filename and os.path.exists(filename):
            projdir, _ = ntpath.split(filename)
            self.dir = os.path.abspath(projdir)
            self.project_dir = os.path.abspath(projdir)
            self.project = MLNProject.open(filename)
            self.project.addlistener(self.project_setdirty)
            self.reset_gui()
            self.set_config(self.project.learnconf.config)
            self.mln_container.update_file_choices()
            self.db_container.update_file_choices()
            if len(self.project.mlns) > 0:
                self.mln_container.selected_file.set(self.project.learnconf['mln'] or self.project.mlns.keys()[0])
            self.mln_container.dirty = False
            if len(self.project.dbs) > 0:
                self.db_container.selected_file.set(self.project.learnconf['db'] or self.project.dbs.keys()[0])
            self.db_container.dirty = False
            self.write_gconfig(savegeometry=False)
            self.settings_dirty.set(0)
            self.project_setdirty(dirty=False)
            self.changewindowtitle()
        else:
            logger.error(
                'File {} does not exist. Creating new project...'.format(
                    filename))
            self.new_project()


    def noask_save_project(self):
        if self.project.name and not self.project.name == DEFAULTNAME .format('.pracmln'):
            self.save_project(
                os.path.join(self.project_dir, self.project.name))
        else:
            self.ask_save_project()


    def ask_save_project(self):
        fullfilename = asksaveasfilename(initialdir=self.project_dir,
                                         confirmoverwrite=True,
                                         filetypes=[('PRACMLN project files', '.pracmln')],
                                         defaultextension=".pracmln")
        self.save_project(fullfilename)


    def save_project(self, fullfilename):
        if fullfilename:
            fpath, fname = ntpath.split(fullfilename)
            fname = fname.split('.')[0]
            self.project.name = fname
            self.dir = os.path.abspath(fpath)
            self.project_dir = os.path.abspath(fpath)

            self.mln_container.save_all_files()
            self.db_container.save_all_files()

            self.update_config()
            self.project.save(dirpath=self.project_dir)
            self.write_gconfig()

            self.load_project(fullfilename)
            self.settings_dirty.set(0)


    def save_proj(self):
        self.project.save(dirpath=self.project_dir)
        self.write_gconfig()
        self.project_setdirty(dirty=False)

    ####################### MLN FUNCTIONS #####################################

    def import_mln(self, name, content):
        self.project.add_mln(name, content)


    def delete_mln(self, fname):
        if fname in self.project.mlns:
            self.project.rm_mln(fname)
        fnamestr = fname.strip('*')
        if fnamestr in self.project.mlns:
            self.project.rm_mln(fnamestr)


    def update_mln(self, old=None, new=None, content=None, askoverwrite=True):
        if old is None:
            old = self.mln_container.selected_file.get()
        if new is None:
            new = self.mln_container.selected_file.get().strip('*')
        if content is None:
            content = self.mln_container.editor.get("1.0", END).strip()

        if old == new and askoverwrite:
            savechanges = tkMessageBox.askyesno("Save changes",
                                                "A file '{}' already exists. "
                                                "Overwrite?".format(new))
            if savechanges:
                self.project.mlns[old] = content
            else:
                logger.error('no name specified!')
                return -1
        elif old == new and not askoverwrite:
            self.project.mlns[old] = content
        else:
            if new in self.project.mlns:
                if askoverwrite:
                    savechanges = tkMessageBox.askyesno("Save changes", "A file '{}' already exists. Overwrite?".format(new))
                    if savechanges:
                        self.project.mlns[new] = content
                    else:
                        logger.error('no name specified!')
                        return -1
            else:
                self.project.mlns[new] = content
        return 1


    def mlnfiles(self):
        return self.project.mlns.keys()


    def mlnfilecontent(self, filename):
        return self.project.mlns.get(filename, '').strip()


    # /MLN FUNCTIONS ###################################

    ####################### DB FUNCTIONS #####################################

    def import_db(self, name, content):
        self.project.add_db(name, content)


    def delete_db(self, fname):
        if fname in self.project.dbs:
            self.project.rm_db(fname)
        fnamestr = fname.strip('*')
        if fnamestr in self.project.dbs:
            self.project.rm_db(fnamestr)


    def update_db(self, old=None, new=None, content=None, askoverwrite=True):
        if old is None:
            old = self.db_container.selected_file.get()
        if new is None:
            new = self.db_container.selected_file.get().strip('*')
        if content is None:
            content = self.db_container.editor.get("1.0", END).strip()

        if old == new and askoverwrite:
            savechanges = tkMessageBox.askyesno("Save changes", "A file '{}' already exists. Overwrite?".format(new))
            if savechanges:
                self.project.dbs[old] = content
            else:
                logger.error('no name specified!')
                return -1
        elif old == new and not askoverwrite:
            self.project.dbs[old] = content
        else:
            if new in self.project.dbs:
                if askoverwrite:
                    savechanges = tkMessageBox.askyesno("Save changes", "A file '{}' already exists. Overwrite?".format(new))
                    if savechanges:
                        self.project.dbs[new] = content
                    else:
                        logger.error('no name specified!')
                        return -1
            else:
                self.project.dbs[new] = content
        return 1


    def dbfiles(self):
        return self.project.dbs.keys()


    def dbfilecontent(self, filename):
        return self.project.dbs.get(filename, '').strip()


    # /DB FUNCTIONS #####################################

    # GENERAL FUNCTIONS #################################

    def onchange_incremental(self):
        if self.incremental.get() == 1:
            self.cb_shuffle.configure(state="normal")
        else:
            self.cb_shuffle.configure(state="disabled")
            self.cb_shuffle.deselect()
        self.settings_setdirty()


    def onchange_pattern(self, *args):
        self.db_container.editor.disable(self.pattern.get())
        self.db_container.list_files.config(
            state=DISABLED if self.pattern.get() else NORMAL)
        self.settings_setdirty()


    def onchange_useprior(self, *args):
        self.en_prior_mean.configure(
            state=NORMAL if self.use_prior.get() else DISABLED)
        self.en_stdev.configure(
            state=NORMAL if self.use_prior.get() else DISABLED)
        self.settings_setdirty()


    def isfile(self, f):
        return os.path.exists(os.path.join(self.dir, f))


    def set_outputfilename(self):
        if not hasattr(self, "output_filename") or not hasattr(self, "db_filename") or not hasattr(self, "mln_filename"):
            return
        mln = self.mln_container.selected_file.get()
        db = self.db_container.selected_file.get()
        if "" in (mln, db):
            return
        if self.selected_method.get():
            method = LearningMethods.clazz(self.selected_method.get())
            methodid = LearningMethods.id(method)
            filename = config.learnwts_output_filename(mln, methodid.lower(), db)
            self.output_filename.set(filename)


    def select_method(self, *args):
        self.change_discr_preds()
        self.set_outputfilename()
        self.settings_setdirty()


    def change_discr_preds(self, *args):
        methodname = self.selected_method.get()
        if methodname:
            method = LearningMethods.clazz(methodname)
            state = NORMAL if issubclass(method, DiscriminativeLearner) else DISABLED
            self.entry_nePreds.configure(state=state if self.discrPredicates.get() == 0 else DISABLED)
            self.entryEvidencePreds.configure(state=state if self.discrPredicates.get() == 1 else DISABLED)
            self.rbEvidencePreds.configure(state=state)
            self.rbQueryPreds.configure(state=state)


    def reset_gui(self):
        self.set_config({})
        self.db_container.clear()
        self.mln_container.clear()


    def set_config(self, newconf):
        self.config = newconf
        self.selected_grammar.set(ifNone(newconf.get('grammar'), 'PRACGrammar'))
        self.selected_logic.set(ifNone(newconf.get('logic'), 'FirstOrderLogic'))
        self.mln_container.selected_file.set(ifNone(newconf.get('mln'), ''))
        self.db_container.selected_file.set(ifNone(newconf.get('db'), ""))
        self.selected_method.set(ifNone(newconf.get("method"), LearningMethods.name('BPLL'), transform=LearningMethods.name))
        self.pattern.set(ifNone(newconf.get('pattern'), ''))
        self.multicore.set(ifNone(newconf.get('multicore'), 0))
        self.use_prior.set(ifNone(newconf.get('use_prior'), 0))
        self.priorMean.set(ifNone(newconf.get('prior_mean'), 0))
        self.priorStdDev.set(ifNone(newconf.get('prior_stdev'), 5))
        self.incremental.set(ifNone(newconf.get('incremental'), 0))
        self.shuffle.set(ifNone(newconf.get('shuffle'), 0))
        self.use_initial_weights.set(ifNone(newconf.get('use_initial_weights'), 0))
        self.profile.set(ifNone(newconf.get('profile'), 0))
        self.params.set(ifNone(newconf.get('params'), ''))
        self.verbose.set(ifNone(newconf.get('verbose'), 1))
        self.ignore_unknown_preds.set(ifNone(newconf.get('ignore_unknown_preds'), 0))
        self.output_filename.set(ifNone(newconf.get('output_filename'), ''))
        self.queryPreds.set(ifNone(newconf.get('qpreds'), ''))
        self.evidencePreds.set(ifNone(newconf.get('epreds'), ''))
        self.discrPredicates.set(ifNone(newconf.get('discr_preds'), 0))
        self.ignore_zero_weight_formulas.set(ifNone(newconf.get('ignore_zero_weight_formulas'), 0))
        self.save.set(ifNone(newconf.get('save'), 0))


    def get_training_db_paths(self, pattern):
        '''
        determine training databases(s)
        '''
        local = False
        dbs = []
        if pattern is not None and pattern.strip():
            fpath, pat = ntpath.split(pattern)
            if not os.path.exists(fpath):
                logger.debug('{} does not exist. Searching for pattern {} in project {}...'.format(fpath, pat, self.project.name))
                local = True
                dbs = [db for db in self.project.dbs if fnmatch.fnmatch(db, pattern)]
                if len(dbs) == 0:
                    raise Exception("The pattern '{}' matches no files in your project {}".format(pat, self.project.name))
            else:
                local = False
                patternpath = os.path.join(self.dir, pattern)

                d, mask = os.path.split(os.path.abspath(patternpath))
                for fname in os.listdir(d):
                    print fname
                    if fnmatch.fnmatch(fname, mask):
                        dbs.append(os.path.join(d, fname))
                if len(dbs) == 0:
                    raise Exception("The pattern '%s' matches no files in %s" % (pat, fpath))
            logger.debug(
                'loading training databases from pattern %s:' % pattern)
            for p in dbs: logger.debug('  %s' % p)
        if not dbs:
            raise Exception("No training data given; A training database must be selected or a pattern must be specified")
        else:
            return local, dbs


    def update_config(self):
        out('update_config')

        self.config = PRACMLNConfig()
        self.config['mln'] = self.mln_container.selected_file.get().strip().lstrip('*')
        self.config["db"] = self.db_container.selected_file.get().strip().lstrip('*')
        self.config["output_filename"] = self.output_filename.get()
        self.config["params"] = self.params.get().strip()
        self.config["method"] = LearningMethods.id(self.selected_method.get().strip())
        self.config["pattern"] = self.pattern.get()
        self.config["use_prior"] = int(self.use_prior.get())
        self.config["prior_mean"] = self.priorMean.get()
        self.config["prior_stdev"] = self.priorStdDev.get()
        self.config["incremental"] = int(self.incremental.get())
        self.config["shuffle"] = int(self.shuffle.get())
        self.config["use_initial_weights"] = int(self.use_initial_weights.get())
        self.config["qpreds"] = self.queryPreds.get().strip()
        self.config["epreds"] = self.evidencePreds.get().strip()
        self.config["discr_preds"] = self.discrPredicates.get()
        self.config['logic'] = self.selected_logic.get()
        self.config['grammar'] = self.selected_grammar.get()
        self.config['multicore'] = self.multicore.get()
        self.config['profile'] = self.profile.get()
        self.config['verbose'] = self.verbose.get()
        self.config['ignore_unknown_preds'] = self.ignore_unknown_preds.get()
        self.config['ignore_zero_weight_formulas'] = self.ignore_zero_weight_formulas.get()
        self.config['save'] = self.save.get()
        self.config["output_filename"] = self.output_filename.get().strip()
        self.project.learnconf = PRACMLNConfig()
        self.project.learnconf.update(self.config.config.copy())


    def write_gconfig(self, savegeometry=True):
        self.gconf['prev_learnwts_path'] = self.project_dir
        self.gconf['prev_learnwts_project': self.project_dir] = self.project.name

        # save geometry
        if savegeometry:
            self.gconf['window_loc_learn'] = self.master.geometry()
        self.gconf.dump()


    def learn(self, savegeometry=True, options={}, *args):
        mln_content = self.mln_container.editor.get("1.0", END).encode('utf8').strip()
        db_content = self.db_container.editor.get("1.0", END).encode('utf8').strip()

        # create conf from current gui settings
        self.update_config()

        # write gui settings
        self.write_gconfig(savegeometry=savegeometry)

        # hide gui
        self.master.withdraw()

        try:
            print headline('PRAC LEARNING TOOL')
            print

            if options.get('mlnarg') is not None:
                mlnobj = MLN(mlnfile=os.path.abspath(options.get('mlnarg')),
                             logic=self.config.get('logic', 'FirstOrderLogic'),
                             grammar=self.config.get('grammar', 'PRACGrammar'))
            else:
                mlnobj = parse_mln(mln_content, searchpaths=[self.project_dir],
                                   projectpath=os.path.join(self.project_dir, self.project.name),
                                   logic=self.config.get('logic', 'FirstOrderLogic'),
                                   grammar=self.config.get('grammar', 'PRACGrammar'))

            if options.get('dbarg') is not None:
                dbobj = Database.load(mlnobj, dbfiles=[options.get('dbarg')], ignore_unknown_preds=self.config.get('ignore_unknown_preds', True))
            else:
                if self.config.get('pattern'):
                    local, dblist = self.get_training_db_paths(self.config.get('pattern').strip())
                    dbobj = []
                    # build database list from project dbs
                    if local:
                        for dbname in dblist:
                            dbobj.extend(parse_db(mlnobj, self.project.dbs[dbname].strip(),
                                         ignore_unknown_preds=self.config.get('ignore_unknown_preds', True),
                                         projectpath=os.path.join(self.dir, self.project.name)))
                        out(dbobj)
                    # build database list from filesystem dbs
                    else:
                        for dbpath in dblist:
                            dbobj.extend(Database.load(mlnobj, dbpath, ignore_unknown_preds= self.config.get('ignore_unknown_preds', True)))
                # build single db from currently selected db
                else:
                    dbobj = parse_db(mlnobj, db_content, projectpath=os.path.join(self.dir, self.project.name), dirs=[self.dir])

            learning = MLNLearn(config=self.config, mln=mlnobj, db=dbobj)
            result = learning.run()

            # write to file if run from commandline, otherwise save result
            # to project results
            if options.get('outputfile') is not None:
                output = StringIO.StringIO()
                result.write(output)
                with open(os.path.abspath(options.get('outputfile')), 'w') as f:
                    f.write(output.getvalue())
                logger.info('saved result to {}'.format(os.path.abspath(options.get('outputfile'))))
            elif self.save.get():
                output = StringIO.StringIO()
                result.write(output)
                self.project.add_mln(self.output_filename.get(), output.getvalue())
                self.mln_container.update_file_choices()
                self.project.save(dirpath=self.project_dir)
                logger.info('saved result to file mln/{} in project {}'.format(self.output_filename.get(), self.project.name))
            else:
                logger.debug("No output file given - results have not been saved.")
        except:
            traceback.print_exc()

        # restore gui
        sys.stdout.flush()
        self.master.deiconify()
Exemple #12
0
                      "--queries",
                      dest="queryarg",
                      help="queries (comma-separated)")
    parser.add_option("-e",
                      "--evidence",
                      dest="dbarg",
                      help="the evidence database file")
    parser.add_option("-r",
                      "--results-file",
                      dest="outputfile",
                      help="the results file to save")
    parser.add_option("--run",
                      action="store_true",
                      dest="run",
                      default=False,
                      help="run with last settings (without showing GUI)")
    (opts, args) = parser.parse_args()
    options = vars(opts)

    root = Tk()
    conf = PRACMLNConfig(DEFAULT_CONFIG)
    app = MLNQueryGUI(root,
                      conf,
                      directory=os.path.abspath(args[0]) if args else None)

    if opts.run:
        logger.debug('running mlnlearn without gui')
        app.infer(savegeometry=False, options=options)
    else:
        root.mainloop()
Exemple #13
0
def main():
    logger.level = logs.DEBUG

    usage = 'PRAC Query Tool'

    parser = argparse.ArgumentParser(description=usage)
    parser.add_argument("instruction", help="The instruction.")
    parser.add_argument(
        "-i",
        "--interactive",
        dest="interactive",
        default=False,
        action='store_true',
        help="Starts PRAC inference with an interactive GUI tool.")
    parser.add_argument("-v",
                        "--verbose",
                        dest="verbose",
                        default=1,
                        type=int,
                        action="store",
                        help="Set verbosity level {0..3}. Default is 1.")

    args = parser.parse_args()
    opts_ = vars(args)

    sentences = args.instruction
    prac = PRAC()
    prac.verbose = args.verbose

    conf = PRACMLNConfig(DEFAULT_CONFIG)

    if args.interactive:  # use the GUI
        from tkinter import Tk
        root = Tk()
        # in case we have natural-language parameters, parse them
        infer = PRACInference(prac, sentences)
        if len(sentences) > 0:
            # module = prac.module('nl_parsing')
            # prac.run(infer, module)
            n = infer.runstep()

            # print parsing result
            for odb in n.outdbs:
                odb.write()

            # print input sentence
            print(n.nlinstr())

            #Started control structure handling
            '''
            cs_recognition = prac.module('cs_recognition')
            prac.run(inference, cs_recognition)
            
            
            dbs = inference.inference_steps[-1].output_dbs
            dbs_ = []
            
            for db in dbs:
                dbs_.extend(parser.extract_multiple_action_cores(db)) 
            inference.inference_steps[-1].output_dbs = dbs_
            '''
            app = PRACQueryGUI(root,
                               infer.prac,
                               n,
                               conf,
                               directory=args[0] if args else None)
            root.mainloop()
        exit(0)

    # regular PRAC pipeline
    infer = PRACInference(prac, sentences)
    infer.run()

    print(headline('inference results'))
    print('instructions:')
    for i in infer.root:
        print(i)
    frames = []
    for step in infer.steps():
        print(step.frame)
    print(prac_heading('cram plans', color='blue'))
    for step in infer.steps():
        if hasattr(step, 'plan'):
            print(step.plan)


#     infer.write()
    exit(0)
Exemple #14
0
class PRACQueryGUI(object):
    def __init__(self, master, prac, node, gconf, directory='.'):
        self.logger = logs.getlogger(self.__class__.__name__, level=logs.DEBUG)
        self.master = master

        self.initialized = False

        self.master.bind('<Return>', self.start)
        self.master.bind('<Escape>', lambda a: self.master.quit())
        self.master.protocol('WM_DELETE_WINDOW', self.quit)

        self.prac = prac
        self.prac_inference = node.pracinfer
        self.infStep = None

        self.module_dir = os.path.join(locations.pracmodules, 'wnsenses')

        self.frame = Frame(master)
        self.frame.pack(fill=BOTH, expand=1)
        self.frame.columnconfigure(1, weight=1)

        # module selection
        row = 0
        Label(self.frame, text="Module: ").grid(row=row, column=0, sticky="E")
        modules = sorted([module for module in self.prac._manifests_by_name])
        self.selected_module = StringVar(master)
        self.selected_module.trace("w", self.select_module)
        self.list_modules = OptionMenu(*(self.frame, self.selected_module) +
                                       tuple(modules))
        self.list_modules.grid(row=row, column=1, sticky="NWE")

        # Project selection
        row += 1
        Label(self.frame, text="Project: ").grid(row=row, column=0, sticky="E")
        saveprojectcontainer = Frame(self.frame)
        saveprojectcontainer.grid(row=row, column=1, sticky="NEWS")
        saveprojectcontainer.columnconfigure(0, weight=1)

        self.selected_project = StringVar(master)
        projectfiles = ['']
        self.list_projects = OptionMenu(
            *(saveprojectcontainer, self.selected_project) +
            tuple(projectfiles))
        self.list_projects.grid(row=0, column=0, sticky="NWES")
        self.selected_project.trace("w", self.select_project)

        # save proj file
        self.btn_saveproj = Button(saveprojectcontainer,
                                   text='Save Project...',
                                   command=self.noask_save_project)
        self.btn_saveproj.grid(row=0, column=1, sticky="E")

        # save proj file as...
        self.btn_saveproj = Button(saveprojectcontainer,
                                   text='Save Project as...',
                                   command=self.ask_save_project)
        self.btn_saveproj.grid(row=0, column=2, sticky="E")

        # logic selection
        row += 1
        Label(self.frame, text='Logic: ').grid(row=row, column=0, sticky='E')
        logics = ['FirstOrderLogic', 'FuzzyLogic']
        self.selected_logic = StringVar(master)
        self.selected_logic.trace('w', self.settings_setdirty)
        l = OptionMenu(*(self.frame, self.selected_logic) + tuple(logics))
        l.grid(row=row, column=1, sticky='NWE')

        # mln section
        row += 1
        Label(self.frame, text="MLN: ").grid(row=row, column=0, sticky='NE')
        self.mln_container = FileEditBar(self.frame,
                                         dir=self.module_dir,
                                         filesettings={
                                             'extension': '.mln',
                                             'ftypes': [('MLN files', '.mln')]
                                         },
                                         defaultname='*unknown{}',
                                         importhook=self.import_mln,
                                         deletehook=self.delete_mln,
                                         projecthook=self.save_proj,
                                         filecontenthook=self.mlnfilecontent,
                                         fileslisthook=self.mlnfiles,
                                         updatehook=self.update_mln,
                                         onchangehook=self.project_setdirty)
        self.mln_container.grid(row=row, column=1, sticky="NEWS")
        self.mln_container.columnconfigure(1, weight=2)
        self.frame.rowconfigure(row, weight=1)

        row += 1
        self.use_emln = IntVar()
        self.use_emln.set(0)
        self.cb_use_emln = Checkbutton(self.frame,
                                       text="use model extension",
                                       variable=self.use_emln,
                                       command=self.onchange_use_emln)
        self.cb_use_emln.grid(row=row, column=1, sticky="W")

        # mln extension section
        row += 1
        self.emlncontainerrow = row
        self.emln_label = Label(self.frame, text="EMLN: ")
        self.emln_label.grid(row=self.emlncontainerrow, column=0, sticky='NE')
        self.emln_container = FileEditBar(self.frame,
                                          dir=self.module_dir,
                                          filesettings={
                                              'extension':
                                              '.emln',
                                              'ftypes':
                                              [('MLN extension files', '.emln')
                                               ]
                                          },
                                          defaultname='*unknown{}',
                                          importhook=self.import_emln,
                                          deletehook=self.delete_emln,
                                          projecthook=self.save_proj,
                                          filecontenthook=self.emlnfilecontent,
                                          fileslisthook=self.emlnfiles,
                                          updatehook=self.update_emln,
                                          onchangehook=self.project_setdirty)
        self.emln_container.grid(row=self.emlncontainerrow,
                                 column=1,
                                 sticky="NEWS")
        self.emln_container.columnconfigure(1, weight=2)
        self.onchange_use_emln(dirty=False)
        self.frame.rowconfigure(row, weight=1)

        # db section
        row += 1
        Label(self.frame, text="Evidence: ").grid(row=row,
                                                  column=0,
                                                  sticky='NE')
        self.db_container = FileEditBar(self.frame,
                                        dir=self.module_dir,
                                        filesettings={
                                            'extension': '.db',
                                            'ftypes':
                                            [('Database files', '.db')]
                                        },
                                        defaultname='*unknown{}',
                                        importhook=self.import_db,
                                        deletehook=self.delete_db,
                                        projecthook=self.save_proj,
                                        filecontenthook=self.dbfilecontent,
                                        fileslisthook=self.dbfiles,
                                        updatehook=self.update_db,
                                        onchangehook=self.project_setdirty)
        self.db_container.grid(row=row, column=1, sticky="NEWS")
        self.db_container.columnconfigure(1, weight=2)
        self.frame.rowconfigure(row, weight=1)

        # inference method selection
        row += 1
        self.list_methods_row = row
        Label(self.frame, text="Method: ").grid(row=row, column=0, sticky=E)
        self.selected_method = StringVar(master)
        self.selected_method.trace('w', self.settings_setdirty)
        self.list_methods = OptionMenu(self.frame, self.selected_method,
                                       *InferenceMethods.names())
        self.list_methods.grid(row=self.list_methods_row,
                               column=1,
                               sticky="NWE")

        # queries
        row += 1
        Label(self.frame, text="Queries: ").grid(row=row, column=0, sticky=E)
        self.query = StringVar(master)
        Entry(self.frame, textvariable=self.query).grid(row=row,
                                                        column=1,
                                                        sticky="NEW")

        #  parameters
        row += 1
        Label(self.frame, text="Parameters: ").grid(row=row,
                                                    column=0,
                                                    sticky="NE")
        self.params = StringVar(master)
        self.entry_params = Entry(self.frame, textvariable=self.params)
        self.entry_params.grid(row=row, column=1, sticky="NEW")

        # closed-world predicates
        row += 1
        Label(self.frame, text="CW preds: ").grid(row=row,
                                                  column=0,
                                                  sticky="NE")
        self.cwpreds = StringVar(master)
        self.entry_cw = Entry(self.frame, textvariable=self.cwpreds)
        self.entry_cw.grid(row=row, column=1, sticky="NEW")

        # all preds open-world
        cw_container = Frame(self.frame)
        cw_container.grid(row=row, column=1, sticky="NES")
        self.closed_world = IntVar()
        self.cb_closed_world = Checkbutton(
            cw_container,
            text="Apply CW assumption to all except queries",
            variable=self.closed_world)
        self.cb_closed_world.grid(row=row, column=2, sticky='E')

        # Multiprocessing and verbose
        row += 1
        options_container = Frame(self.frame)
        options_container.grid(row=row, column=1, sticky='NEWS')

        self.multicore = IntVar()
        self.cb_multicore = Checkbutton(options_container,
                                        text="Use all CPUs",
                                        variable=self.multicore)
        self.cb_multicore.grid(row=0, column=0, sticky=W)

        self.verbose = IntVar()
        self.cb_verbose = Checkbutton(options_container,
                                      text="verbose",
                                      variable=self.verbose)
        self.cb_verbose.grid(row=0, column=1, sticky=W)

        self.keep_evidence = IntVar()
        self.cb_keep_evidence = Checkbutton(options_container,
                                            text="keep result",
                                            variable=self.keep_evidence)
        self.cb_keep_evidence.grid(row=0, column=2, sticky=W)
        self.keep_evidence.set(True)

        # start and continue buttons
        row += 1
        self.btn_container = Frame(self.frame)
        self.btn_container.grid(row=row, column=1, sticky='EW')

        start_button = Button(self.btn_container,
                              text="Start Inference",
                              command=self.start)
        start_button.grid(row=0, column=1, sticky='E')

        continue_button = Button(self.btn_container,
                                 text="Continue >",
                                 command=self.oncontinue)
        continue_button.grid(row=0, column=2, sticky='W')

        self.settings_dirty = IntVar()
        self.project_dirty = IntVar()

        self.gconf = gconf
        self.project = None
        self.dir = os.path.abspath(
            ifnone(gconf['prev_query_path'], DEFAULT_CONFIG))
        if gconf['prev_query_project':self.dir] is not None:
            self.load_project(
                os.path.join(self.dir, gconf['prev_query_project':self.dir]))
        else:
            self.new_project()

        self.config = self.project.queryconf
        self.project.addlistener(self.project_setdirty)

        self.selected_module.set(self.gconf.get("module", modules[0]))
        self.update_dbeditor_from_result(node.outdbs)
        self.mln_container.dirty = False
        self.emln_container.dirty = False
        self.db_container.dirty = False
        self.project_setdirty(dirty=False)

        self.master.geometry(gconf['window_loc_query'])

        self.initialized = True

    def quit(self):
        if self.settings_dirty.get() or self.project_dirty.get():
            savechanges = tkinter.messagebox.askyesnocancel(
                "Save changes",
                "You have unsaved project changes. Do you want to save them before quitting?"
            )
            if savechanges is None:
                return
            elif savechanges:
                self.noask_save_project()
            self.master.destroy()
        else:
            # write gui settings and destroy
            self.write_gconfig()
            self.master.destroy()

    ####################### PROJECT FUNCTIONS #################################
    def new_project(self):
        self.project = MLNProject()
        self.project.addlistener(self.project_setdirty)
        self.project.name = DEFAULTNAME.format('.pracmln')
        self.reset_gui()
        self.set_config(self.project.queryconf)
        self.mln_container.update_file_choices()
        self.emln_container.update_file_choices()
        self.db_container.update_file_choices()
        self.settings_setdirty()

    def project_setdirty(self, dirty=False, *args):
        self.project_dirty.set(dirty or self.mln_container.dirty
                               or self.db_container.dirty
                               or self.emln_container.dirty)
        self.changewindowtitle()

    def settings_setdirty(self, *args):
        self.settings_dirty.set(1)
        self.changewindowtitle()

    def changewindowtitle(self):
        title = (WINDOWTITLEEDITED if
                 (self.settings_dirty.get() or self.project_dirty.get()) else
                 WINDOWTITLE).format(self.dir, self.project.name)
        self.master.title(title)

    def select_project(self, *args):
        filename = os.path.join(
            self.prac.manifest(self.selected_module.get()).module_path,
            self.selected_project.get())
        if filename and os.path.exists(filename):
            self.load_project(filename)
        else:
            self.logger.info('No file selected.')
            return

    def load_project(self, filename):
        if filename and os.path.exists(filename):
            projdir, _ = ntpath.split(filename)
            self.dir = os.path.abspath(projdir)
            self.module_dir = os.path.abspath(projdir)
            self.project = MLNProject.open(filename)
            self.project.addlistener(self.project_setdirty)
            self.reset_gui(keepdb=True)
            self.set_config(self.project.queryconf.config)
            self.mln_container.update_file_choices()
            self.db_container.update_file_choices()
            if len(self.project.mlns) > 0:
                self.mln_container.selected_file.set(
                    self.project.queryconf['mln']
                    or list(self.project.mlns.keys())[0])
                self.mln_container.dirty = False
            if len(self.project.emlns) > 0:
                self.emln_container.selected_file.set(
                    self.project.queryconf['emln']
                    or list(self.project.emlns.keys())[0])
                self.emln_container.dirty = False
            if len(self.project.dbs) > 0 and not self.keep_evidence.get():
                self.db_container.selected_file.set(
                    self.project.queryconf['db']
                    or list(self.project.dbs.keys())[0])
            self.write_gconfig(savegeometry=False)
            self.settings_dirty.set(0)
            self.changewindowtitle()
        else:
            self.logger.error(
                'File {} does not exist. Creating new project...'.format(
                    filename))
            self.new_project()

    def noask_save_project(self):
        if self.project.name and not self.project.name == DEFAULTNAME.format(
                '.pracmln'):
            self.save_project(os.path.join(self.module_dir, self.project.name))
        else:
            self.ask_save_project()

    def ask_save_project(self):
        fullfilename = asksaveasfilename(initialdir=self.module_dir,
                                         confirmoverwrite=True,
                                         filetypes=[('PRACMLN project files',
                                                     '.pracmln')],
                                         defaultextension=".pracmln")
        self.save_project(fullfilename)

    def save_project(self, fullfilename):
        if fullfilename is not None:
            fpath, fname = ntpath.split(fullfilename)
            fname = fname.split('.')[0]
            self.project.name = fname
            self.dir = os.path.abspath(fpath)
            self.module_dir = os.path.abspath(fpath)

            self.mln_container.save_all_files()
            self.emln_container.save_all_files()
            self.db_container.save_all_files()

            self.update_config()
            self.project.save(dirpath=self.module_dir)
            self.write_gconfig()

            self.load_project(fullfilename)
            self.settings_dirty.set(0)

    def save_proj(self):
        self.project.save(dirpath=self.module_dir)
        self.write_gconfig()
        self.project_setdirty()

    ####################### MLN FUNCTIONS #####################################
    def import_mln(self, name, content):
        self.project.add_mln(name, content)

    def delete_mln(self, fname):
        if fname in self.project.mlns:
            self.project.rm_mln(fname)
        fnamestr = fname.strip('*')
        if fnamestr in self.project.mlns:
            self.project.rm_mln(fnamestr)

    def update_mln(self, old=None, new=None, content=None, askoverwrite=True):
        if old is None:
            old = self.mln_container.selected_file.get()
        if new is None:
            new = self.mln_container.selected_file.get().strip('*')
        if content is None:
            content = self.mln_container.editor.get("1.0", END).strip()

        if old == new and askoverwrite:
            savechanges = tkinter.messagebox.askyesno(
                "Save changes",
                "A file '{}' already exists. Overwrite?".format(new))
            if savechanges:
                self.project.mlns[old] = content
            else:
                self.logger.error('no name specified!')
                return -1
        elif old == new and not askoverwrite:
            self.project.mlns[old] = content
        else:
            if new in self.project.mlns:
                if askoverwrite:
                    savechanges = tkinter.messagebox.askyesno(
                        "Save changes",
                        "A file '{}' already exists. Overwrite?".format(new))
                    if savechanges:
                        self.project.mlns[new] = content
                    else:
                        self.logger.error('no name specified!')
                        return -1
            else:
                self.project.mlns[new] = content
        return 1

    def mlnfiles(self):
        return list(self.project.mlns.keys())

    def mlnfilecontent(self, filename):
        return self.project.mlns.get(filename, '').strip()

    ####################### /MLN FUNCTIONS #####################################

    ####################### EMLN FUNCTIONS #####################################
    def import_emln(self, name, content):
        self.project.add_emln(name, content)

    def delete_emln(self, fname):
        if fname in self.project.emlns:
            self.project.rm_emln(fname)
        fnamestr = fname.strip('*')
        if fnamestr in self.project.emlns:
            self.project.rm_emln(fnamestr)

    def update_emln(self, old=None, new=None, content=None, askoverwrite=True):
        if old is None:
            old = self.emln_container.selected_file.get()
        if new is None:
            new = self.emln_container.selected_file.get().strip('*')
        if content is None:
            content = self.emln_container.editor.get("1.0", END).strip()

        if old == new and askoverwrite:
            savechanges = tkinter.messagebox.askyesno(
                "Save changes",
                "A file '{}' already exists. Overwrite?".format(new))
            if savechanges:
                self.project.emlns[old] = content
            else:
                self.logger.error('no name specified!')
                return -1
        elif old == new and not askoverwrite:
            self.project.emlns[old] = content
        else:
            if new in self.project.emlns:
                if askoverwrite:
                    savechanges = tkinter.messagebox.askyesno(
                        "Save changes",
                        "A file '{}' already exists. Overwrite?".format(new))
                    if savechanges:
                        self.project.emlns[new] = content
                    else:
                        self.logger.error('no name specified!')
                        return -1
            else:
                self.project.emlns[new] = content
        return 1

    def emlnfiles(self):
        return list(self.project.emlns.keys())

    def emlnfilecontent(self, filename):
        return self.project.emlns.get(filename, '').strip()

    ####################### /EMLN FUNCTIONS #####################################

    ####################### DB FUNCTIONS #####################################
    def import_db(self, name, content):
        self.project.add_db(name, content)

    def delete_db(self, fname):
        if fname in self.project.dbs:
            self.project.rm_db(fname)
        fnamestr = fname.strip('*')
        if fnamestr in self.project.dbs:
            self.project.rm_db(fnamestr)

    def update_db(self, old=None, new=None, content=None, askoverwrite=True):
        if old is None:
            old = self.db_container.selected_file.get()
        if new is None:
            new = self.db_container.selected_file.get().strip('*')
        if content is None:
            content = self.db_container.editor.get("1.0", END).strip()

        if old == new and askoverwrite:
            savechanges = tkinter.messagebox.askyesno(
                "Save changes",
                "A file '{}' already exists. Overwrite?".format(new))
            if savechanges:
                self.project.dbs[old] = content
            else:
                self.logger.error('no name specified!')
                return -1
        elif old == new and not askoverwrite:
            self.project.dbs[old] = content
        else:
            if new in self.project.dbs:
                if askoverwrite:
                    savechanges = tkinter.messagebox.askyesno(
                        "Save changes",
                        "A file '{}' already exists. Overwrite?".format(new))
                    if savechanges:
                        self.project.dbs[new] = content
                    else:
                        self.logger.error('no name specified!')
                        return -1
            else:
                self.project.dbs[new] = content
        return 1

    def dbfiles(self):
        return list(self.project.dbs.keys())

    def dbfilecontent(self, filename):
        return self.project.dbs.get(filename, '').strip()

    ####################### /DB FUNCTIONS #####################################

    ####################### GENERAL FUNCTIONS #################################

    def onchange_use_emln(self, dirty=True, *args):
        if not self.use_emln.get():
            self.emln_label.grid_forget()
            self.emln_container.grid_forget()
        else:
            self.emln_label.grid(row=self.emlncontainerrow,
                                 column=0,
                                 sticky="NE")
            self.emln_container.grid(row=self.emlncontainerrow,
                                     column=1,
                                     sticky="NWES")
        if dirty:
            self.settings_setdirty()

    def onchange_cw(self, *args):
        if self.closed_world.get():
            self.entry_cw.configure(state=DISABLED)
        else:
            self.entry_cw.configure(state=NORMAL)
        self.settings_setdirty()

    def reset_gui(self, keepdb=False):
        self.set_config({})
        self.db_container.clear(keep=keepdb)
        self.emln_container.clear()
        self.mln_container.clear()

    def set_config(self, conf):
        self.config = conf
        self.selected_logic.set(ifnone(conf.get('logic'), 'FirstOrderLogic'))
        self.mln_container.selected_file.set(ifnone(conf.get('mln'), ''))
        if not self.keep_evidence:
            self.db_container.selected_file.set(ifnone(conf.get('db'), ''))
        self.selected_method.set(
            ifnone(self.config.get("method"),
                   InferenceMethods.name('MCSAT'),
                   transform=InferenceMethods.name))
        self.use_emln.set(ifnone(conf.get('use_emln'), False))
        if self.use_emln.get():
            self.emln_container.selected_file.set(ifnone(conf.get('emln'), ""))
        self.multicore.set(ifnone(conf.get('multicore'), False))
        self.verbose.set(ifnone(conf.get('verbose'), False))
        self.params.set(ifnone(conf.get('params'), ''))
        self.cwpreds.set(ifnone(conf.get('cw_preds'), ''))
        self.closed_world.set(ifnone(conf.get('cw'), False))
        self.query.set(ifnone(conf.get('queries'), 'foo, bar'))

    def update_config(self):

        self.config = PRACMLNConfig()
        self.config['mln'] = self.mln_container.selected_file.get().strip(
        ).lstrip('*')
        self.config['emln'] = self.emln_container.selected_file.get().strip(
        ).lstrip('*')
        self.config["db"] = self.db_container.selected_file.get().strip(
        ).lstrip('*')
        self.config["method"] = InferenceMethods.id(
            self.selected_method.get().strip())
        self.config["params"] = self.params.get().strip()
        self.config["queries"] = self.query.get()
        self.config["cw"] = self.closed_world.get()
        self.config["cw_preds"] = self.cwpreds.get()
        self.config["use_emln"] = self.use_emln.get()
        self.config['logic'] = self.selected_logic.get()
        self.config['multicore'] = self.multicore.get()
        self.config['verbose'] = self.verbose.get()
        self.config['window_loc'] = self.master.winfo_geometry()
        self.config['dir'] = self.dir
        self.project.queryconf = PRACMLNConfig()
        self.project.queryconf.update(self.config.config.copy())

    def write_gconfig(self, savegeometry=True):
        self.gconf['prev_query_path'] = self.dir
        self.gconf['prev_query_project':self.dir] = self.project.name

        # save geometry
        if savegeometry:
            self.gconf['window_loc_query'] = self.master.geometry()
        self.gconf.dump()

    def select_module(self, *args):
        module = self.selected_module.get()
        module_path = self.prac.manifest(module).module_path
        dirpath = os.path.abspath(module_path)
        self.module_dir = dirpath
        self.update_project_choices()
        if self.gconf['prev_query_project':dirpath] is not None:
            self.selected_project.set(self.gconf['prev_query_project':dirpath])

    def update_project_choices(self):
        modulename = self.selected_module.get()
        module_path = self.prac.manifest(modulename).module_path

        # remove all items
        self.list_projects['menu'].delete(0, 'end')

        projects = [
            y for y in os.listdir(module_path)
            if os.path.isfile(os.path.join(module_path, y))
            and y.endswith('.pracmln')
        ]
        for p in projects:
            self.list_projects['menu'].add_command(label=p,
                                                   command=_setit(
                                                       self.selected_project,
                                                       p))

    def oncontinue(self):
        if self.infStep is None:
            self.start()

        curstep = self.prac_inference.lastnode.infchain[-1]
        evidence = curstep.outdbs

        self.update_dbeditor_from_result(evidence)
        self.logger.info(
            'Input databases have been replaced by the latest results.')

    def update_dbeditor_from_result(self, dbs):
        self.db_container.selected_file.set('')
        strbuf = io.StringIO()
        for i, db in enumerate(dbs):
            db.write(strbuf, bars=False, color=False)
            if i < len(dbs) - 1:
                strbuf.write('---\n')

        self.db_container.editor.delete("1.0", END)
        self.db_container.editor.insert(INSERT,
                                        strbuf.getvalue().encode('utf-8'))
        strbuf.close()
        self.db_container._editor_dirty = True

    def update_result_from_dbeditor(self):
        dbtext = self.db_container.editor.get("1.0",
                                              END).encode('utf8').strip()
        dbobj = parse_db(self.prac.mln,
                         dbtext,
                         ignore_unknown_preds=self.config.get(
                             'ignore_unknown_preds', True))

        self.prac_inference.inference_steps[-1].output_dbs = dbobj

    def start(self, savegeometry=True):

        # create conf from current gui settings
        self.update_config()
        self.update_mln(askoverwrite=False)

        # write gui settings
        self.write_gconfig(savegeometry=savegeometry)

        # hide gui
        self.master.withdraw()

        # if evidence was modified in gui, update dbs for next inference step
        self.update_result_from_dbeditor()

        # runinference
        try:
            print(headline('PRAC QUERY TOOL'))
            print()

            next_step = self.prac_inference.runstep()
            curstep = self.prac_inference.lastnode.infchain[-1]
            evidence = curstep.outdbs

            module = self.prac.module(self.selected_module.get())

            self.infStep = module(self.prac_inference,
                                  project=self.project,
                                  projectpath=os.path.join(
                                      self.module_dir, self.project.name))

        except:
            cls, e, tb = sys.exc_info()
            sys.stderr.write("Error: %s\n" % str(e))
            traceback.print_tb(tb)

        # restore main window
        self.master.deiconify()
Exemple #15
0
class MLNQueryGUI(object):
    def __init__(self, master, gconf, directory=None):
        self.master = master
        # icon = Tkinter.Image("photo", file=os.path.join(PRACMLN_HOME, 'doc', '_static', 'favicon.ico'))
        # self.master.tk.call('wm', 'iconphoto', self.master._w, icon)

        self.initialized = False

        self.master.bind('<Return>', self.infer)
        self.master.bind('<Escape>', lambda a: self.master.quit())
        self.master.protocol('WM_DELETE_WINDOW', self.quit)

        self.dir = os.path.abspath(ifNone(directory, ifNone(gconf['prev_query_path'], os.getcwd())))

        self.frame = Frame(master)
        self.frame.pack(fill=BOTH, expand=1)
        self.frame.columnconfigure(1, weight=1)

        row = 0
        # pracmln project options
        Label(self.frame, text='PRACMLN Project: ').grid(row=row, column=0,
                                                         sticky='ES')
        project_container = Frame(self.frame)
        project_container.grid(row=row, column=1, sticky="NEWS")

        # new proj file
        self.btn_newproj = Button(project_container, text='New Project...', command=self.new_project)
        self.btn_newproj.grid(row=0, column=1, sticky="WS")

        # open proj file
        self.btn_openproj = Button(project_container, text='Open Project...', command=self.ask_load_project)
        self.btn_openproj.grid(row=0, column=2, sticky="WS")

        # save proj file
        self.btn_updateproj = Button(project_container, text='Save Project...', command=self.noask_save_project)
        self.btn_updateproj.grid(row=0, column=3, sticky="WS")

        # save proj file as...
        self.btn_saveproj = Button(project_container, text='Save Project as...', command=self.ask_save_project)
        self.btn_saveproj.grid(row=0, column=4, sticky="WS")

        # grammar selection
        row += 1
        Label(self.frame, text='Grammar: ').grid(row=row, column=0, sticky='E')
        grammars = ['StandardGrammar', 'PRACGrammar']
        self.selected_grammar = StringVar(master)
        self.selected_grammar.trace('w', self.settings_setdirty)
        l = apply(OptionMenu, (self.frame, self.selected_grammar) + tuple(grammars))
        l.grid(row=row, column=1, sticky='NWE')

        # logic selection
        row += 1
        Label(self.frame, text='Logic: ').grid(row=row, column=0, sticky='E')
        logics = ['FirstOrderLogic', 'FuzzyLogic']
        self.selected_logic = StringVar(master)
        self.selected_logic.trace('w', self.settings_setdirty)
        l = apply(OptionMenu, (self.frame, self.selected_logic) + tuple(logics))
        l.grid(row=row, column=1, sticky='NWE')

        # mln section
        row += 1
        Label(self.frame, text="MLN: ").grid(row=row, column=0, sticky='NE')
        self.mln_container = FileEditBar(self.frame, dir=self.dir,
                                         filesettings={'extension': '.mln', 'ftypes': [('MLN files', '.mln')]},
                                         defaultname='*unknown{}',
                                         importhook=self.import_mln,
                                         deletehook=self.delete_mln,
                                         projecthook=self.save_proj,
                                         filecontenthook=self.mlnfilecontent,
                                         fileslisthook=self.mlnfiles,
                                         updatehook=self.update_mln,
                                         onchangehook=self.project_setdirty)
        self.mln_container.grid(row=row, column=1, sticky="NEWS")
        self.mln_container.columnconfigure(1, weight=2)
        self.frame.rowconfigure(row, weight=1)

        row += 1
        self.use_emln = IntVar()
        self.use_emln.set(0)
        self.cb_use_emln = Checkbutton(self.frame, text="use model extension",
                                       variable=self.use_emln,
                                       command=self.onchange_use_emln)
        self.cb_use_emln.grid(row=row, column=1, sticky="W")

        # mln extension section
        row += 1
        self.emlncontainerrow = row
        self.emln_label = Label(self.frame, text="EMLN: ")
        self.emln_label.grid(row=self.emlncontainerrow, column=0, sticky='NE')
        self.emln_container = FileEditBar(self.frame,
                                          dir=self.dir,
                                          filesettings={'extension': '.emln', 'ftypes': [('MLN extension files','.emln')]},
                                          defaultname='*unknown{}',
                                          importhook=self.import_emln,
                                          deletehook=self.delete_emln,
                                          projecthook=self.save_proj,
                                          filecontenthook=self.emlnfilecontent,
                                          fileslisthook=self.emlnfiles,
                                          updatehook=self.update_emln,
                                          onchangehook=self.project_setdirty)
        self.emln_container.grid(row=self.emlncontainerrow, column=1, sticky="NEWS")
        self.emln_container.columnconfigure(1, weight=2)
        self.onchange_use_emln(dirty=False)
        self.frame.rowconfigure(row, weight=1)

        # db section
        row += 1
        Label(self.frame, text="Evidence: ").grid(row=row, column=0, sticky='NE')
        self.db_container = FileEditBar(self.frame, dir=self.dir,
                                        filesettings={'extension': '.db', 'ftypes': [('Database files', '.db')]},
                                        defaultname='*unknown{}',
                                        importhook=self.import_db,
                                        deletehook=self.delete_db,
                                        projecthook=self.save_proj,
                                        filecontenthook=self.dbfilecontent,
                                        fileslisthook=self.dbfiles,
                                        updatehook=self.update_db,
                                        onchangehook=self.project_setdirty)
        self.db_container.grid(row=row, column=1, sticky="NEWS")
        self.db_container.columnconfigure(1, weight=2)
        self.frame.rowconfigure(row, weight=1)

        # inference method selection
        row += 1
        self.list_methods_row = row
        Label(self.frame, text="Method: ").grid(row=row, column=0, sticky=E)
        self.selected_method = StringVar(master)
        self.selected_method.trace('w', self.select_method)
        methodnames = sorted(InferenceMethods.names())
        self.list_methods = apply(OptionMenu, (self.frame, self.selected_method) + tuple(methodnames))
        self.list_methods.grid(row=self.list_methods_row, column=1, sticky="NWE")

        # options
        row += 1
        option_container = Frame(self.frame)
        option_container.grid(row=row, column=1, sticky="NEWS")

        # Multiprocessing
        self.multicore = IntVar()
        self.cb_multicore = Checkbutton(option_container, text="Use all CPUs",
                                        variable=self.multicore,
                                        command=self.settings_setdirty)
        self.cb_multicore.grid(row=0, column=2, sticky=W)

        # profiling
        self.profile = IntVar()
        self.cb_profile = Checkbutton(option_container, text='Use Profiler',
                                      variable=self.profile,
                                      command=self.settings_setdirty)
        self.cb_profile.grid(row=0, column=3, sticky=W)

        # verbose
        self.verbose = IntVar()
        self.cb_verbose = Checkbutton(option_container, text='verbose',
                                      variable=self.verbose,
                                      command=self.settings_setdirty)
        self.cb_verbose.grid(row=0, column=4, sticky=W)

        # options
        self.ignore_unknown_preds = IntVar(master)
        self.cb_ignore_unknown_preds = Checkbutton(option_container,
                                                   text='ignore unkown predicates',
                                                   variable=self.ignore_unknown_preds,
                                                   command=self.settings_setdirty)
        self.cb_ignore_unknown_preds.grid(row=0, column=5, sticky="W")

        # queries
        row += 1
        Label(self.frame, text="Queries: ").grid(row=row, column=0, sticky=E)
        self.query = StringVar(master)
        self.query.trace('w', self.settings_setdirty)
        Entry(self.frame, textvariable=self.query).grid(row=row, column=1, sticky="NEW")

        # additional parameters
        row += 1
        Label(self.frame, text="Add. params: ").grid(row=row, column=0, sticky="NE")
        self.params = StringVar(master)
        self.params.trace('w', self.settings_setdirty)
        self.entry_params = Entry(self.frame, textvariable=self.params)
        self.entry_params.grid(row=row, column=1, sticky="NEW")

        # closed-world predicates
        row += 1
        Label(self.frame, text="CW preds: ").grid(row=row, column=0, sticky="E")

        cw_container = Frame(self.frame)
        cw_container.grid(row=row, column=1, sticky='NEWS')
        cw_container.columnconfigure(0, weight=1)

        self.cwPreds = StringVar(master)
        self.cwPreds.trace('w', self.settings_setdirty)
        self.entry_cw = Entry(cw_container, textvariable=self.cwPreds)
        self.entry_cw.grid(row=0, column=0, sticky="NEWS")

        self.closed_world = IntVar()
        self.cb_closed_world = Checkbutton(cw_container, text="CW Assumption",
                                           variable=self.closed_world,
                                           command=self.onchange_cw)
        self.cb_closed_world.grid(row=0, column=1, sticky='W')

        # output filename
        row += 1
        output_cont = Frame(self.frame)
        output_cont.grid(row=row, column=1, sticky='NEWS')
        output_cont.columnconfigure(0, weight=1)

        # - filename
        Label(self.frame, text="Output: ").grid(row=row, column=0, sticky="NE")
        self.output_filename = StringVar(master)
        self.entry_output_filename = Entry(output_cont, textvariable=self.output_filename)
        self.entry_output_filename.grid(row=0, column=0, sticky="NEW")

        # - save option
        self.save = IntVar()
        self.cb_save = Checkbutton(output_cont, text="save", variable=self.save)
        self.cb_save.grid(row=0, column=1, sticky=W)

        # start button
        row += 1
        start_button = Button(self.frame, text=">> Start Inference <<", command=self.infer)
        start_button.grid(row=row, column=1, sticky="NEW")

        self.settings_dirty = IntVar()
        self.project_dirty = IntVar()

        self.gconf = gconf
        self.project = None
        self.project_dir = os.path.abspath(ifNone(directory, ifNone(gconf['prev_query_path'], os.getcwd())))
        if gconf['prev_query_project': self.project_dir] is not None:
            self.load_project(os.path.join(self.project_dir, gconf['prev_query_project':self.project_dir]))
        else:
            self.new_project()

        self.config = self.project.queryconf
        self.project.addlistener(self.project_setdirty)

        self.mln_container.dirty = False
        self.emln_container.dirty = False
        self.db_container.dirty = False
        self.project_setdirty(dirty=False)

        self.master.geometry(gconf['window_loc_query'])

        self.initialized = True


    def quit(self):
        if self.settings_dirty.get() or self.project_dirty.get():
            savechanges = tkMessageBox.askyesnocancel("Save changes", "You have unsaved project changes. Do you want to save them before quitting?")
            if savechanges is None:
                return
            elif savechanges:
                self.noask_save_project()
            self.master.destroy()
        else:
            # write gui settings and destroy
            self.write_gconfig()
            self.master.destroy()


    ####################### PROJECT FUNCTIONS #################################

    def new_project(self):
        self.project = MLNProject()
        self.project.addlistener(self.project_setdirty)
        self.project.name = DEFAULTNAME.format('.pracmln')
        self.reset_gui()
        self.set_config(self.project.queryconf)
        self.mln_container.update_file_choices()
        self.emln_container.update_file_choices()
        self.db_container.update_file_choices()
        self.project_setdirty(dirty=True)


    def project_setdirty(self, dirty=False, *args):
        self.project_dirty.set(dirty or self.mln_container.dirty or self.db_container.dirty or
            self.emln_container.dirty)
        self.changewindowtitle()


    def settings_setdirty(self, *args):
        self.settings_dirty.set(1)
        self.changewindowtitle()


    def changewindowtitle(self):
        title = (WINDOWTITLEEDITED if (self.settings_dirty.get() or self.project_dirty.get()) else WINDOWTITLE).format(self.project_dir, self.project.name)
        self.master.title(title)


    def ask_load_project(self):
        filename = askopenfilename(initialdir=self.dir, filetypes=[('PRACMLN project files', '.pracmln')], defaultextension=".pracmln")
        if filename and os.path.exists(filename):
            self.load_project(filename)
        else:
            logger.info('No file selected.')
            return


    def load_project(self, filename):
        if filename and os.path.exists(filename):
            projdir, _ = ntpath.split(filename)
            self.dir = os.path.abspath(projdir)
            self.project_dir = os.path.abspath(projdir)
            self.project = MLNProject.open(filename)
            self.project.addlistener(self.project_setdirty)
            self.reset_gui()
            self.set_config(self.project.queryconf.config)
            self.mln_container.update_file_choices()
            self.db_container.update_file_choices()
            if len(self.project.mlns) > 0:
                self.mln_container.selected_file.set(self.project.queryconf['mln'] or self.project.mlns.keys()[0])
            self.mln_container.dirty = False
            if len(self.project.emlns) > 0:
                self.emln_container.selected_file.set(self.project.queryconf['emln'] or self.project.emlns.keys()[0])
            self.emln_container.dirty = False
            if len(self.project.dbs) > 0:
                self.db_container.selected_file.set(self.project.queryconf['db'] or self.project.dbs.keys()[0])
            self.db_container.dirty = False
            self.write_gconfig(savegeometry=False)
            self.settings_dirty.set(0)
            self.project_setdirty(dirty=False)
            self.changewindowtitle()
        else:
            logger.error('File {} does not exist. Creating new project...'.format(filename))
            self.new_project()


    def noask_save_project(self):
        if self.project.name and not self.project.name == DEFAULTNAME.format('.pracmln'):
            self.save_project(os.path.join(self.project_dir, self.project.name))
        else:
            self.ask_save_project()


    def ask_save_project(self):
        fullfilename = asksaveasfilename(initialdir=self.project_dir,
                                         confirmoverwrite=True,
                                         filetypes=[('PRACMLN project files','.pracmln')],
                                         defaultextension=".pracmln")
        self.save_project(fullfilename)


    def save_project(self, fullfilename):
        if fullfilename:
            fpath, fname = ntpath.split(fullfilename)
            fname = fname.split('.')[0]
            self.project.name = fname
            self.dir = os.path.abspath(fpath)
            self.project_dir = os.path.abspath(fpath)

            self.mln_container.save_all_files()
            self.emln_container.save_all_files()
            self.db_container.save_all_files()

            self.update_config()
            self.project.save(dirpath=self.project_dir)
            self.write_gconfig()

            self.load_project(fullfilename)
            self.settings_dirty.set(0)


    def save_proj(self):
        self.project.save(dirpath=self.project_dir)
        self.write_gconfig()
        self.project_setdirty(dirty=False)


    ####################### MLN FUNCTIONS #####################################

    def import_mln(self, name, content):
        self.project.add_mln(name, content)


    def delete_mln(self, fname):
        if fname in self.project.mlns:
            self.project.rm_mln(fname)
        fnamestr = fname.strip('*')
        if fnamestr in self.project.mlns:
            self.project.rm_mln(fnamestr)


    def update_mln(self, old=None, new=None, content=None, askoverwrite=True):
        if old is None:
            old = self.mln_container.selected_file.get()
        if new is None:
            new = self.mln_container.selected_file.get().strip('*')
        if content is None:
            content = self.mln_container.editor.get("1.0", END).strip()

        if old == new and askoverwrite:
            savechanges = tkMessageBox.askyesno("Save changes", "A file '{}' already exists. Overwrite?".format(new))
            if savechanges:
                self.project.mlns[old] = content
            else:
                logger.error('no name specified!')
                return -1
        elif old == new and not askoverwrite:
            self.project.mlns[old] = content
        else:
            if new in self.project.mlns:
                if askoverwrite:
                    savechanges = tkMessageBox.askyesno("Save changes", "A file '{}' already exists. Overwrite?".format(new))
                    if savechanges:
                        self.project.mlns[new] = content
                    else:
                        logger.error('no name specified!')
                        return -1
            else:
                self.project.mlns[new] = content
        return 1


    def mlnfiles(self):
        return self.project.mlns.keys()


    def mlnfilecontent(self, filename):
        return self.project.mlns.get(filename, '').strip()

    # /MLN FUNCTIONS #####################################


    ####################### EMLN FUNCTIONS #####################################

    def import_emln(self, name, content):
        self.project.add_emln(name, content)


    def delete_emln(self, fname):
        if fname in self.project.emlns:
            self.project.rm_emln(fname)
        fnamestr = fname.strip('*')
        if fnamestr in self.project.emlns:
            self.project.rm_emln(fnamestr)


    def update_emln(self, old=None, new=None, content=None, askoverwrite=True):
        if old is None:
            old = self.emln_container.selected_file.get()
        if new is None:
            new = self.emln_container.selected_file.get().strip('*')
        if content is None:
            content = self.emln_container.editor.get("1.0", END).strip()

        if old == new and askoverwrite:
            savechanges = tkMessageBox.askyesno("Save changes", "A file '{}' already exists. Overwrite?".format(new))
            if savechanges:
                self.project.emlns[old] = content
            else:
                logger.error('no name specified!')
                return -1
        elif old == new and not askoverwrite:
            self.project.emlns[old] = content
        else:
            if new in self.project.emlns:
                if askoverwrite:
                    savechanges = tkMessageBox.askyesno("Save changes", "A file '{}' already exists. Overwrite?".format(new))
                    if savechanges:
                        self.project.emlns[new] = content
                    else:
                        logger.error('no name specified!')
                        return -1
            else:
                self.project.emlns[new] = content
        return 1


    def emlnfiles(self):
        return self.project.emlns.keys()


    def emlnfilecontent(self, filename):
        return self.project.emlns.get(filename, '').strip()

    # /EMLN FUNCTIONS #####################################

    # DB FUNCTIONS #####################################
    def import_db(self, name, content):
        self.project.add_db(name, content)


    def delete_db(self, fname):
        if fname in self.project.dbs:
            self.project.rm_db(fname)
        fnamestr = fname.strip('*')
        if fnamestr in self.project.dbs:
            self.project.rm_db(fnamestr)


    def update_db(self, old=None, new=None, content=None, askoverwrite=True):
        if old is None:
            old = self.db_container.selected_file.get()
        if new is None:
            new = self.db_container.selected_file.get().strip('*')
        if content is None:
            content = self.db_container.editor.get("1.0", END).strip()

        if old == new and askoverwrite:
            savechanges = tkMessageBox.askyesno("Save changes", "A file '{}' already exists. Overwrite?".format(new))
            if savechanges:
                self.project.dbs[old] = content
            else:
                logger.error('no name specified!')
                return -1
        elif old == new and not askoverwrite:
            self.project.dbs[old] = content
        else:
            if new in self.project.dbs:
                if askoverwrite:
                    savechanges = tkMessageBox.askyesno("Save changes", "A file '{}' already exists. Overwrite?".format(new))
                    if savechanges:
                        self.project.dbs[new] = content
                    else:
                        logger.error('no name specified!')
                        return -1
            else:
                self.project.dbs[new] = content
        return 1


    def dbfiles(self):
        return self.project.dbs.keys()


    def dbfilecontent(self, filename):
        return self.project.dbs.get(filename, '').strip()

    # /DB FUNCTIONS #####################################

    # GENERAL FUNCTIONS #################################

    def select_method(self, *args):
        self.set_outputfilename()
        self.settings_setdirty()


    def onchange_use_emln(self, dirty=True, *args):
        if not self.use_emln.get():
            self.emln_label.grid_forget()
            self.emln_container.grid_forget()
        else:
            self.emln_label.grid(row=self.emlncontainerrow, column=0, sticky="NE")
            self.emln_container.grid(row=self.emlncontainerrow, column=1, sticky="NWES")
        if dirty:
            self.settings_setdirty()


    def onchange_cw(self, *args):
        if self.closed_world.get():
            self.entry_cw.configure(state=DISABLED)
        else:
            self.entry_cw.configure(state=NORMAL)
        self.settings_setdirty()


    def reset_gui(self):
        self.set_config({})
        self.db_container.clear()
        self.emln_container.clear()
        self.mln_container.clear()


    def set_config(self, newconf):
        self.config = newconf
        self.selected_grammar.set(ifNone(newconf.get('grammar'), 'PRACGrammar'))
        self.selected_logic.set(ifNone(newconf.get('logic'), 'FirstOrderLogic'))
        self.mln_container.selected_file.set(ifNone(newconf.get('mln'), ''))
        if self.use_emln.get():
            self.emln_container.selected_file.set(ifNone(newconf.get('mln'), ''))
        self.db_container.selected_file.set(ifNone(newconf.get('db'), ""))
        self.selected_method.set(ifNone(newconf.get("method"), InferenceMethods.name('MCSAT'), transform=InferenceMethods.name))
        self.multicore.set(ifNone(newconf.get('multicore'), 0))
        self.profile.set(ifNone(newconf.get('profile'), 0))
        self.params.set(ifNone(newconf.get('params'), ''))
        self.use_emln.set(ifNone(newconf.get('use_emln'), 0))
        self.verbose.set(ifNone(newconf.get('verbose'), 1))
        self.ignore_unknown_preds.set(ifNone(newconf.get('ignore_unknown_preds'), 0))
        self.output_filename.set(ifNone(newconf.get('output_filename'), ''))
        self.cwPreds.set(ifNone(newconf.get('cw_preds'), ''))
        self.closed_world.set(ifNone(newconf.get('cw'), 0))
        self.save.set(ifNone(newconf.get('save'), 0))
        self.query.set(ifNone(newconf.get('queries'), ''))
        self.onchange_cw()


    def set_outputfilename(self):
        if not hasattr(self, "output_filename") or not hasattr(self, "db_filename") or not hasattr(self, "mln_filename"):
            return
        mln = self.mln_container.selected_file.get()
        db = self.db_container.selected_file.get()
        if "" in (mln, db):
            return
        if self.selected_method.get():
            method = InferenceMethods.clazz(self.selected_method.get())
            methodid = InferenceMethods.id(method)
            filename = config.query_output_filename(mln, methodid, db)
            self.output_filename.set(filename)


    def update_config(self):

        self.config = PRACMLNConfig()
        self.config["use_emln"] = self.use_emln.get()
        self.config['mln'] = self.mln_container.selected_file.get().strip().lstrip('*')
        self.config['emln'] = self.emln_container.selected_file.get().strip().lstrip('*')
        self.config["db"] = self.db_container.selected_file.get().strip().lstrip('*')
        self.config["method"] = InferenceMethods.id(self.selected_method.get().strip())
        self.config["params"] = self.params.get().strip()
        self.config["queries"] = self.query.get()
        self.config["output_filename"] = self.output_filename.get().strip()
        self.config["cw"] = self.closed_world.get()
        self.config["cw_preds"] = self.cwPreds.get()
        self.config['profile'] = self.profile.get()
        self.config['logic'] = self.selected_logic.get()
        self.config['grammar'] = self.selected_grammar.get()
        self.config['multicore'] = self.multicore.get()
        self.config['save'] = self.save.get()
        self.config['ignore_unknown_preds'] = self.ignore_unknown_preds.get()
        self.config['verbose'] = self.verbose.get()
        self.config['window_loc'] = self.master.winfo_geometry()
        self.config['dir'] = self.dir
        self.project.queryconf = PRACMLNConfig()
        self.project.queryconf.update(self.config.config.copy())


    def write_gconfig(self, savegeometry=True):
        self.gconf['prev_query_path'] = self.dir
        self.gconf['prev_query_project': self.dir] = self.project.name

        # save geometry
        if savegeometry:
            self.gconf['window_loc_query'] = self.master.geometry()
        self.gconf.dump()


    def infer(self, savegeometry=True, options={}, *args):
        mln_content = self.mln_container.editor.get("1.0", END).encode('utf8').strip()
        db_content = self.db_container.editor.get("1.0", END).encode('utf8').strip()

        # create conf from current gui settings
        self.update_config()

        # write gui settings
        self.write_gconfig(savegeometry=savegeometry)

        # hide gui
        self.master.withdraw()

        try:
            print headline('PRACMLN QUERY TOOL')
            print

            if options.get('mlnarg') is not None:
                mlnobj = MLN(mlnfile=os.path.abspath(options.get('mlnarg')),
                             logic=self.config.get('logic', 'FirstOrderLogic'),
                             grammar=self.config.get('grammar', 'PRACGrammar'))
            else:
                mlnobj = parse_mln(mln_content, searchpaths=[self.dir],
                                   projectpath=os.path.join(self.dir, self.project.name),
                                   logic=self.config.get('logic', 'FirstOrderLogic'),
                                   grammar=self.config.get('grammar', 'PRACGrammar'))

            if options.get('emlnarg') is not None:
                emln_content = mlnpath(options.get('emlnarg')).content
            else:
                emln_content = self.emln_container.editor.get("1.0", END).encode('utf8').strip()

            if options.get('dbarg') is not None:
                dbobj = Database.load(mlnobj, dbfiles=[options.get('dbarg')], ignore_unknown_preds=self.config.get('ignore_unknown_preds', True))
            else:
                out(self.config.get('ignore_unknown_preds', True))
                dbobj = parse_db(mlnobj, db_content, ignore_unknown_preds=self.config.get('ignore_unknown_preds', True))

            if options.get('queryarg') is not None:
                self.config["queries"] = options.get('queryarg')

            infer = MLNQuery(config=self.config, mln=mlnobj, db=dbobj, emln=emln_content)
            result = infer.run()


            # write to file if run from commandline, otherwise save result to project results
            if options.get('outputfile') is not None:
                output = StringIO.StringIO()
                result.write(output)
                with open(os.path.abspath(options.get('outputfile')), 'w') as f:
                    f.write(output.getvalue())
                logger.info('saved result to {}'.format(os.path.abspath(options.get('outputfile'))))
            elif self.save.get():
                output = StringIO.StringIO()
                result.write(output)
                fname = self.output_filename.get()
                self.project.add_result(fname, output.getvalue())
                self.project.save(dirpath=self.dir)
                logger.info('saved result to file results/{} in project {}'.format(fname, self.project.name))
            else:
                logger.debug('No output file given - results have not been saved.')
        except:
            traceback.print_exc()

        # restore main window
        sys.stdout.flush()
        self.master.deiconify()