Ejemplo n.º 1
0
    def parse_XML_channel(file_path, name, mole_object):
        xml = parse(file_path)
        pool = ['Tunnel', 'Pore', 'Path']

        for element in pool:
            i = 1

            for tunnel in xml.getElementsByTagName(element):

                if mole_object.plugin_type == "PyMOL":
                    model = Indexed()
                    individual_model = None

                else:
                    model = Molecule()
                    individual_model = model.newResidue(
                        "Tunnel_" + str(i), " ", 1, " ")

                for node in tunnel.getElementsByTagName('Node'):

                    nodes = [
                        float(node.getAttribute('X')),
                        float(node.getAttribute('Y')),
                        float(node.getAttribute('Z')),
                        float(node.getAttribute('Radius'))
                    ]

                    plugin.append_node(model, nodes, individual_model)

                model = plugin.make_channel(model, i)
                i += 1

        if mole_object.plugin_type == "PyMOL":
            plugin.center()
    def open_channels(self):
        file_path = tkFileDialog.askopenfilenames(
            title='Select MOLE tunnel files',
            filetypes=[('MOLE tunnels', '.xml .pdb .py')])

        if self.plugin_type == "PyMOL":
            file_path = self.fix_list(file_path)

        for chan_file in file_path:

            chan_file = os.path.normcase(chan_file)
            extension = os.path.splitext(chan_file)[1].lower()
            name = os.path.basename(chan_file).split('.')[0].lower()

            if len(extension) < 3:
                return

            try:
                if extension == '.py':
                    plugin.run(chan_file)
                if extension == '.xml':
                    Manager.Manager().parse_XML_channel(chan_file, name, self)
                if extension == '.pdb':
                    plugin().parse_PDB_channel(chan_file, name)

            except Exception, e:
                print(e)
    def group_objects(self, script_path, script_name, structure):
        """

        :param script_path:
        :param script_name:
        :param structure:
        :return:
        """
        if os.path.exists(script_path):

            previous = plugin.return_object_list()
            imp.load_source(structure + str(datetime.now().toordinal()),
                            script_path)

            for o in plugin.return_object_list():

                if o not in previous:
                    plugin.return_group(script_name, o)
    def set_structures(self, listbox):
        """
        Fill input structures listbox
        :param listbox:
        :return:
        """
        listbox.clear()
        listbox.insert('end', 'all')

        for item in plugin.return_object_list():
            listbox.insert('end', item)
    def when_computation_done(self, out, param):
        """
        After computation of tunnels is done, run tunnel script
        :param out:
        :return:
        """
        tkMessageBox.showinfo('Computation is done', out)
        self.set_state('normal')

        if self.plugin_type == "Chimera":
            self.profile_wd = os.path.realpath(
                os.path.normcase(self.main_parameters[1] + "/chimera/"))

        tunnels_script = os.path.join(self.profile_wd, 'complex.py')
        paths_script = os.path.join(self.wd, 'paths.py')
        pores_script = os.path.join(self.wd, 'pores.py')
        autopores_script = os.path.join(self.wd, 'autopores.py')
        dom = parse(os.path.join(self.xml_wd, 'tunnels.xml'))

        for e in dom.getElementsByTagName('Exception'):
            tkMessageBox.showinfo('Exception', e.getAttribute('Text'))

        if self.plugin_type == "PyMOL":

            if param == "pores":
                self.group_objects(tunnels_script, 'Pores', "MOLE_tunnels")
            else:
                self.group_objects(tunnels_script, 'Tunnels', "MOLE_pores")

            self.group_objects(paths_script, 'Paths', 'MOLE_Paths')
            self.group_objects(pores_script, 'Pores', 'MOLE_Pores')
            self.group_objects(autopores_script, 'AutoPores', 'MOLE_AutoPores')
            plugin().show("cgo", "Interior*")
            plugin().set_view(self.original_view)

        else:
            plugin.run(tunnels_script)

        self.set_state('normal')
Ejemplo n.º 6
0
    def construct_params_and_run(self, mole_object, param):
        """
        Generates params.xml file
        :param mole_object:
        :param param:
        :return:
        """
        mole_object.set_state('disabled')

        if mole_object.plugin_type == "PyMOL":
            mole_object.original_view = plugin.get_view()

        tunnelParameters = {}
        cavityParameters = {}

        for i in mole_object.params:
            tunnelParameters[i['label_text'].replace(' ', '')] = i.get()

        cavityParameters["InteriorThreshold"] = tunnelParameters[
            "InteriorThreshold"]
        cavityParameters["ProbeRadius"] = tunnelParameters["ProbeRadius"]

        del tunnelParameters["ProbeRadius"]
        del tunnelParameters["InteriorThreshold"]

        tunnelParameters['BottleneckTolerance'] = tunnelParameters.pop(
            'BottleneckLength')
        tunnelParameters['MaxTunnelSimilarity'] = tunnelParameters.pop(
            'CutoffRatio')

        if len(plugin.return_object_list()) == 0:
            mole_object.when_error('', 'No structure loaded!')

        if not os.path.exists(mole_object.main_parameters[0]):
            mole_object.when_error('',
                                   'Your MOLE 2.5 executable was not found!')
            return

        # region create working directory and test permissions
        if not os.path.exists(mole_object.main_parameters[1]):
            mole_object.when_error('', 'No output directory specified.')
            return
        # endregion

        self.wd = os.path.realpath(
            os.path.normcase(mole_object.main_parameters[1]))

        # region create subdirectory
        if not mole_object.overwrite_results.get():
            self.wd = os.path.join(self.wd,
                                   str(datetime.datetime.now().toordinal()))

        if not os.path.exists(self.wd):

            try:
                os.mkdir(self.wd)

            except:
                mole_object.when_error('',
                                       'Output directory cannot be created!')
                return

        used_struct = 'All'
        list_of_structures = []

        doc = Document()
        root = doc.createElement("Tunnels")
        doc.appendChild(root)

        if len(mole_object.input_structure_box.getvalue()) < 1:
            mole_object.when_error('', 'No structure selected')
            return

        elif 'all' in mole_object.input_structure_box.getvalue():

            if mole_object.plugin_type == "PyMOL":

                for i in plugin.return_object_list():
                    list_of_structures.append(i)
            else:
                for i in mole_object.input_structure_box.get(1, 'end'):
                    list_of_structures.append(i)

        else:
            selection = set(mole_object.input_structure_box.getvalue())

            for s in selection:
                if mole_object.plugin_type == "PyMOL":
                    current_structure = plugin.return_object_list(s)

                else:
                    chimera_index = int(
                        mole_object.input_structure_box.index('active')) - 1
                    chimera_index = str("#") + str(chimera_index)
                    current_structure = list(
                        (mole_object.input_structure_box.getvalue()))

                if current_structure is None:
                    mole_object.when_error(
                        '',
                        'The structure you have selected is no longer available in the PyMOL object '
                        'list. Please refresh structures.')
                    return

                else:
                    list_of_structures.append(current_structure[0])

            if len(list_of_structures) == 1:
                used_struct = str(list_of_structures[0])

        for i in list_of_structures:
            used_struct = str(i)

            # region Input
            path = os.path.realpath(os.path.join(self.wd,
                                                 used_struct + '.pdb'))
            e = doc.createElement("Input")

            if len(list_of_structures) == 1:
                if mole_object.plugin_type == "PyMOL":
                    path = os.path.realpath(
                        os.path.join(self.wd, used_struct + '.pdb'))
                    plugin.save(path, list_of_structures[0])

                if mole_object.plugin_type == "Chimera":
                    name = self.wd + "\\" + used_struct + ".pdb"
                    plugin.save(
                        str(
                            mole_object.input_structure_box.index('active') -
                            1), name)

            else:
                ex = ''
                for i in list_of_structures:
                    ex += i + "|"

                ex = string.rstrip(ex, '|')

                if mole_object.plugin_type == "PyMOL":
                    plugin.do("select x,", ex)
                    plugin.save(path, "x")
                    plugin.delete("x")

            e.appendChild(doc.createTextNode(path))
            root.appendChild(e)
            # endregion

            # region WorkingDirectory
            e = doc.createElement("WorkingDirectory")
            e.appendChild(doc.createTextNode(self.wd))
            root.appendChild(e)
            # endregion

            # region Params
            query_str = mole_object.strip_white(mole_object.query_entry.get())
            if mole_object.is_valid and len(
                    mole_object.query_entry.get()) != 0:
                e = doc.createElement("NonActiveParts")
                child = doc.createElement("Query")
                child.appendChild(doc.createTextNode(query_str))
                e.appendChild(child)
                root.appendChild(e)

            e = doc.createElement("Params")
            child = doc.createElement("Cavity")

            for i in cavityParameters.keys():
                child.setAttribute(i, cavityParameters[i])

            if mole_object.ignore_het.get():
                child.setAttribute('IgnoreHETAtoms', '1')

            if mole_object.remove_hydrogens.get():
                child.setAttribute('IgnoreHydrogens', '1')

            e.appendChild(child)

            child = doc.createElement("Tunnel")

            for i in tunnelParameters.keys():
                child.setAttribute(i, tunnelParameters[i])

            child.setAttribute('WeightFunction',
                               mole_object.weight_function.get())
            e.appendChild(child)

            root.appendChild(e)
            # endregion

            # region Export
            e = doc.createElement("Export")
            child = doc.createElement("Formats")
            child.setAttribute('PDBStructure', '0')
            child.setAttribute('PDBProfile', '1')
            child.setAttribute('CSV', '1')

            if mole_object.plugin_type == "PyMOL":
                child.setAttribute('PyMol', '1')

            else:
                child.setAttribute('Chimera', '1')

            child.setAttribute('Mesh', '0')
            child.setAttribute('ChargeSurface', '0')
            e.appendChild(child)

            child = doc.createElement("Types")
            child.setAttribute('Cavities', '0')

            if param == 'pores':
                if len(mole_object.path_starting_points_box.getvalue()
                       ) == 0 and len(
                           mole_object.path_end_points_box.getvalue()) == 0:
                    child.setAttribute('PoresAuto', '1')

                else:
                    child.setAttribute('PoresUser', '1')

            e.appendChild(child)

            child = doc.createElement("PyMol")
            child.setAttribute('SurfaceType', 'Spheres')
            e.appendChild(child)

            #if param == 'pores':
            #e.setAttribute('Tunnels', '0')

            root.appendChild(e)

        if param == 'tunnels':
            e = doc.createElement("Origins")
            mole_object.compute_tunnels_button.config(
                text='Processing... Please wait.')

            if len(mole_object.start_points_box.getvalue()) == 0:
                e.setAttribute('Auto', '1')

            else:
                e.setAttribute('Auto', '0')
                child = doc.createElement("Origin")

            if len(mole_object.start_points_box.getvalue()) == 1:

                for i in mole_object.points.keys():

                    if i in mole_object.start_points_box.getvalue()[0]:
                        self.append_origin(doc, child, mole_object.points[i])
                        e.appendChild(child)

            if len(mole_object.start_points_box.getvalue()) > 1:

                for i in mole_object.points.keys():

                    for j in mole_object.start_points_box.getvalue():

                        if i in j:
                            f = doc.createElement('Origin')
                            self.append_origin(doc, f, mole_object.points[i])
                            e.appendChild(f)

                e.appendChild(child)

            root.appendChild(e)
        # endregion

        # region PathPointsBoxes
        if param == 'pores':

            if len(mole_object.path_starting_points_box.getvalue()) > 0:
                if len(mole_object.path_end_points_box.getvalue()) > 0:
                    e = doc.createElement('CustomExits')

                else:
                    mole_object.when_error(
                        '',
                        'Only one Pore point selected. Please select at least one start pair of points'
                        'or deselect, for automatic pores detection')
                    return

            mole_object.compute_pores_button.config(
                text='Processing... Please wait.')
            start_values = mole_object.path_starting_points_box.getvalue()
            stop_values = mole_object.path_end_points_box.getvalue()

            for i in start_values:  # todo here

                for j in stop_values:

                    start = mole_object.get_element(i)
                    stop = mole_object.get_element(j)

                    if start is not '42' and stop is not '42':
                        f = doc.createElement('Exit')
                        self.append_origin(doc, f, start)
                        e.appendChild(f)
                        g = doc.createElement('Exit')
                        self.append_origin(doc, g, stop)
                        e.appendChild(g)

            root.appendChild(e)

        # endregion
        with open(os.path.join(self.wd, 'params.xml'), 'w') as f:
            doc.writexml(f)

        mole_object.parent.update()
        mole_object.set_state('disabled')
        plat = str.lower(sys.platform)

        if 'win32' not in plat:

            if self.mono_test() is not 1:

                mole_object.when_error(
                    'Error',
                    'Mono environment required for MOLE 2.0 in non-windows environment is not '
                    'installed. Please go to www.mono-project.com and install it.'
                )
                mole_object.rename_buttons(param)
                return

        try:
            t = threading.Thread(target=self.run_sub_process(
                mole_object.main_parameters[0], param))
            t.daemon = True
            t.start()
            t.join()

        except Exception, e:
            mole_object.when_error(
                '',
                'An error occurred during processing. If this problem persists and you are a non-windows '
                'user try installing \'mono-devel\' package. If it does not help, please send the text '
                'below to the authors with the description \n#################\n '
                + str(e))
            mole_object.rename_buttons(param)
            return
Ejemplo n.º 7
0
    def generate_CSA_selections(self, mole_object):
        active_sites = ()
        csa_structure = mole_object.structure_for_CSA.get().lower()

        if mole_object.main_parameters[2] == '':
            mole_object.when_error(
                '', 'Specify CSA.dat file for search of active sites.')
            return

        if csa_structure == '':

            if len(plugin.return_object_list()) == 0:
                mole_object.when_error(
                    '', 'No structure was found in object list.')
                return

            mole_object.when_error('', 'No structure was defined.')
            return

        else:
            if csa_structure not in map(lambda x: x.lower(),
                                        plugin.return_object_list()):
                mole_object.when_error(
                    '', csa_structure + ' was not found in object list.')
                return

        try:
            file = csv.reader(open(mole_object.main_parameters[2], 'r'))
            sites = 0
            s = ''
            listbox_entry = ()
            points_entry = ()
            points_entry += ({'Structure': '', 'Type': 'CSA'}, )

            data = []

            for row in file:
                if row[0] == csa_structure:
                    data.append(row)
                    sites = long(row[1])

            for i in range(sites + 1):

                for row in data:

                    if row[1] == str(i):
                        s += ' (chain ' + row[3] + ' & resi ' + row[
                            4] + ') |'  # (row[3] + '/' + row[2] + ' ' + row[4] + '/',)
                        points_entry += ({
                            'Element': 'Residue',
                            'Name': row[2],
                            'Chain': row[3],
                            'SequenceNumber': row[4]
                        }, )
                        listbox_entry += (row[3] + row[4], )

                if len(s) > 1:
                    y = ''

                    for j in range(len(listbox_entry) - 1):
                        y += listbox_entry[j] + ','

                    y += listbox_entry[len(listbox_entry) - 1] + ','
                    x = csa_structure + ' & (' + s[0:-1] + ')'

                    if mole_object.plugin_type == "PyMOL":
                        plugin.select_structure(csa_structure, y, x)

                    else:
                        chimera_active_site = y.split(',')
                        del chimera_active_site[-1]
                        swapped = []
                        selection_list = []
                        chimera_sel = "#" + str(
                            mole_object.input_structure_box.index('active') -
                            1) + ":"

                        for i in chimera_active_site:
                            swapped.append(i[-1] + i[1:-1] + i[0])

                        for i in range(len(swapped)):
                            selection_list.append(swapped[i][:-1] + "." +
                                                  swapped[i][-1:] + ":")

                        for i in selection_list:
                            chimera_sel += i

                        chimera_sel = chimera_sel[:-1]
                        plugin().select(chimera_sel)
                        plugin().save_selection(x)

                    mole_object.points[csa_structure + '|' +
                                       y[0:-1]] = points_entry
                    active_sites += (y, )
                    s = ''
                    listbox_entry = ()
                    points_entry = ()
                    points_entry += ({'Structure': '', 'Type': 'CSA'}, )

            mole_object.fill_boxes(
                tuple((map(lambda x: csa_structure + '|' + x, active_sites))))
            mole_object.structure_for_CSA.clear()

            if len(active_sites) < 1:
                mole_object.when_error(
                    '',
                    'No active sites found for the \'' + csa_structure + '\'')

        except Exception, e:
            mole_object.when_error(
                '',
                'An error occurred during the processing of CSA file. Did you provide it in a '
                'correct format?')
            print e
            return
    def __init__(self):
        self.plugin_type = PLUGIN

        root = Toplevel()
        root.title('MOLE 2.5')
        root.resizable(0, 0)
        self.parent = root

        # region Create Frame and NoteBook
        self.mainframe = Frame(self.parent, width=463, height=623)
        self.mainframe.pack(fill='both', expand=1)
        self.mainframe.bind(
            '<<WrongExecutable>>', lambda e: self.when_error(
                e, 'Your MOLE 2.0 executable was not found!'))
        root.bind(
            '<F5>',
            (lambda event: self.set_structures(self.input_structure_box)))
        balloon = Pmw.Balloon(self.mainframe)

        self.points = {}
        # Binary file, Working directory, csa file
        self.main_parameters = ['', '', '']

        self.notebook = Pmw.NoteBook(self.mainframe)
        self.notebook.pack(fill='both', expand=1, padx=10, pady=10)
        # endregion

        # region self.mainPage / settings
        self.mainpage = self.notebook.add('Compute Tunnels')
        self.mainpage.focus_set()

        input_structure_group = Pmw.Group(self.mainpage,
                                          tag_text='Specify Input Structure')
        input_structure_group.pack(fill='both')

        starting_point_group = Pmw.Group(self.mainpage,
                                         tag_text='Specify Starting Point')
        starting_point_group.pack(fill='both')

        if self.plugin_type == "PyMOL":
            initialized_structs = ('all', ) + plugin.return_tuple_objects()
        else:
            initialized_structs = ()

        self.input_structure_box = Pmw.ScrolledListBox(
            input_structure_group.interior(),
            items=initialized_structs,
            labelpos='nw',
            listbox_height=4,
            listbox_selectmode=EXTENDED,
        )
        self.input_structure_box.component('listbox').configure(
            exportselection=0, background='white')
        self.input_structure_box.pack(fill='both', expand=0, padx=10, pady=5)
        balloon.bind(
            self.input_structure_box,
            'Select one or more structures in which you want to find channels.'
        )

        if self.plugin_type == "Chimera":
            self.input_structure_box.insert('end', 'all')

            if plugin.return_object_list() is not None:

                for item in plugin.return_object_list():
                    self.input_structure_box.insert('end', item)

        query = Pmw.Group(input_structure_group.interior(),
                          tag_text="Not Active Residues")
        query.pack(fill='both')
        self.query_entry = Entry(query.interior(), width=65)
        self.query_entry.config(background='white')
        self.query_entry.grid(column=0,
                              row=0,
                              padx=10,
                              pady=5,
                              sticky=W + E + N + S)
        self.query_entry.columnconfigure(0, minsize=65)
        self.query_entry.bind(
            "<KeyRelease>",
            lambda event: root.after(2500, self.validate_query))
        self.query_entry.bind('<Control-KeyRelease-a>',
                              lambda event: self.select_all_query_entry())
        self.query_entry.focus_set()

        balloon.bind(self.query_entry, 'Input not active residues here')

        self.query_label = Label(
            query.interior(),
            text=
            'Select atoms/residues not to be included in the calculation using PatternQuery '
            'syntax.',
            width=68)
        self.query_label.grid(column=0,
                              row=1,
                              padx=10,
                              pady=5,
                              sticky=W + E + N + S,
                              columnspan=2)
        self.query_help = Label(query.interior(),
                                text='?',
                                fg="blue",
                                cursor="hand2")
        self.query_help.grid(column=1, row=0, padx=[0, 10], pady=5)
        self.query_help.bind(
            "<Button-1>", lambda event: webbrowser.open_new(
                "https://webchem.ncbr.muni.cz/Wiki"
                "/PatternQuery:UserManual"))
        balloon.bind(self.query_help, 'PatternQuery Wiki pages.')
        self.is_valid = False

        self.start_points_box = Pmw.ScrolledListBox(
            starting_point_group.interior(),
            items=(),
            labelpos='nw',
            listbox_height=4,
            listbox_selectmode=EXTENDED)
        self.start_points_box.component('listbox').configure(
            exportselection=0, background='white')
        self.start_points_box.pack(fill='both', expand=0, padx=10, pady=5)
        balloon.bind(
            self.start_points_box,
            'Starting point list. If no starting point is specified, \nMOLE plugin will try to find suitable '
            'starting points automatically.\nOtherwise all selected points will be used.'
        )

        self.button_box1 = Pmw.ButtonBox(starting_point_group.interior())
        self.button_box1.pack(fill='both', expand=0, padx=10, pady=5)
        self.button_box1.add(
            'AddStartingPoint',
            text='Add Starting Point',
            command=lambda: self.add_point(self.start_points_box))
        self.button_box1.add(
            'RemoveStartingPoint',
            text='Remove Starting Point',
            command=lambda: self.remove_point(self.start_points_box))
        self.button_box1.add(
            'RefreshStructures',
            text='Refresh Structures',
            command=lambda: self.set_structures(self.input_structure_box))
        self.button_box1.alignbuttons()

        property_group = Pmw.Group(self.mainpage, tag_pyclass=None)
        property_group.pack(fill='both')

        self.overwrite_results = BooleanVar()
        self.overwrite_results.set(True)
        self.overwrite_results_button = Checkbutton(
            property_group.interior(),
            text="Overwrite results",
            variable=self.overwrite_results,
            onvalue=True,
            offvalue=False)
        self.overwrite_results_button.grid(column=0,
                                           row=0,
                                           padx=10,
                                           pady=5,
                                           sticky=W + E + N + S)
        balloon.bind(
            self.overwrite_results_button,
            'If checked MOLE will overwrite old files in output folder. Otherwise, new folder will be '
            'created in output folder.')

        self.remove_hydrogens = BooleanVar()
        self.remove_hydrogens_button = Checkbutton(
            property_group.interior(),
            text="Remove hydrogens",
            variable=self.remove_hydrogens,
            onvalue=True,
            offvalue=False)
        self.remove_hydrogens_button.grid(column=1,
                                          row=0,
                                          padx=10,
                                          pady=5,
                                          sticky=W + E + N + S)
        balloon.bind(
            self.remove_hydrogens_button,
            'If checked MOLE will remove all hydrogens from the structure prior to the calculation.'
        )

        self.ignore_het = BooleanVar()
        self.ignore_het_button = Checkbutton(property_group.interior(),
                                             text="Ignore HETeroatoms",
                                             variable=self.ignore_het,
                                             onvalue=True,
                                             offvalue=False)
        self.ignore_het_button.grid(column=2,
                                    row=0,
                                    padx=10,
                                    pady=5,
                                    sticky=W + E + N + S)
        balloon.bind(
            self.ignore_het_button,
            'If checked MOLE will exclude all HETATM entries prior to the calculation.'
        )

        self.select_working_directory_button = Button(
            property_group.interior(),
            text='Save output to:',
            command=self.select_working_directory)
        self.select_working_directory_button.grid(row=1,
                                                  column=0,
                                                  sticky=W + E + N + S,
                                                  padx=10,
                                                  pady=5)
        self.select_working_directory_button.columnconfigure(0, weight=1)
        balloon.bind(self.select_working_directory_button,
                     'Where do you wish to save output from MOLE 2.0 plugin.')

        self.working_directory = Pmw.EntryField(property_group.interior(),
                                                labelpos='w')
        self.working_directory.component('entry').configure(background='white')
        self.working_directory.grid(row=1,
                                    column=1,
                                    columnspan=2,
                                    sticky=W + E + N + S,
                                    padx=10,
                                    pady=5)
        balloon.bind(self.working_directory,
                     'Where do you wish to save output from MOLE 2.0 plugin.')

        self.generate_csa_selections_button = Button(
            property_group.interior(),
            text='Generate CSA sites:',
            command=self.CSA_button_click)
        self.generate_csa_selections_button.grid(column=0,
                                                 row=2,
                                                 sticky=W + E + N + S,
                                                 padx=10,
                                                 pady=5)
        balloon.bind(
            self.generate_csa_selections_button,
            'Specify structure by writing its PDB ID and press Generate button.'
        )
        self.structure_for_CSA = Pmw.EntryField(property_group.interior(),
                                                labelpos='w')
        self.structure_for_CSA.component('entry').configure(background='white')
        self.structure_for_CSA.component('entry').bind(
            '<Return>', lambda event: self.CSA_button_click())
        self.structure_for_CSA.grid(column=1,
                                    row=2,
                                    columnspan=2,
                                    sticky=W + E + N + S,
                                    padx=10,
                                    pady=5)
        balloon.bind(
            self.structure_for_CSA,
            'Specify structure by writing its PDB ID and press Generate button.'
        )

        self.select_CSA_button = Button(property_group.interior(),
                                        text='Select CSA file:',
                                        command=self.select_CSA)
        self.select_CSA_button.grid(column=0,
                                    row=3,
                                    sticky=W + E + N + S,
                                    padx=10,
                                    pady=5)
        balloon.bind(
            self.select_CSA_button,
            'Insert location of CSA.dat file containing CSA database for suggesting active sites as a '
            'starting points.')

        self.CSA = Pmw.EntryField(property_group.interior(), labelpos='w')
        self.CSA.component('entry').configure(background='white')
        self.CSA.grid(column=1,
                      columnspan=2,
                      row=3,
                      sticky=W + E + N + S,
                      padx=10,
                      pady=5)
        balloon.bind(
            self.CSA,
            'Insert location of CSA.dat file containing CSA database for suggesting active sites as a '
            'starting points.')

        self.select_executable_button = Button(property_group.interior(),
                                               text='MOLE 2.5 location:',
                                               command=self.select_executable)
        self.select_executable_button.grid(column=0,
                                           row=4,
                                           sticky=W + E + N + S,
                                           padx=10,
                                           pady=5)
        balloon.bind(
            self.select_executable_button,
            'Select proper path to the MOLE 2.0 command line location')

        self.executable = Pmw.EntryField(property_group.interior(),
                                         labelpos='w')
        self.executable.component('entry').configure(background='white')
        self.executable.grid(column=1,
                             columnspan=2,
                             row=4,
                             sticky=W + E + N + S,
                             padx=10,
                             pady=5)
        balloon.bind(
            self.executable,
            'Select proper path to the MOLE 2.5 command line location.')

        self.compute_tunnels_button = Button(
            self.mainpage,
            text='Compute Tunnels',
            font=("Helvetica", 12, "bold"),
            command=lambda b='tunnels': Manager.Manager(
            ).construct_params_and_run(self, b))
        self.compute_tunnels_button.pack(side=BOTTOM,
                                         fill='both',
                                         expand=0,
                                         padx=10,
                                         pady=5)

        # endregion

        # region self.paramsPage / params
        self.params_page = self.notebook.add('Settings')
        cavity_parameters_group = Pmw.Group(self.params_page,
                                            tag_text='Cavity Parameters')
        cavity_parameters_group.pack(fill='both', expand=4)

        self.probe_radius = Pmw.Counter(cavity_parameters_group.interior(),
                                        labelpos='w',
                                        label_text='Probe Radius',
                                        entryfield_value='3',
                                        increment=0.1,
                                        entryfield_validate={
                                            'validator': 'real',
                                            'separator': '.',
                                            'min': 1.4,
                                            'max': 45
                                        },
                                        datatype={
                                            'counter': 'real',
                                            'separator': '.'
                                        })
        self.probe_radius.component('entry').configure(background='white')
        balloon.bind(self.probe_radius,
                     'Radius used for construction of molecular surface.')

        self.interior_threshold = Pmw.Counter(
            cavity_parameters_group.interior(),
            labelpos='w',
            label_text='Interior Threshold',
            entryfield_value='1.25',
            increment=0.1,
            entryfield_validate={
                'validator': 'real',
                'separator': '.',
                'min': 0.8,
                'max': 45.0
            },
            datatype={
                'counter': 'real',
                'separator': '.'
            })
        self.interior_threshold.component('entry').configure(
            background='white')
        balloon.bind(self.interior_threshold,
                     'Lower bound of the tunnel radius.')

        self.surface_cover_radius = Pmw.Counter(
            cavity_parameters_group.interior(),
            labelpos='w',
            label_text='Surface Cover Radius',
            entryfield_value='10',
            increment=0.1,
            entryfield_validate={
                'validator': 'real',
                'separator': '.',
                'min': 5.0,
                'max': 25.0
            },
            datatype={
                'counter': 'real',
                'separator': '.'
            })
        self.surface_cover_radius.component('entry').configure(
            background='white')
        balloon.bind(
            self.surface_cover_radius,
            'Determines the density of tunnel exits on the molecular surface.')

        self.origin_radius = Pmw.Counter(cavity_parameters_group.interior(),
                                         labelpos='w',
                                         label_text='Origin Radius',
                                         entryfield_value='5',
                                         increment=0.1,
                                         entryfield_validate={
                                             'validator': 'real',
                                             'separator': '.',
                                             'min': 0.1,
                                             'max': 10.0
                                         },
                                         datatype={
                                             'counter': 'real',
                                             'separator': '.'
                                         })
        self.origin_radius.component('entry').configure(background='white')
        balloon.bind(
            self.origin_radius,
            'Better starting points are localized within the defined radius from the original starting point.'
        )

        filter_settings = Pmw.Group(self.params_page,
                                    tag_text='Tunnel Parameters')
        filter_settings.pack(fill='both', expand=4)
        self.bottleneck_radius = Pmw.Counter(filter_settings.interior(),
                                             labelpos='w',
                                             label_text='Bottleneck Radius',
                                             entryfield_value='1.25',
                                             increment=0.1,
                                             entryfield_validate={
                                                 'validator': 'real',
                                                 'separator': '.',
                                                 'min': 0.1,
                                                 'max': 6.0
                                             },
                                             datatype={
                                                 'counter': 'real',
                                                 'separator': '.'
                                             })
        self.bottleneck_radius.component('entry').configure(background='white')
        balloon.bind(self.bottleneck_radius, 'The minimum radius of a tunnel.')

        self.bottleneck_length = Pmw.Counter(filter_settings.interior(),
                                             labelpos='w',
                                             label_text='Bottleneck Length',
                                             entryfield_value='3',
                                             increment=0.1,
                                             entryfield_validate={
                                                 'validator': 'real',
                                                 'separator': '.',
                                                 'min': 0.0,
                                                 'max': 20.0
                                             },
                                             datatype={
                                                 'counter': 'real',
                                                 'separator': '.'
                                             })
        self.bottleneck_length.component('entry').configure(background='white')
        balloon.bind(
            self.bottleneck_length,
            'Length of a possible profile narrower than the Bottleneck Radius')

        self.cutoff_ratio = Pmw.Counter(filter_settings.interior(),
                                        labelpos='w',
                                        label_text='Cutoff Ratio',
                                        entryfield_value='0.7',
                                        increment=0.05,
                                        entryfield_validate={
                                            'validator': 'real',
                                            'separator': '.',
                                            'min': 0.0,
                                            'max': 1.0
                                        },
                                        datatype={
                                            'counter': 'real',
                                            'separator': '.'
                                        })
        self.cutoff_ratio.component('entry').configure(background='white')
        balloon.bind(
            self.cutoff_ratio,
            'Determines maximum similarity of tunnels centerline. \nIf two tunnels are more similar than the '
            'threshold, the longer is discarded.')

        # region load executable location from settingsfile

        temp_path = os.path.normcase(
            str(os.environ['TEMP']) if 'win32' ==
            str.lower(sys.platform) else '/tmp/')

        if os.path.exists(CONFIGFILE):

            try:
                with open(CONFIGFILE, 'r') as f:
                    self.main_parameters = list(
                        map(lambda x: os.path.normcase(x), pickle.load(f)))
                    self.executable.setvalue(self.main_parameters[0])
                    self.working_directory.setvalue(self.main_parameters[1])
                    self.CSA.setvalue(self.main_parameters[2])

            except:
                self.executable.setvalue('')
                self.working_directory.setvalue(temp_path)
                self.CSA.setvalue('')

        else:
            self.working_directory.setvalue(temp_path)
            self.main_parameters[1] = temp_path
            with open(CONFIGFILE, 'w') as f:
                pickle.dump(self.main_parameters, f)
        # endregion

        self.params = (self.probe_radius, self.interior_threshold,
                       self.surface_cover_radius, self.origin_radius,
                       self.bottleneck_radius, self.bottleneck_length,
                       self.cutoff_ratio)
        Pmw.alignlabels(self.params)

        for counter in self.params:
            counter.pack(fill='both', expand=1, padx=10, pady=5)

        weight_function_group = Pmw.Group(self.params_page,
                                          tag_text='Weight Function')
        weight_function_group.pack(fill='both', expand=0)

        self.weight_function = StringVar()

        self.voronoi_button = Radiobutton(weight_function_group.interior(),
                                          text='Voronoi Scale',
                                          variable=self.weight_function,
                                          value="VoronoiScale")
        self.voronoi_button.grid(column=0,
                                 row=0,
                                 padx=30,
                                 pady=5,
                                 sticky=W + E + N + S)
        balloon.bind(
            self.voronoi_button,
            'Recommended for identification of tunnels leading to the buried active sites'
        )

        self.length_radius_button = Radiobutton(
            weight_function_group.interior(),
            text='Length + Radius',
            variable=self.weight_function,
            value="LengthAndRadius")
        self.length_radius_button.grid(column=1,
                                       row=0,
                                       padx=30,
                                       pady=5,
                                       sticky=W + E + N + S)
        balloon.bind(self.length_radius_button,
                     'Old and universal MOLE 2.0 weight function')

        self.length_button = Radiobutton(weight_function_group.interior(),
                                         text='Length',
                                         variable=self.weight_function,
                                         value="Length")
        self.length_button.grid(column=2,
                                row=0,
                                padx=30,
                                pady=5,
                                sticky=W + E + N + S)
        balloon.bind(self.length_button,
                     'Recommended for identification of transmembrane pores')

        self.voronoi_button.invoke()

        # endregion

        # region self.pathPage / settings
        self.path_page = self.notebook.add('Compute Pores')

        input_structure_group = Pmw.Group(
            self.path_page, tag_text='Specify pores starting points')
        input_structure_group.pack(fill='both')

        self.path_starting_points_box = Pmw.ScrolledListBox(
            input_structure_group.interior(),
            items=(),
            labelpos='nw',
            label_text='Starting Points',
            listbox_height=4,
            listbox_selectmode=EXTENDED)
        self.path_starting_points_box.component('listbox').configure(
            exportselection=0, background='white')
        self.path_starting_points_box.pack(fill='both',
                                           expand=0,
                                           padx=10,
                                           pady=5)
        self.path_starting_points_box.bind(
            '<Delete>',
            lambda event: self.remove_point(self.path_starting_points_box))
        balloon.bind(
            self.path_starting_points_box,
            'Starting point list. Every starting point must have coresponding end point.'
        )

        self.button_box2 = Pmw.ButtonBox(input_structure_group.interior())
        self.button_box2.pack(fill='both', expand=0, padx=10, pady=5)
        self.button_box2.add(
            'AddStartingPoint',
            text='Add Starting Points',
            command=lambda: self.add_point(self.path_starting_points_box))
        self.button_box2.add(
            'RemoveStartingPoint',
            text='Remove Starting Points',
            command=lambda: self.remove_point(self.path_starting_points_box))
        self.button_box2.alignbuttons()

        input_structure_group = Pmw.Group(self.path_page,
                                          tag_text='Specify pores end points')
        input_structure_group.pack(fill='both')

        self.path_end_points_box = Pmw.ScrolledListBox(
            input_structure_group.interior(),
            items=(),
            labelpos='nw',
            label_text='End Points',
            listbox_height=4,
            listbox_selectmode=EXTENDED)
        self.path_end_points_box.component('listbox').configure(
            exportselection=0, background='white')
        self.path_end_points_box.bind(
            '<Delete>',
            lambda event: self.remove_point(self.path_end_points_box))
        self.path_end_points_box.pack(fill='both', expand=0, padx=10, pady=5)
        balloon.bind(
            self.path_end_points_box,
            'End points list. Every end point must have coresponding starting point.'
        )

        self.button_box3 = Pmw.ButtonBox(input_structure_group.interior())
        self.button_box3.pack(fill='both', expand=0, padx=10, pady=5)
        self.button_box3.add(
            'AddEndPoint',
            text='Add End Points',
            command=lambda: self.add_point(self.path_end_points_box))
        self.button_box3.add(
            'RemoveEndPoint',
            text='Remove end points',
            command=lambda: self.remove_point(self.path_end_points_box))
        self.button_box3.alignbuttons()

        self.compute_pores_button = Button(
            self.path_page,
            text='Compute Pores',
            font=("Helvetica", 12, "bold"),
            command=lambda b='pores': Manager.Manager(
            ).construct_params_and_run(self, b))
        self.compute_pores_button.pack(fill='both', expand=0, padx=10, pady=5)
        # endregion

        # prev set

        # region READ
        self.read_page = self.notebook.add('Read Channels')
        read_group = Pmw.Group(
            self.read_page,
            tag_text='Select a file with previously computed MOLE tunnels/pores'
        )
        read_group.pack(fill='both')
        self.open_channels_button = Button(read_group.interior(),
                                           text='Open computation results',
                                           command=self.open_channels,
                                           font=("Helvetica", 12, "bold"))
        self.open_channels_button.pack(fill='both', expand=0, padx=10, pady=5)

        # endregion

        # region QuickStartGuide

        self.guide_page = self.notebook.add('Quick Guide')

        guide = Text(self.guide_page, width=72, wrap=WORD)
        guide.config(padx=5, pady=8)
        guide.tag_configure('big', font=('Arial', 12, 'bold'))
        guide.tag_configure('plain_text', font=('Arial', 10))
        guide.tag_configure('smaller', font=('Arial', 9))

        guide.insert(END, 'Plugin description:\n\n', 'big')
        plugin_description = (
            "The plugin is separated into several tabs The crucial for the calculation are: "
            "Compute Tunnels, Settings, and Compute Pores. At first, specify location of output "
            "folder and MOLE 2.5 command line executable. Afterwards, select a structure in the "
            "'input structure listbox' and starting point from the 'starting point listbox'. "
            "Additionally, if you provide a path to the CSA database [1], the plugin will suggest "
            "you the potential starting points.\n\n")
        guide.insert(END, plugin_description, 'plain_text')

        guide.insert(END, "Run:\n\n", 'big')
        run_description = (
            "After selecting one or more structures and one or more starting points by clicking 'Add Starting Point'. Additional "
            "search parameters can be adjusted in the Settings tabs. For further info on how to use this "
            "please refer the included manual or visit our webpages. Whenever you would feel lost just "
            "hover your cursor above any element in order to get tooltip. For more info and news about the "
            "MOLE 2.5 visit our webpages.\n")

        guide.insert(END, run_description, 'plain_text')

        improve_text = (
            "\n"
            "Also if you would like to make a suggestion on how to "
            "improve MOLE or send a bug report, please contact authors at [email protected] "
            "or the author of this extension directly - [email protected]\n\n"
        )

        guide.insert(END, improve_text, 'plain_text')
        guide.insert(END, "Happy tunneling!    ", 'big')
        team_text = (
            "Mole development team. http://mole.chemi.muni.cz\n\n"
            "[1] Furnham,N., Holliday,G.L., De Beer,T.A.P., Jacobsen,J.O.B., Pearson,W.R. and Thornton,J.M. (2014) "
            "The Catalytic Site Atlas 2.0: Cataloging catalytic sites and residues identified in enzymes. Nucleic "
            "Acids Res., 42, 1–5.")
        guide.insert(END, team_text, 'smaller')
        guide.config(state=DISABLED)

        guide.pack(side=LEFT, fill='both')

        # endregion

        # region AuthorsPage
        self.authors_page = self.notebook.add('Authors')
        authors_text_widget = Text(self.authors_page, width=72, height=17)
        authors_text_widget.config(padx=5, bg='#52A300', pady=8)
        authors_text_widget.tag_configure('plain_text',
                                          font=('Arial', 10),
                                          foreground='white')
        authors_text_widget.insert(
            END,
            "If you find this tool useful for your work please cite it as:\n\n",
            'plain_text')
        cite_text = (
            "Sehnal D, Svobodova Varekova R, Berka K, Pravda L, Navratilova V,\nBanas P, Ionescu C-M, Otyepka M, "
            "Koca J. MOLE2.0: advanced approach for analysis of biomacromolecular channels. Journal of "
            "Cheminformatics 2013, 5:39., doi:10.1186/1758-2946-5-39.\n\n"
            "If you were using the web server, which is available at http://mole.upol.cz/ please cite it as:\n\n"
            "Berka K, Hanak O, Sehnal D, Banas P, Navratilova V, Jaiswal D,Ionescu C-M, Svobodova Varekova R, "
            "Koca J, Otyepka M.\nMOLEonline 2.0: interactive web-based analysis of biomacromolecular\nchannels. Nucleic "
            "acids research 2012, 40:W222?7., doi:10.1093/nar/gks363")

        authors_text_widget.insert(END, cite_text, 'plain_text')
        authors_text_widget.config(state=DISABLED)
        authors_text_widget.pack(side=LEFT, fill='both')

        # endregion

        Label(
            self.mainframe,
            relief='sunken',
            anchor=W,
            justify=LEFT,
            bg='#52A300',
            fg='white',
            font=("Helvetica", 12),
            padx=10,
            pady=10,
            text=
            "(c) 2017 CEITEC & NCBR MU & FCH UPOL\nhttp://mole.chemi.muni.cz                                v. "
            "2.5.17.7.11").pack(fill='both')

        self.notebook.setnaturalsize()
        self.wd = os.path.realpath(os.path.normcase(self.main_parameters[1]))
        self.xml_wd = os.path.realpath(
            os.path.normcase(self.main_parameters[1] + "/xml/"))
        self.profile_wd = os.path.realpath(
            os.path.normcase(self.main_parameters[1] + "/pymol/"))
        os.system('xset r off')  # for keypress

        self.original_view = None