Ejemplo n.º 1
0
    def _validate_arguments_to_add_motif(self, m, m_name):
        """
        makes sure the add_motif function is called correctly

        :param m: motif to add to tree
        :type m: Motif object

        :param m_name: name of motif to add
        :type m_name: str

        :return: None
        """

        if m is not None and m_name is not None:
            raise exceptions.MotifTreeException(
                "cannot supply both a motif and motif name to add a motif to "
                "a motif tree")

        if m is None and m_name is None:
            raise exceptions.MotifTreeException(
                "must supply a motif object or motif name to add_motif")

        if m is not None:
            for n in self.tree.nodes:
                if n.data.id == m.id:
                    raise exceptions.MotifTreeException(
                        "cannot add motif: " + m.name +
                        " to tree as its uuid is " +
                        "already present in the tree")
Ejemplo n.º 2
0
    def replace_motif(self, pos, new_motif):
        """
        replaces the motif at a specific node with a new motif and updates the
        oriention of each motif. The new motif has the same number of basepair
        ends as the motif it is replacing. Does not check sterics upon swaping
        new motif

        :param pos: node position of the motif you wish to replace
        :type pos: int

        :param new_motif: motif to be inserted into tree
        :type new_motif: Motif

        """

        node = self.get_node(pos)
        if len(new_motif.ends) != len(node.data.ends):
            raise exceptions.MotifTreeException(
                "attmpted to replace a motif with a different number of ends")

        node.data = new_motif.copy()

        for n in tree.transverse_tree(self.tree, pos):
            parent = n.parent
            if parent is None:
                continue
            pei = n.parent_end_index()
            m_added = motif.get_aligned_motif(parent.data.ends[pei],
                                              n.data.ends[0], n.data)
            n.data = m_added

        self.update_merger = 1
Ejemplo n.º 3
0
    def _get_motif_from_manager(self, m_name, m_end_name):
        """
        helper function for add_motif should not be called directly. calls
        resource manager to get motif to be added to tree by the name of
        the motif.

        :param m_name: name of the motif to add to the tree
        :type m_name: str

        :param m_end_name: name of the basepair end of the motif to align by.
        :type m_end_name: str

        """

        try:
            if m_end_name is not None:
                m = rm.manager.get_motif(name=m_name, end_name=m_end_name)
            else:
                m = rm.manager.get_motif(name=m_name)
        except exceptions.ResourceManagerException as e:
            raise exceptions.MotifTreeException(
                "cannot add motif to tree, motif cannot be found in resource "
                "manager")

        return m
Ejemplo n.º 4
0
    def _get_connection_end(self, node, bp_name):

        node_end_index = -1

        if bp_name != "":
            ei = node.data.get_end_index(bp_name)

            if not node.available_pos(ei):
                raise exceptions.MotifTreeException(
                    "cannot add connection with " + str(node.index) + " and "
                    "end name " + bp_name + " as this end is not available")

            if self.connections.in_connection(node.index, bp_name):
                raise exceptions.MotifTreeException(
                    "cannot add connection with " + str(node.index) +
                    " and end name " + bp_name + " as this end is "
                    "already in a connection")

            node_end_index = ei
        else:
            node_indexes = node.available_children_pos()
            node_indexes.remove(0)

            if len(node_indexes) > 1:
                raise exceptions.MotifTreeException("cannot connect nodes " +
                                                    str(node.index) +
                                                    " its unclear "
                                                    " which ends to attach")

            if len(node_indexes) == 0:
                raise exceptions.MotifTreeException(
                    "cannot connect nodes " + str(node.index) + " there are "
                    "no ends free ends to attach too")

            node_index_name = node.data.ends[node_indexes[0]].name()
            if self.connections.in_connection(node.index, node_index_name):
                raise exceptions.MotifTreeException(
                    "cannot connect nodes " + str(node.index) + " there are "
                    "no ends free ends to attach too")

            node_end_index = node_indexes[0]

        return node_end_index
Ejemplo n.º 5
0
        def _setup_node_positions(self):
            """
            Setups up the horizontal position of each node on the screen.
            Position is prograted from the start_pos with the first node. If
            the node only has one child, that child retains the same position,
            but if it has two the children will be seperated by 2* the branch
            length.
            """

            self._assign_node_levels()

            self.nodes_per_level = defaultdict(int)
            for n in self.nodes:
                self.nodes_per_level[self.levels[n.index]] += 1

            for i, n in enumerate(self.nodes):
                if i == 0:
                    self.node_pos[n.index] = self.start_pos

                children = []
                for j, c in enumerate(n.connections):
                    if j == 0:
                        continue
                    if c is not None:
                        child = c.partner(n.index)
                        if child.connections[0] != c:
                            continue

                        if child.index in self.node_pos:
                            continue
                        else:
                            children.append(child)

                if len(children) == 1:
                    self.node_pos[children[0].index] = self.node_pos[n.index]
                elif len(children) == 2:
                    level = self.levels[n.index]
                    nodes_per_level = self.nodes_per_level[level + 1]
                    extra = nodes_per_level - 2
                    parent_pos = self.node_pos[n.index]
                    if extra == 0:
                        self.node_pos[children[0].
                                      index] = parent_pos - self.branch_length
                        self.node_pos[children[1].
                                      index] = parent_pos + self.branch_length
                    else:
                        self.node_pos[children[
                            0].index] = parent_pos - self.branch_length / extra
                        self.node_pos[children[
                            1].index] = parent_pos + self.branch_length / extra
                elif len(children) > 2:
                    raise exceptions.MotifTreeException(
                        "Greater then two children is not supported for pretty_printing"
                    )
Ejemplo n.º 6
0
    def add_motif_tree(self, mt, parent_index=-1, parent_end_name=None):
        """
        add entire motif tree with all the motifs in that tree to this motif
        tree.

        :param mt: MotifTree object you wish to add
        :type mt: MotifTree

         :param parent_index: the index associated with the parent you want to
            align to. Default is -1 which will use the last motif added if one
            has been added.
        :type parent_index: int

        :param parent_end_name: the name of the end of the parent you wish to
            align too.
        :type parent_end_name: str

        :return: None
        """

        parent = self._get_parent_node(parent_index)
        parent_avail_ends = self._get_parent_available_ends(
            parent, -1, parent_end_name)

        if len(parent_avail_ends) > 1 or len(parent_avail_ends) == 0:
            parent_end_index = -1
        else:
            parent_end_index = parent_avail_ends[0]

        index_hash = {}
        for i, n in enumerate(mt):
            m = n.data
            if i == 0:
                j = self.add_motif(m, parent_index, parent_end_index)
            else:
                pi = index_hash[n.parent_index()]
                j = self.add_motif(m,
                                   pi,
                                   parent_end_index=n.parent_end_index())

            if j == -1:
                raise exceptions.MotifTreeException(
                    "failed to add a motif in add_motif_tree to the current "
                    "motif tree it is likely a steric clash, consider "
                    "turning off sterics")

            index_hash[n.index] = j
Ejemplo n.º 7
0
    def _get_parent_node(self, parent_index):
        """
        gets node that serve as the parent of the current motif being added
        to the tree.

        :param parent_index: the tree index corresponding to the requested motif
        :type parent_index: int

        :return: tree node of parent
        :rtype: TreeNode
        """

        parent = self.tree.last_node

        if parent_index != -1:
            try:
                parent = self.tree.get_node(parent_index)
            except exceptions.TreeIndexException:
                raise exceptions.MotifTreeException(
                    "parent_index supplied: " + str(parent_index) +
                    " does not " + "exist in current motif tree")

        return parent
Ejemplo n.º 8
0
 def get_node_by_id(self, uuid):
     for n in self.tree.nodes:
         if n.data.id == uuid:
             return n
     raise exceptions.MotifTreeException("cannot find node with id")
Ejemplo n.º 9
0
    def _get_parent_available_ends(self, parent, parent_end_index,
                                   parent_end_name):
        """
        Gets the available ends of the parent that the current motif can align
        to. If either parent_end_index or parent_end_name are specified, checks
        to see if that position is available.

        :param parent: the TreeNode of parent
        :type parent: TreeNode

        :param parent_end_index: which end this motif will be aligned to on
            parent
        :type parent_end_index: int

        :param parent_end_name: the name instead of the index of the end the
            current motif will align to
        :type parent_end_name: str

        :return: list of available parent end indexes that meet the specified
            constraints
        :rtype: list of ints
        """

        if parent is None:
            return []

        if parent_end_index != -1 and parent_end_name is not None:
            raise exceptions.MotifTreeException(
                "cannot supply parent_end_index and parent_end_name together")

        elif parent_end_name is not None:
            parent_ends = parent.data.get_basepair(name=parent_end_name)
            if len(parent_ends) == 0:
                raise exceptions.MotifTreeException(
                    "cannot find parent_end_name: " + parent_end_name + " in "
                    "parent motif: " + parent.data.name)
            if len(parent_ends) > 1:
                raise exceptions.MotifTreeException(
                    "more then one end was found with parent_end_name: " +
                    parent_end_name + " in parent motif: " + parent.data.name)

            parent_end = parent_ends[0]
            parent_end_index = parent.data.ends.index(parent_end)

            if parent_end_index == parent.data.block_end_add:
                raise exceptions.MotifTreeException(
                    "cannot add motif: to tree as the parent_end_name" +
                    " supplied is blocked see class Motif")

            available = parent.available_pos(parent_end_index)
            if not available:
                raise exceptions.MotifTreeException(
                    "cannot add motif to tree as the end " +
                    "you are trying to add it to is already filled or does "
                    "not exist")

            if self.connections.in_connection(parent.index, parent_end_name):
                raise exceptions.MotifTreeException(
                    "cannot add motif to tree as the end " +
                    "you are trying to add it to is in a connection")

            return [parent_end_index]

        elif parent_end_index != -1:
            if parent_end_index == parent.data.block_end_add:
                raise exceptions.MotifTreeException(
                    "cannot add motif: to tree as the parent_end_index" +
                    " supplied is blocked see class Motif")

            available = parent.available_pos(parent_end_index)
            if not available:
                raise exceptions.MotifTreeException(
                    "cannot add motif to tree as the end " +
                    "you are trying to add it to is already filled or does "
                    "not exist")
            parent_end_name = parent.data.ends[parent_end_index].name()

            if self.connections.in_connection(parent.index, parent_end_name):
                raise exceptions.MotifTreeException(
                    "cannot add motif to tree as the end " +
                    "you are trying to add it to is in a connection")
            return [parent_end_index]

        else:
            avail_pos = parent.available_children_pos()
            avail_pos.remove(0)

            final_avail_pos = []
            for p in avail_pos:
                parent_end_name = parent.data.ends[p].name()
                if self.connections.in_connection(parent.index,
                                                  parent_end_name):
                    continue
                final_avail_pos.append(p)

            return final_avail_pos