Ejemplo n.º 1
0
    def get_args(self, input_function: t.Callable[[str], t.Any]):
        """should be overridden by every subclass of Exporter. It will assign all necessary varaibles using input_function

        For Gromos_Exporter: out_path

        Parameters
        ----------
        input_function:  t.Callable[[str],t.Any]
            a function that will provide the arguments for the selection in the necessary format.

        Returns
        -------
        NoReturn

        Raises
        ------
         u.BadArgumentException
        """

        # Error checking can only be done when we try to acess the file
        self.out_path = u.check_or_convert_argument(
            input_function('Name of the output File:'), str)
        if self.out_path == '' or self.out_path == 'None':
            raise u.BadArgumentException(
                "Empty filename. (Unless you actually wanted to call your file None. \n"
                "In which case you have to blame Python's promiscuous type conversion.  And yourself, for not using file extensions.)"
            )
        self.out_path = ".".join(self.out_path.split(".")[:-1]) if (len(
            ".".join(self.out_path.split(".")[:-1])) > 0) else self.out_path
Ejemplo n.º 2
0
    def get_args(self, input_function: t.Callable):
        """
            should be overridden by every subclass of _Selection. It will assign all necessart variables using input function.
            For MCS_Selection the argument is a list of the Molecules in the pdb format.

        Parameters
        ----------
        input_function : t.Callable (str)
            a function that will provide the arguments for the selection in the necessary format. Here: Not necessesary. Just pass an 'empty' function or any function at all. It will not be called.

        Returns
        -------
        NoReturn

        Raises
        ------
        BadArgumentException:
            if the input function does not provide all arguments in the necessary format

        """

        input = input_function("A List of Molecules in the PDB FORMAT:")
        input = u.check_or_convert_argument(input, list)
        molecules_pdb = [u.check_or_convert_argument(i, str) for i in input]
        self.molecules_rdk = Rdkit_Functions.parse_pdb_blocks_to_rdkit(
            molecules_pdb)

        self.update()
Ejemplo n.º 3
0
    def get_args(self, input_function: t.Callable):
        """
            get_args(...) Needs to be called, before filter() can be used. It uses an input function to find all arguments required by a certain instance of a _Filter.

            For RingFilter that is a List of all Molecules in the pdb format (CAREFULL: The Molecules need to contain ALL atoms in the Molecules, not just the selected one.)

            TODO: What Kind of Error will I get if tools_Rdkit conversion fails?/ Catch it here

        Parameters
        ----------
        input_function: function(str)
            A function that can get the input
        message: str
            A string that is displayed if if input function needs to communicate with the user

        Returns
        -------
        NoReturn

        Raises
        ------
        BadArgumentException
            if the input function does not provide all arguments in the necessary format

        """

        input = input_function("A List of Molecules in the PDB FORMAT:")
        input = u.check_or_convert_argument(input, list)
        molecules_pdb = [u.check_or_convert_argument(i, str) for i in input]
        self.molecules_rdk = Rdkit_Functions.parse_pdb_blocks_to_rdkit(
            molecules_pdb)
Ejemplo n.º 4
0
    def get_args(self, input_function: t.Callable):
        '''
         get_args(...) should be overridden by every subclass of Exporter. It will assign all necessary varaibles using input_function

         For Gromos_Importer: in_path

         :param input_function: a function that will provide the arguments for the selection in the necessary format.
         :type input_function: t.Callable[[str],t.Any]
         :return: -
         :rtype: None
         :raises BadArgument Excpetion if the input function does not deliver the arguments as needed
        :raises NotImplementedError if _Importer.get_args is called directly

        '''

        input = input_function(
            'Which file should the restrants be read from? ')
        self.in_path = u.check_or_convert_argument(input, str)
        if self.in_path == '' or self.in_path == 'None':
            raise u.BadArgumentException(
                "Empty filename. (Unless you actually wanted to call your file 'None'. \n"
                "In which case you have to blame Python's promiscuous type conversion.  And yourself, for not using file extensions.)"
            )
        if (not os.path.isfile(self.in_path)):
            raise IOError("Could not find File in import path: " +
                          str(self.in_path))
Ejemplo n.º 5
0
    def import_restraints(self, verbose: bool = False) -> t.List[dict]:
        """
        This function reads in a gromos distance restraint file. TODO: Read
            in additional Settings (r0, w0, etc...)

        TODO: WE could try to read thefile in get_args to get the Error there already.
         IDEA: READ THE WHOLE TEXT IN GET ARGS AND ONLY CONVERT IT HERE. OS ALLERRORS HAPPEN IN GET ARGS

        Parameters
        ----------
        verbose

        Returns
        -------
        t.List[dict]
            returns a dict containing the atom ids for each disres. (has to be
            translated in interface_Pymol


        """

        restraint_objects = [
        ]  # Define before try_block, so we can return the empty list in case of errors
        try:
            # readFiles
            disres_file = Files.Gromos_files.disres(self.in_path)
            if verbose: print(disres_file)
            if verbose: print("READ: " + "".join(disres_file["TITLE"]))

            # Analogous new version
            for restraint in disres_file.distance_res_spec_block.RESTRAINTS:
                if verbose: print(restraint)
                atom1 = u.find_atom_by_property(self.all_atoms,
                                                restraint.atom1i)
                atom2 = u.find_atom_by_property(self.all_atoms,
                                                restraint.atom2i)
                new_restraint = Restraints.DistanceRestraint(atomA=atom1,
                                                             atomB=atom2)
                restraint_objects.append(new_restraint)

            # PRINT RESULTS
            for i_r, r in enumerate(restraint_objects):
                print('PairRestraint', str(i_r), ': Atom1_ID:',
                      str(r.atoms[0].id), 'Atom2_ID:', str(r.atoms[1].id))

        except FileNotFoundError:
            print("Error: Could not find the file: \'" + self.in_path + "\'",
                  mv=4)
        except KeyError:
            print("Error: Could not read the file: " + self.in_path, mv=4)
        except ImportError:
            print(
                "BAD ERROR: FAILED TO IMPORT THE MODULES NECESSARY FOR IMPORTING AND EXPORTING GROMOS FILES!",
                mv=4)

        if (len(restraint_objects) == 0):
            warnings.warn("Could not find any Restraint in file: " +
                          str(self.in_path))
        return restraint_objects
Ejemplo n.º 6
0
    def import_restraints(self, verbose: bool = False) -> t.List[dict]:
        """
        This function reads in a gromos distance restraint file. TODO: Read
            in additional Settings (r0, w0, etc...)

        TODO: WE could try to read thefile in get_args to get the Error there already.
         IDEA: READ THE WHOLE TEXT IN GET ARGS AND ONLY CONVERT IT HERE. OS ALLERRORS HAPPEN IN GET ARGS

        Parameters
        ----------
        verbose

        Returns
        -------
        t.List[dict]
            returns a dict containing the atom ids for each disres. (has to be
            translated in interface_Pymol


        """

        restraint_objects = [
        ]  # Define before try_block, so we can return the empty list in case of errors
        try:
            tmp_file_content = json.load(open(self.in_path, "r"))

            # Analogous new version
            for i, restraint in tmp_file_content.items():
                if verbose: print(restraint)
                atom1 = u.find_atom_by_property(self.all_atoms,
                                                restraint['a1']['id'])
                atomRef = u.find_atom_by_property(self.all_atoms,
                                                  restraint['aR']['id'])
                new_restraint = Restraints.PositionRestraint(
                    atomA=atom1, reference_atom=atomRef)
                restraint_objects.append(new_restraint)

            # PRINT RESULTS
            for i_r, r in enumerate(restraint_objects):
                print('PositionRestraint', str(i_r), ': Atom1_ID:',
                      str(r.atoms[0].id), 'AtomR_ID:',
                      str(r.reference_atom.id))

        except FileNotFoundError:
            print("Error: Could not find the file: \'" + self.in_path + "\'",
                  mv=4)
        except KeyError:
            print("Error: Could not read the file: " + self.in_path, mv=4)
        except ImportError:
            print(
                "BAD ERROR: FAILED TO IMPORT THE MODULES NECESSARY FOR IMPORTING AND EXPORTING JSON FILES!",
                mv=4)

        if (len(restraint_objects) == 0):
            warnings.warn("Could not find any Restraint in file: " +
                          str(self.in_path))
        return restraint_objects
Ejemplo n.º 7
0
    def _set_exporter_type(self, new_exporter_type: type):
        '''
            _set_exporter_type changes the current type of Exporter and creates and applies an Exporter of that type.

            :warning: Should only be called via set_action_type which handles type checking.
            :param new_exporter_type: type of the new Filter
            :type new_exporter_type: t.Type[Exporter]
            :return: None
            :rtype: None
            '''

        if new_exporter_type == None:
            self.current_exporter_type == None
            self.my_exporter == None
            return

        if not new_exporter_type in self.available_exporter_types + [None]:
            raise TypeError(str(new_exporter_type) + ' is not an available type of Exporter')

        self.my_exporter = new_exporter_type(self.selected_restraints)
        if try_to_get_args(self.my_exporter, u.create_file_save_dialog()):  # u.create_input_dialog(None, 'Exporter')
            self.my_exporter.export_restraints()
        else:
            self.my_exporter = None
            self.current_exporter_type = None
Ejemplo n.º 8
0
    def get_args(self, input_function: t.Callable = lambda *args: 'C'):
        """
            get_args(...) Needs to be called, before filter() can be used.
             For the Element_Filter it finds out which element should be filtered

        Parameters
        ----------
        input_function: function(str)
            A function that will find the input needed ofr the filter.
        message: str
            A string that is displayed if if input function needs to communicate with the user

        Returns
        -------
        NoReturn

        """

        input: str = input_function(
            "Which Element do do you want to filter for?\n (select multiple elements seperated by , ; e.g. 'O, N')"
        )

        if (len(input) > 1):
            input = list(map(lambda x: x.strip(), input.split(",")))
        else:
            input = [input]

        self.in_path = u.check_or_convert_argument(input, str)
        self.elem = input
Ejemplo n.º 9
0
    def _set_importer_type(self, new_importer_type: t.Type[Importer._Importer]):
        '''
        _set_importer_type changes the current Importer type, and creates and apllies a new Importer of that type.

        :warning: Should only be called via set_action_type which handles type checking
        :param new_importer_type: An available type of Importer
        :type new_importer_type: type[Importer]
        :return: None
        :rtype: None
        :raises TypeError if new_importer_type is not in available_importer_types
        '''

        if new_importer_type == None:
            self.current_importer_type = None
            self.my_importer = None
            return

        if not new_importer_type in self.available_importer_types:
            raise TypeError(str(new_importer_type) + ' is not an available type of Importer')

        self.my_importer = new_importer_type(self.all_atoms)
        if try_to_get_args(self.my_importer, u.create_file_open_dialog()):
            self.selected_restraints = self.my_importer.import_restraints()

        else:
            self.my_importer = None
            self.current_importer_type = None
Ejemplo n.º 10
0
def pymol_selection_to_atom_list(sele: str) -> t.List[u.Atom]:
    """
    pymol_selection_to_atom_list(...) converts a interface_Pymol selection and returns a list of restraintmaker_Logic.utilities.Atom
    :return: A list of Atoms
    :rtype: t.List[u.Atom]
    """
    atom_info: t.List[t.Dict] = []
    # Get all the information about the Atoms as a dict. I can not directly put it into an atom, because the interface_Pymol interpreter will not know what an u.Atom is.
    cmd.iterate_state(
        -1,
        selection=sele,
        expression=
        "atom_info.append({\"elem\":elem,\"id\":ID, \"name\":name, \"x\":x, \"y\":y, \"z\":z, \"model\": model, \"chain\":chain, \"resn\":resn, \"resi\":resi, \"alt\":alt,  \"label\":label, \"b\":b})",
        space=locals())

    # Convert dict to Atoms
    atoms: t.List[u.Atom] = []
    for a in atom_info:
        x = u.Atom(elem=a['elem'],
                   id=a['id'],
                   name=a['name'],
                   x=a['x'],
                   y=a['y'],
                   z=a['z'],
                   chain=a['chain'],
                   resn=a['resn'],
                   resi=a['resi'],
                   alt=a['alt'],
                   label=a['label'],
                   b=a['b'])
        atoms.append(x)

    return (atoms)
Ejemplo n.º 11
0
    def get_args(self, input_function: t.Callable):
        """
            get_args(...) Needs to be called, before filter() can be used. For the Property_Filter it finds out which
                property should be filter-criterion and then which value it should have.

            Todo: think about multiple property selections

        Parameters
        ----------
        input_function : function(str)
            A function that will find the input needed ofr the filter.
        message : str
            A string that is displayed if if input function needs to communicate with the user

        Returns
        -------
        NoReturn

        Raises
        ------
        BadArgumentException
            if the input function does not provide all arguments in the necessary format

        """

        input = input_function(
            'Which atom-property should be the filter criterion?\nPossible criteria are: '
            + ", ".join(u.Atom._fields))
        self.criterion: str = u.check_or_convert_argument(input, str)
        if not self.criterion in u.Atom._fields:
            raise u.BadArgumentException(
                "The filter criterion \' " + self.criterion +
                " \' provided by the input function is not an attribute of an Atom."
            )

        input = input_function('What value should ' + self.criterion +
                               ' have?')
        try:
            self.value = u.check_or_convert_argument(
                input,
                self.atoms[0].__getattribute__(self.criterion).__class__)
        except IndexError:  # Happens when len(self.atoms) is 0. No special handling necessary. It just means no atoms will be selected.
            pass
Ejemplo n.º 12
0
    def get_args(self, input_function: t.Callable):
        """
        get_args(...) Needs to be called, before filter() can be used. It uses an input function to find all arguments required by a certain instance of a _Filter.

        For RingFilter that is a List of all Molecules in the pdb format (CAREFULL: The Molecules need to contain ALL atoms in the Molecules, not just the selected one.)


        :param input_function: A function that can get the input
        :type input_function: function(str)
        :param message: A string that is displayed if if input function needs to communicate with the user
        :type message: String
        :return: -
        :rtype: -
        :raises: BadArgumentException if the input function does not provide all arguments in the necessary format
        """

        input = input_function("A List of Molecules in the PDB FORMAT:")
        input = u.check_or_convert_argument(input, list)
        molecules_pdb = [u.check_or_convert_argument(i, str) for i in input]
        self.molecules_rdk = Rdkit_Functions.parse_pdb_blocks_to_rdkit(molecules_pdb)
Ejemplo n.º 13
0
    def get_args(self, input_function: t.Callable):
        """
        should be overridden by every subclass of Exporter. It will assign all necessary varaibles using input_function

         For Gromos_Importer: in_path

        Parameters
        ----------
        input_function : t.Callable[[str], t.Any]
             a function that will provide the arguments for the selection in the necessary format.

        Returns
        -------
        NoReturn

        Raises
        ------
        BadArgument
            Excpetion if the input function does not deliver the arguments as needed
        NotImplementedError
            if _Importer.get_args is called directly
        """

        input = input_function(
            'Which file should the restrants be read from? ')
        self.in_path = u.check_or_convert_argument(input, str)

        if (self.in_path.endswith(self.file_ending)):
            warnings.warn(
                "I could not find the correct file ending. However I will try importing! File ending should be: "
                + str(self.file_ending))

        if self.in_path == '' or self.in_path == 'None':
            raise u.BadArgumentException(
                "Empty filename. (Unless you actually wanted to call your file 'None'. \n"
                "In which case you have to blame Python's promiscuous type conversion.  And yourself, for not using file extensions.)"
            )

        if (not os.path.isfile(self.in_path)):
            raise IOError("Could not find File in import path: " +
                          str(self.in_path))
Ejemplo n.º 14
0
    def _set_filter_type(self, new_filter_type: type):
        '''
        _set_filter_type changes the current type of Filter and creates and applies a Filter of that type.

        :warning: Should only be called via set_action_type which handles type checking
        :param new_filter_type: type of the new Filter
        :type new_filter_type: t.Type[Filter]
        :return: None
        :rtype: None
        '''

        if new_filter_type == None:
            self.current_filter_type = None
            self.my_filter = None
            return

        # Check for erros the GUI module hsould already have dealt with
        if not new_filter_type in self.available_filter_types + [None]:
            raise TypeError(str(new_filter_type) + ' is not an available type of Filter')

        # Create list of all atoms in the current selection:

        self.my_filter = new_filter_type(self.selected_atoms)

        # Switchtable for different provider funcs
        # TODO STRUC: Remove special cases, use a generic input function

        input_function = u.do_nothing
        if isinstance(self.my_filter, Filter.PropertyFilter):
            input_function = u.create_input_dialog(parent_window=None, title='PropertyFilter')
        elif isinstance(self.my_filter, Filter.ElementFilter):
            input_function = u.create_input_dialog(parent_window=None, title='ElementFilter')
        elif isinstance(self.my_filter, Filter.RingFilter):
            # TODO: GET INDEPENDENT OF PYMOL HERE => Write an own pdb function
            input_function = lambda dummy_arg: _convert_molecules_to_pdb()

        if try_to_get_args(self.my_filter, input_function):
            self.selected_atoms = self.my_filter.filter()
        else:
            self.my_filter = None
            self.current_filter_type = None
Ejemplo n.º 15
0
    def get_args(self, input_function: t.Callable[[str], t.Any]):
        '''
        get_args(...) should be overridden by every subclass of Exporter. It will assign all necessary varaibles using input_function

        For Gromos_Exporter: out_path

        :param input_function: a function that will provide the arguments for the selection in the necessary format.
        :type input_function: t.Callable[[str],t.Any]
        :return: -
        :rtype: None
        :raises: u.BadArgumentException
        '''

        # Error checking can only be done when we try to acess the file
        self.out_path = u.check_or_convert_argument(
            input_function('Name of the output File:'), str)
        if self.out_path == '' or self.out_path == 'None':
            raise u.BadArgumentException(
                "Empty filename. (Unless you actually wanted to call your file None. \n"
                "In which case you have to blame Python's promiscuous type conversion.  And yourself, for not using file extensions.)"
            )
    def react_to_event(self, event_type: program_states.EventType, **kw_args: t.Any):
        """
                react_to_event should be called by the GUI-module to report an event

            react_to_event will then call the relevant update function of the active selection and refresh all atom lists etc.

         @Waring react_to_event will change the state of the program (i.e. selected_atoms, selected_restraints, mode and actions states)
         It is strongly recommended to wrap react_to_event into a function of the GUI-module, which will check these and redraw the scene and de?activate buttons, if necessary/.


        Parameters
        ----------
        event_type : program_states.EventType
             What kind of event was triggered?
        kw_args :  dict
             Arguments the relevant update function will need

        Returns
        -------
        NoReturn

        Raises
        ------
        BadArgumentException
            if args to not match the the corresponding logic_handler.react_to_*_event_function
        NotImplementedError
            if a new event_type is used, which the function does not know about.

        """
        if self.my_selection == None or self.my_selection.has_finished:
            return

        try:
            if event_type == program_states.EventType.SELECT:
                self.my_selection._update_select(**kw_args)
            elif event_type == program_states.EventType.MOVE:
                self.my_selection._update_move(**kw_args)
            elif event_type == program_states.EventType.SIZE:
                self.my_selection._update_size(**kw_args)
            elif event_type == program_states.EventType.CONFIRM:
                self.my_selection._update_confirm(**kw_args)
            else:
                raise NotImplementedError('No action defined for event_type ' + str(event_type))

        except TypeError as err:
            raise u.BadArgumentException(
                'The provided arguments do not fit the function logic_handler.react to_ ' + str(
                    event_type) + ' _event') from err

        self._check_selection_status()
        self.set_action_states()
Ejemplo n.º 17
0
    def get_args(self, input_function: t.Callable):
        """
        get_args(...) should be overridden by every subclass of _Selection. It will assign all necessart variables using input function.
        For Limited_Filter those are: max_size: int - Maximal number of atoms in selection.
        :param input_function: a function that will provide the arguments for the selection in the necessary format: int
        :type input_function: t.Callable (str)
        :return: -
        :rtype: -
        :raises BadArgumentException: if the input function does not provide all arguments in the necessary format
        """

        input = input_function(
            "Maximal Number of Atoms in Limited Selection (int):")
        self.max_size = u.check_or_convert_argument(input, int)
Ejemplo n.º 18
0
    def __init__(self, all_atoms: t.List[u.Atom]):
        '''
        :param all_atoms: List of all atoms in the Molecules, which should be connected
        :type all_atoms: t.List[u.Atom]
        '''

        self.all_atoms: t.List[u.Atom] = all_atoms
        self.selected_atoms: t.List[u.Atom] = []
        self.selected_restraints: t.List[Restraint._Restraint] = []

        # Define Restraint-Types
        self.available_restraint_types = u.get_all_subclasses(Restraint._Restraint)
        self.current_restraint_type = None
        self.my_restraint = None

        # Define Importer-Types
        self.available_importer_types = u.get_all_subclasses(Importer._Importer)
        self.current_importer_type = None
        self.my_importer = None

        # Define Selection-Types
        self.available_selection_types: t.list[t.type] = u.get_all_subclasses(Selection._Selection)
        self.current_selection_type = None
        self.my_selection = None  # Unlike my_filter my_selection needs to be accessed by several methods: do_pick, set_selection

        # Define Filter-Types
        self.available_filter_types: t.list[t.type] = u.get_all_subclasses(Filter._Filter)
        self.current_filter_type = None
        self.my_filter = None

        # Define-Optimizer Types
        self.available_optimizer_types: t.List[t.type] = u.get_all_subclasses(Optimizer._Optimizer)
        self.current_optimizer_type = None
        self.my_optimizer = None

        # Define-Exporter-Types
        self.available_exporter_types = u.get_all_subclasses(Exporter._Exporter)
        self.current_exporter_type = None
        self.my_exporter = None

        # Modes & Action_States (Modes: What do to atoms, when they are selected. Action states: Which actions are possible right now)
        # TODO CLEAN (1): If we ever use more porgram modes it mioght be cleaner to make the enum u.ActionStates a class,
        # which contains one attribute indicating actions AND one for each mode
        self.select_or_delete_mode = True  # True = select, False = delte
        self.atom_or_restraint_mode = True  # True = atom, False = Restraint

        self._action_states: dict = {
            'toggle_select_delete': u.ActionState.ALWAYS_ENABLED,
            'toggle_atom_restraint': u.ActionState.ALWAYS_ENABLED,
            'Importer': u.ActionState.ALWAYS_DISABLED,
            'Restraint': u.ActionState.ALWAYS_DISABLED,
            'Selection': u.ActionState.ALWAYS_DISABLED,
            'Filter': u.ActionState.ALWAYS_DISABLED,
            'Optimizer': u.ActionState.ALWAYS_DISABLED,
            'Exporter': u.ActionState.ALWAYS_DISABLED,
            'Done': u.ActionState.ALWAYS_ENABLED}
        self.set_action_states()
Ejemplo n.º 19
0
    def get_args(self, input_function: t.Callable = lambda *args: 'C'):
        """
        get_args(...) Needs to be called, before filter() can be used.

         For the Element_Filter it finds out which element should be filtered
        :param input_function: A function that will find the input needed ofr the filter.
        :type input_function: function(str)
        :param message: A string that is displayed if if input function needs to communicate with the user
        :type message: String
        :return: -
        :rtype: -
        """
        input: str = input_function("Which Element do do you want to filter for?")
        self.in_path = u.check_or_convert_argument(input, str)
        self.elem = input
Ejemplo n.º 20
0
    def react_to_event(self, event_type: u.EventType, **kw_args: t.Any):
        '''
        react_to_event should be called by the GUI-module to report an event

        react_to_event will then call the relevant update function of the active selection and refresh all atom lists etc.

        :warning: react_to_event will change the state of the program (i.e. selected_atoms, selected_restraints, mode and actions states)
        It is strongly recommended to wrap react_to_event into a function of the GUI-module, which will check these and redraw the scene and de?activate buttons, if necessary/.

        :param event_type: What kind of event was triggered?
        :type event_type: u.EventType
        :param kw_args: Arguments the relevant update function will need
        :type kw_args: t.Any
        :raises u.BadArgumentException if args to not match the the corresponding logic_handler.react_to_*_event_function
        :raises NotImplementedError if a new event_type is used, which the function does not know about.
        :return: None
        :rtype: None
        '''

        # Note: Wierd python Syntax:  The * operator means two different things here: in the function definition **kw_args indicates, that I want to take an arbitrary number of keyword arguments and pack them all INTO a dict called args.
        #                                                in the function calls ** kw_args means, that I want to UNPACK a dict called kwargs s and pass each value as a separate keyword-argument.

        if self.my_selection == None or self.my_selection.has_finished:
            return

        try:
            if event_type == u.EventType.SELECT:
                self.my_selection._update_select(**kw_args)
            elif event_type == u.EventType.MOVE:
                self.my_selection._update_move(**kw_args)
            elif event_type == u.EventType.SIZE:
                self.my_selection._update_size(**kw_args)
            elif event_type == u.EventType.CONFIRM:
                self.my_selection._update_confirm(**kw_args)
            else:
                raise NotImplementedError('No action defined for event_type ' + str(event_type))

        except TypeError as err:
            raise u.BadArgumentException(
                'The provided arguments do not fit the function logic_handler.react to_ ' + str(
                    event_type) + ' _event') from err

        self._check_selection_status()
        self.set_action_states()
Ejemplo n.º 21
0
    def _set_selection_type(self, new_selection_type: type, ):
        '''
        _set_selection_type chagnes the current type of Selection and starts a new selection of that type.

        :warning: Should only be called via set_action_type which handles type checking
        :param new_selection_type: type of the new Selection
        :type new_selection_type: t.Type[Selection]
        :return: None
        :rtype: None
        '''

        if new_selection_type == None:
            self.current_selection_type = None
            self.my_selection = None
            return

        if not new_selection_type in self.available_selection_types:
            raise TypeError(str(new_selection_type) + ' is not an  available type of Selection')

        self.current_selection_type = new_selection_type
        self.my_selection = new_selection_type(self.all_atoms)

        # Switchtable for different provider funcs
        # TODO STRUC: Remove special cases, use a generic input function

        input_function = u.do_nothing
        if self.my_selection.__class__ == Selection.LimitedSelection:
            input_function = u.create_input_dialog(parent_window=None, title='Selection')
        elif isinstance(self.my_selection, Selection.SphericalSelection):
            input_function = lambda _: 5
        elif isinstance(self.my_selection, Selection.MCS_Selection):
            input_function = lambda dummy_arg: _convert_molecules_to_pdb()

        if not try_to_get_args(self.my_selection, input_function):
            self.my_selection = None
            self.current_selection_type = None
Ejemplo n.º 22
0
    def _set_optimizer_type(self, new_optimizer_type: type):
        '''
        _set_optimizer_type changes the current type of Optimizer and creates and applies a Optimizer of that type.

        :warning: Should only be called via set_action_type which handles type checking.
        :param new_optimizer_type: type of the new Filter
        :type new_optimizer_type: t.Type[Filter]
        :return: None
        :rtype: None
        '''
        if new_optimizer_type == None:
            self.current_optimizer_type = None
            self.my_optimizer = None
            return

        if not new_optimizer_type in self.available_optimizer_types + [None]:
            raise TypeError(str(new_optimizer_type) + ' is not an available type of Optimizer')

        self.my_optimizer = new_optimizer_type(self.selected_atoms)

        # TODO: See TODO in u.creat_multi_dialog
        # SWITCHTABLE FOR input function
        input_functions = u.do_nothing()
        # TODO: More elegant than these hardcoded input functions: Give each Optimizer etc. an attribute specifzing which args it needs, which we can than pass to create_multi_dialog
        # TODO: Generate new field in pyqt win to select if you want a chain, ring, or all to all connection

        if isinstance(self.my_optimizer, Optimizer.TreeHeuristicOptimizer):
            input_function = u.create_multi_dialog(title='Parameters for TreeHeuristicOptimizer', \
                                                   inputs=['number of restraints', 'maximal distance of restraints',
                                                           'tree-algorithm', 'optimize molecules pairs by'], \
                                                   options={'tree-algorithm': ['shortest', 'cog', 'prim', "biased_avg"],
                                                            'optimize molecules pairs by': ['None', 'convex_hull',
                                                                                            'pca_2d']}, \
                                                   default={'number of restraints': '4',
                                                            'maximal distance of restraints': '1.2',
                                                            'algorithm': 'shortest',
                                                            'optimize molecules pairs by': 'pca_2d'})


        elif isinstance(self.my_optimizer, Optimizer.BruteForceRingOptimzer):
            input_function = u.create_multi_dialog(title='Parameters for BruteForceOptimizer', \
                                                   inputs=['number of restraints', 'maximal distance of restraints',
                                                           'algorithm', 'optimize molecules pairs by'], \
                                                   options={'algorithm': ['convex_hull', 'pca'],
                                                            'optimize molecules pairs by': ['None', 'convex_hull',
                                                                                            'pca_2d']}, \
                                                   default={'number of restraints': '4',
                                                            'maximal distance of restraints': '1.2', 'algorithm': 'pca',
                                                            'optimize molecules pairs by': 'pca_2d'})

        elif isinstance(self.my_optimizer, Optimizer.MetaMoleculeRingOptimizer):
            input_function = u.create_multi_dialog(title='Parameters for BestMoleculeRingOptimizer', \
                                                   inputs=['number of restraints', 'maximal distance of restraints',
                                                           'algorithm', 'optimize molecules pairs by'], \
                                                   options={'algorithm': ['convex_hull', 'pca'],
                                                            'optimize molecules pairs by': ['convex_hull',
                                                                                            'pca_2d']}, \
                                                   default={'number of restraints': '4',
                                                            'maximal distance of restraints': '1.2', 'algorithm': 'pca',
                                                            'optimize molecules pairs by': 'pca_2d'})

        if try_to_get_args(self.my_optimizer, input_function):
            time_start = time.time()

            try:
                self.selected_restraints = self.my_optimizer.make_restraints()
                time_stop = time.time()
                print('Optimized in ' + '{:0.1f}'.format(time_stop - time_start) + ' s', mv=3)
            except u.NoOptimalSolutionException as ex:
                print('Failed to find a optimal solution under the given conditions:', ex, mv=4)
        else:
            self.my_optimizer = None
            self.current_optimizer_type = None
    def _set_optimizer_type(self, new_optimizer_type: type):
        """
            changes the current type of Optimizer and creates and applies a Optimizer of that type.
            @Warnings  Should only be called via set_action_type which handles type checking.

        Parameters
        ----------
        new_optimizer_type : t.Type[Filter]
            type of the new Filter

        Returns
        -------
        NoReturn

        """

        if new_optimizer_type == None:
            self.current_optimizer_type = None
            self.my_optimizer = None
            return

        if not new_optimizer_type in self.available_optimizer_types + [None]:
            raise TypeError(str(new_optimizer_type) + ' is not an available type of Optimizer')

        self.my_optimizer = new_optimizer_type(self.selected_atoms)

        # SWITCHTABLE FOR input function
        input_functions = u.do_nothing()

        if isinstance(self.my_optimizer, Optimizer.GreedyGraphOptimizer):
            input_function = qt_dialogs.create_multi_dialog(
                title='Parameters for GreedyGraphOptimizer', \
                inputs=['number of restraints', 'maximal distance of restraints',
                        'tree-algorithm', 'optimize molecules pairs by'], \
                options={'tree-algorithm': ['minmax', 'cog', 'prim', "biased_avg"],
                         'optimize molecules pairs by': ['None', 'convex_hull',
                                                         'pca_2d']}, \
                default={'number of restraints': '4',
                         'maximal distance of restraints': '1.0',
                         'algorithm': 'minmax',
                         'optimize molecules pairs by': 'convex_hull'})


        elif isinstance(self.my_optimizer, Optimizer.BruteForceRingOptimzer):
            input_function = qt_dialogs.create_multi_dialog(
                title='Parameters for BruteForceOptimizer', \
                inputs=['number of restraints', 'maximal distance of restraints',
                        'algorithm', 'optimize molecules pairs by'], \
                options={'algorithm': ['convex_hull', 'pca'],
                         'optimize molecules pairs by': ['None', 'convex_hull',
                                                         'pca_2d']}, \
                default={'number of restraints': '4',
                         'maximal distance of restraints': '1.2', 'algorithm': 'pca',
                         'optimize molecules pairs by': 'pca_2d'})

        elif isinstance(self.my_optimizer, Optimizer.MetaMoleculeRingOptimizer):
            input_function = qt_dialogs.create_multi_dialog(
                title='Parameters for BestMoleculeRingOptimizer', \
                inputs=['number of restraints', 'maximal distance of restraints',
                        'algorithm', 'optimize molecules pairs by'], \
                options={'algorithm': ['convex_hull', 'pca'],
                         'optimize molecules pairs by': ['convex_hull',
                                                         'pca_2d']}, \
                default={'number of restraints': '4',
                         'maximal distance of restraints': '1.2', 'algorithm': 'pca',
                         'optimize molecules pairs by': 'pca_2d'})

        if try_to_get_args(self.my_optimizer, input_function):
            time_start = time.time()

            try:
                self.selected_restraints = self.my_optimizer.make_restraints()
                time_stop = time.time()
                print('Optimized in ' + '{:0.1f}'.format(time_stop - time_start) + ' s', mv=3)
            except u.NoOptimalSolutionException as ex:
                print('Failed to find a optimal solution under the given conditions:', ex, mv=4)
        else:
            self.my_optimizer = None
            self.current_optimizer_type = None
    def __init__(self, all_atoms: t.List[u.Atom]):
        """
            Handles the program flow. By defining it inside a class we get proper encapsulation and prevent problems with multiple imports

            When a GUI Program Launches it should create one instance of a Logic_Handler and use it to control the program flow.
            It should pass GUI-events to it (by calling the react_to_event method.). The GUI Module should NOT need to directly access any other modules. (Except utilities).
            Warning: To keep things clean there is not backwards communicatopn from the Logic_Handler to the GUI module. It is the GUI Modules responsibility to check on the current state of the program, after creating events.
            Warning: I really do NOT want the GUI-Program to inherit form the Logic_Handler. It will inherit from a GUI Element (e.g. interface_Pymol.Wizard). Python suppports multiple inheritance, but I don't.

            RECOMMENDATIONS TO WRITE A NEW GUI MODULE:
            The GUI Module should have the following functions/Elements

            1) Buttons/Lists... for the different actions that can be performed (Import, RestraintType, Selection ...). These should call the function set_importer_type, set_restraint_type ...
                    The GUI Program should use the action_states dict, to check which actions are currently available.
            2) 2 Toggle buttons / radio buttons... to switch between select / delete mode and atom / restraint mode

            2) Events: The GUI Module is responsible for translating whatever events it understands into events relevant to the selections. It can do this by calling the function react_to_event(event_type, kw_args)
               Recommended translations:    SELECT: When the user clicks a certain Atom
                                            MOVE: Mouse movement / keyboard arrows ...
                                            SIZE: Mouse wheel / keyboard arrows
                                            CONFIRM: Double Click, Enter ...

                 The GUI module should check the state of the program (event_state dict and selected_atoms, selected-restraints) every time after calling react_to_event.
                 I recommend wrapping the react_to_event function into a function of the GUI module to do that automatically.

            3) Some Selections (SphericalSelection & subclasses) are more intuitive if the GUI program draws a sphere at the corresponding position. => If you want that you have to introduce special for the GUI module to check the current selection

        Parameters
        ----------
        all_atoms : t.List[u.Atom]
             List of all atoms in the Molecules, which should be connected

        """

        self.all_atoms: t.List[u.Atom] = all_atoms
        self.selected_atoms: t.List[u.Atom] = []
        self.selected_restraints: t.List[Restraints._Restraint] = []

        # Define Restraint-Types
        self.all_restraint_types = u.get_all_subclasses(Restraint_Types._Restraint_Type)
        self.available_restraint_types = []
        self.current_restraint_type:Restraint_Types._Restraint_Type = Restraint_Types.DistanceRestraintType
        self.my_restraint: Restraint_Types._Restraint_Type = None

        # Define Importer-Types
        self.available_importer_types = u.get_all_subclasses(Importer._Importer)
        self.current_importer_type = None
        self.my_importer = None

        # Define Selection-Types
        self.available_selection_types: t.List[t.Type] = u.get_all_subclasses(Selection._Selection)
        self.current_selection_type = None
        self.my_selection = None  # Unlike my_filter my_selection needs to be accessed by several methods: do_pick, set_selection

        # Define Filter-Types
        self.available_filter_types: t.List[t.Type] = u.get_all_subclasses(Filter._Filter)
        self.current_filter_type = None
        self.my_filter = None

        # Define-Optimizer Types
        self.available_optimizer_types: t.List[t.Type] = [x for x in u.get_all_subclasses(Optimizer._Optimizer) if (not x == Optimizer.MetaMoleculeRingOptimizer)]
        self.current_optimizer_type = None
        self.my_optimizer = None

        # Define-Exporter-Types
        self.all_exporter_types = u.get_all_subclasses(Exporter._Exporter)
        self.available_exporter_types = u.get_all_subclasses(Exporter._Export_Distance_Restraints)
        self.current_exporter_type = None
        self.my_exporter = None

        # Modes & Action_States (Modes: What do to atoms, when they are selected. Action states: Which actions are possible right now)
        # which contains one attribute indicating actions AND one for each mode

        self._action_states: dict = {
            'toggle_select_delete': program_states.ActionState.ALWAYS_ENABLED,
            'toggle_atom_restraint': program_states.ActionState.ALWAYS_ENABLED,
            'Reset':  program_states.ActionState.ALWAYS_ENABLED,
            'Importer': program_states.ActionState.ALWAYS_DISABLED,
            'Restraint': program_states.ActionState.ALWAYS_DISABLED,
            'Selection': program_states.ActionState.ALWAYS_DISABLED,
            'Filter': program_states.ActionState.ALWAYS_DISABLED,
            'Optimizer': program_states.ActionState.ALWAYS_DISABLED,
            'Exporter': program_states.ActionState.ALWAYS_DISABLED,
            'Done': program_states.ActionState.ALWAYS_ENABLED}

        #initialize
        self.set_mode(select_delete=True, atom_restraint=True)
        self.set_action_states()
        self._set_restraint_type(self.current_restraint_type)
Ejemplo n.º 25
0
def print(*args, mv=0):
    u.print(*args, mv=mv)