Example #1
0
    def update(self, strand5p: StrandT, idx: int = None):
        """Pass ``idx`` to this method in order to install a floating
        Xover for the forced xover tool

        Args:
            strand5p: Description
            idx: Default is ``None``
        """
        self._strand5p = strand5p
        strand3p = strand5p.connection3p()
        vhi5p = self._virtual_helix_item
        part_item = vhi5p.partItem()

        # This condition is for floating xovers
        idx_3_prime = idx if idx else strand5p.idx3Prime()

        if self._node5 is None:
            self._node5 = XoverNode5(vhi5p, self, strand5p, idx_3_prime)
        if strand3p is not None:
            if self._node3 is None:
                vhi3p = part_item.idToVirtualHelixItem(strand3p.idNum())
                self._node3 = XoverNode3(vhi3p, self, strand3p,
                                         strand3p.idx5Prime())
            else:
                self._node5.setIdx(idx_3_prime)
                self._node3.setIdx(strand3p.idx5Prime())
            self._node5.setPartnerVirtualHelix(strand5p)
            self._updatePath(strand5p)
        else:
            if self._node3:
                self._node3.destroyItem()
                self._node3 = None
Example #2
0
    def removeStrand(self,
                     strand: StrandT,
                     use_undostack: bool = True,
                     solo: bool = True):
        """Remove a :class:`Strand` from the set

        Args:
            strand: the :class:`Strand` to remove
            use_undostack (optional): default = ``True``
            solo ( optional): solo is an argument to enable
                limiting signals emiting from the command in the case the
                command is instantiated part of a larger command, default=``True``
        """
        cmds = []

        if not self.isStrandInSet(strand):
            raise IndexError("Strandset.removeStrand: strand not in set")
        if strand.sequence() is not None:
            cmds.append(strand.oligo().applySequenceCMD(None))
        cmds += strand.clearDecoratorCommands()
        cmds.append(RemoveStrandCommand(self, strand, solo=solo))
        util.execCommandList(self,
                             cmds,
                             desc="Remove strand",
                             use_undostack=use_undostack)
Example #3
0
 def setPartnerVirtualHelix(self, strand: StrandT):
     """
     Args:
         strand: Description
     """
     if strand.connection3p():
         self._partner_virtual_helix_id_num = strand.connection3p().idNum()
     else:
         self._partner_virtual_helix_id_num = None
 def __init__(self, strand: StrandT, idx: int, length: int):
     super(AddInsertionCommand, self).__init__("add insertion")
     self._strand = strand
     id_num = strand.idNum()
     self._insertions = strand.part().insertions()[id_num]
     self._idx = idx
     self._length = length
     self._insertion = Insertion(idx, length)
     self._comp_strand = \
         strand.strandSet().complementStrandSet().getStrand(idx)
Example #5
0
 def __init__(self, strand: StrandT, idx: int, length: int):
     super(AddInsertionCommand, self).__init__("add insertion")
     self._strand = strand
     id_num = strand.idNum()
     self._insertions = strand.part().insertions()[id_num]
     self._idx = idx
     self._length = length
     self._insertion = Insertion(idx, length)
     self._comp_strand = \
         strand.strandSet().complementStrandSet().getStrand(idx)
Example #6
0
    def __init__(self,  model_strand: StrandT,
                        virtual_helix_item: PathVirtualHelixItemT):
        """The parent should be a VirtualHelixItem.

        Args:
            model_strand:
            virtual_helix_item:
        """
        super(StrandItem, self).__init__(virtual_helix_item)
        self._model_strand = model_strand
        self._virtual_helix_item = virtual_helix_item
        self._viewroot: PathRootItemT = virtual_helix_item._viewroot
        self._getActiveTool = self._viewroot.manager.activeToolGetter

        self._controller = StrandItemController(self, model_strand)
        is_forward = model_strand.strandSet().isForward()

        self._strand_filter = model_strand.strandFilter()

        self._insertion_items = {}
        # caps
        self._low_cap = EndpointItem(self, 'low', is_forward)
        self._high_cap = EndpointItem(self, 'high', is_forward)
        self._dual_cap = EndpointItem(self, 'dual', is_forward)

        # orientation
        self.is_forward = is_forward
        self._seq_label = QGraphicsSimpleTextItem(self)

        self.refreshInsertionItems(model_strand)
        if not getBatch():
            self._updateSequenceText()

        # create a larger click area rect to capture mouse events
        self._click_area = c_a = QGraphicsRectItem(_DEFAULT_RECT, self)
        c_a.mousePressEvent = self.mousePressEvent
        c_a.setPen(_NO_PEN)
        self.setAcceptHoverEvents(True)
        c_a.setAcceptHoverEvents(True)
        c_a.hoverMoveEvent = self.hoverMoveEvent

        self.setZValue(styles.ZSTRANDITEM)

        # xover comming from the 3p end
        self.xover_3p_end = XoverItem(self, virtual_helix_item)
        if not getBatch():
            # initial refresh
            self._updateColor(model_strand)
            self._updateAppearance(model_strand)

        self.setZValue(styles.ZSTRANDITEM)
        self.setFlag(QGraphicsItem.ItemIsSelectable)
Example #7
0
    def __init__(self, model_strand: StrandT,
                 virtual_helix_item: PathVirtualHelixItemT):
        """The parent should be a VirtualHelixItem.

        Args:
            model_strand:
            virtual_helix_item:
        """
        super(StrandItem, self).__init__(virtual_helix_item)
        self._model_strand = model_strand
        self._virtual_helix_item = virtual_helix_item
        self._viewroot: PathRootItemT = virtual_helix_item._viewroot
        self._getActiveTool = self._viewroot.manager.activeToolGetter

        self._controller = StrandItemController(self, model_strand)
        is_forward = model_strand.strandSet().isForward()

        self._strand_filter = model_strand.strandFilter()

        self._insertion_items = {}
        # caps
        self._low_cap = EndpointItem(self, 'low', is_forward)
        self._high_cap = EndpointItem(self, 'high', is_forward)
        self._dual_cap = EndpointItem(self, 'dual', is_forward)

        # orientation
        self.is_forward = is_forward
        self._seq_label = QGraphicsSimpleTextItem(self)

        self.refreshInsertionItems(model_strand)
        if not getBatch():
            self._updateSequenceText()

        # create a larger click area rect to capture mouse events
        self._click_area = c_a = QGraphicsRectItem(_DEFAULT_RECT, self)
        c_a.mousePressEvent = self.mousePressEvent
        c_a.setPen(_NO_PEN)
        self.setAcceptHoverEvents(True)
        c_a.setAcceptHoverEvents(True)
        c_a.hoverMoveEvent = self.hoverMoveEvent

        self.setZValue(styles.ZSTRANDITEM)

        # xover comming from the 3p end
        self.xover_3p_end = XoverItem(self, virtual_helix_item)
        if not getBatch():
            # initial refresh
            self._updateColor(model_strand)
            self._updateAppearance(model_strand)

        self.setZValue(styles.ZSTRANDITEM)
        self.setFlag(QGraphicsItem.ItemIsSelectable)
Example #8
0
    def canInstallXoverAt(self, idx: int,
                                from_strand: StrandT,
                                from_idx: int) -> bool:
        """Assumes idx is:
        self.lowIdx() <= idx <= self.highIdx()
        """

        if self.hasXoverAt(idx):
            return False
        ss = self.strandSet()
        is_same_strand = from_strand == self

        is_forward = ss.isForward()
        index_diff_H = self.highIdx() - idx
        index_diff_L = idx - self.lowIdx()
        idx3p = self.idx3Prime()
        idx5p = self.idx5Prime()
        # ensure 2 bps from 3p end if not the 3p end
        index3_lim = idx3p - 1 if is_forward else idx3p + 1

        if is_same_strand:
            index_diff_strands = from_idx - idx
            if idx == idx5p or idx == index3_lim:
                return True
            elif index_diff_strands > -3 and index_diff_strands < 3:
                return False
        # end if for same Strand
        else:
            from_idx3p = from_strand.idx3Prime()
            from_idx5p = from_strand.idx5Prime()
            if idx == idx5p or idx == index3_lim:
                if from_idx3p == from_idx:
                    return True
                elif (abs(from_idx3p - from_idx) > 1 and
                      abs(from_idx5p - from_idx) > 1):
                    return True
                else:
                    # print("this:", idx, idx3p, idx5p)
                    # print("from:", from_idx, from_idx3p, from_idx5p)
                    return False
            elif index_diff_H > 2 and index_diff_L > 1:
                if from_idx3p == from_idx:
                    return True
                elif (abs(from_idx3p - from_idx) > 1 and
                      abs(from_idx5p - from_idx) > 1):
                    return True
                else:
                    return False
            else:
                # print("default", index_diff_H, index_diff_L)
                return False
Example #9
0
    def __init__(self, virtual_helix_item: PathVirtualHelixItemT,
                 xover_item: 'ForcedXoverItem', strand3p: StrandT, idx: int):
        """Summary

        Args:
            virtual_helix_item: from vhi
            xover_item (TYPE): Description
            strand3p (Strand): reference to the 3' strand
            idx (int): the base index within the virtual helix
        """
        super(ForcedXoverNode3, self).__init__(virtual_helix_item)
        self._vhi = virtual_helix_item
        self._xover_item = xover_item
        self._idx = idx

        self.is_forward = strand3p.strandSet().isForward()
        self._is_on_top = self.is_forward

        self._partner_virtual_helix = virtual_helix_item

        self._blank_thing = QGraphicsRectItem(_blankRect, self)
        self._blank_thing.setBrush(QBrush(Qt.white))
        self._path_thing = QGraphicsPathItem(self)
        self.configurePath()

        self._label = None
        self.setPen(_NO_PEN)
        self.setBrush(_NO_BRUSH)
        self.setRect(_rect)

        self.setZValue(styles.ZENDPOINTITEM + 1)
Example #10
0
    def strandCanBeSplit(self, strand: StrandT, base_idx: int) -> bool:
        """Make sure the base index is within the strand
        Don't split right next to a 3Prime end
        Don't split on endpoint (AKA a crossover)

        Args:
            strand: the :class:`Strand`
            base_idx: the index to split at

        Returns:
            ``True`` if can be split, ``False`` otherwise
        """
        # no endpoints
        lo, hi = strand.idxs()
        if base_idx == lo or base_idx == hi:
            return False
        # make sure the base index within the strand
        elif lo > base_idx or base_idx > hi:
            return False
        elif self._is_fwd:
            if base_idx - lo > 0 and hi - base_idx > 1:
                return True
            else:
                return False
        elif base_idx - lo > 1 and hi - base_idx > 0:  # reverse
            return True
        else:
            return False
Example #11
0
    def strandCanBeSplit(self, strand: StrandT, base_idx: int) -> bool:
        """Make sure the base index is within the strand
        Don't split right next to a 3Prime end
        Don't split on endpoint (AKA a crossover)

        Args:
            strand: the :class:`Strand`
            base_idx: the index to split at

        Returns:
            ``True`` if can be split, ``False`` otherwise
        """
        # no endpoints
        lo, hi = strand.idxs()
        if base_idx == lo or base_idx == hi:
            return False
        # make sure the base index within the strand
        elif lo > base_idx or base_idx > hi:
            return False
        elif self._is_fwd:
            if base_idx - lo > 0 and hi - base_idx > 1:
                return True
            else:
                return False
        elif base_idx - lo > 1 and hi - base_idx > 0:  # reverse
            return True
        else:
            return False
Example #12
0
    def __init__(self, virtual_helix_item: PathVirtualHelixItemT,
                        xover_item: 'ForcedXoverItem',
                        strand3p: StrandT,
                        idx: int):
        """Summary

        Args:
            virtual_helix_item: from vhi
            xover_item (TYPE): Description
            strand3p (Strand): reference to the 3' strand
            idx (int): the base index within the virtual helix
        """
        super(ForcedXoverNode3, self).__init__(virtual_helix_item)
        self._vhi = virtual_helix_item
        self._xover_item = xover_item
        self._idx = idx

        self.is_forward = strand3p.strandSet().isForward()
        self._is_on_top = self.is_forward

        self._partner_virtual_helix = virtual_helix_item

        self._blank_thing = QGraphicsRectItem(_blankRect, self)
        self._blank_thing.setBrush(QBrush(Qt.white))
        self._path_thing = QGraphicsPathItem(self)
        self.configurePath()

        self._label = None
        self.setPen(_NO_PEN)
        self.setBrush(_NO_BRUSH)
        self.setRect(_rect)

        self.setZValue(styles.ZENDPOINTITEM + 1)
Example #13
0
 def __init__(self, document: DocT, strand: StrandT, idx: int, mod_id: str):
     super(AddModsCommand, self).__init__()
     self._strand = strand
     self._id_num = strand.idNum()
     self._idx = idx
     self._mod_id = mod_id
     self.document = document
Example #14
0
 def __init__(self, document: DocT, strand: StrandT, idx: int, mod_id: str):
     super(AddModsCommand, self).__init__()
     self._strand = strand
     self._id_num = strand.idNum()
     self._idx = idx
     self._mod_id = mod_id
     self.document = document
Example #15
0
    def strandResizedSlot(self, strand: StrandT, indices: SegmentT):
        """Slot for handling resizing of this StrandItem

        Args:
            strand:
            indices: low and high indices
        """
        low_moved, group_low = self._low_cap.updatePosIfNecessary(
            self.idxs()[0])
        high_moved, group_high = self._high_cap.updatePosIfNecessary(
            self.idxs()[1])
        group = self.group()
        self.tempReparent()
        if low_moved:
            self.updateLine(self._low_cap)
        if high_moved:
            self.updateLine(self._high_cap)
        if strand.connection3p():
            self.xover_3p_end.update(strand)
        self.refreshInsertionItems(strand)
        self._updateSequenceText()
        if group:
            group.addToGroup(self)
        if group_low is not None:
            group_low.addToGroup(self._low_cap)
        if group_high is not None:
            group_high.addToGroup(self._high_cap)
Example #16
0
    def strandResizedSlot(self, strand: StrandT, indices: SegmentT):
        """Slot for handling resizing of this StrandItem

        Args:
            strand:
            indices: low and high indices
        """
        low_moved, group_low = self._low_cap.updatePosIfNecessary(self.idxs()[0])
        high_moved, group_high = self._high_cap.updatePosIfNecessary(self.idxs()[1])
        group = self.group()
        self.tempReparent()
        if low_moved:
            self.updateLine(self._low_cap)
        if high_moved:
            self.updateLine(self._high_cap)
        if strand.connection3p():
            self.xover_3p_end.update(strand)
        self.refreshInsertionItems(strand)
        self._updateSequenceText()
        if group:
            group.addToGroup(self)
        if group_low is not None:
            group_low.addToGroup(self._low_cap)
        if group_high is not None:
            group_high.addToGroup(self._high_cap)
Example #17
0
    def upperLeftCornerOfBase(self, idx: int, strand: StrandT) -> Vec2T:
        """
        Args:
            idx: the base index within the virtual helix
            strand: Description

        Returns:
            Tuple of upperLeftCornerOfBase
        """
        x = idx * _BASE_WIDTH
        y = 0 if strand.isForward() else _BASE_WIDTH
        return x, y
Example #18
0
    def __init__(self, strand: StrandT,
                        new_idxs: SegmentT,
                        update_segments: bool = True):
        super(ResizeCommand, self).__init__("resize strand")
        self.strand = strand
        self.old_indices = o_i = strand.idxs()
        self.new_idxs = new_idxs
        # an increase in length leads to positive delta
        self.delta = (new_idxs[1] - new_idxs[0]) - (o_i[1] - o_i[0])
        # now handle insertion deltas
        oldInsertions = strand.insertionsOnStrand(*o_i)
        newInsertions = strand.insertionsOnStrand(*new_idxs)
        o_l = 0
        for i in oldInsertions:
            o_l += i.length()
        n_l = 0
        for i in newInsertions:
            n_l += i.length()
        self.delta += (n_l - o_l)

        self.update_segments = update_segments
Example #19
0
    def removeStrand(self,  strand: StrandT,
                            use_undostack: bool = True,
                            solo: bool = True):
        """Remove a :class:`Strand` from the set

        Args:
            strand: the :class:`Strand` to remove
            use_undostack (optional): default = ``True``
            solo ( optional): solo is an argument to enable
                limiting signals emiting from the command in the case the
                command is instantiated part of a larger command, default=``True``
        """
        cmds = []

        if not self.isStrandInSet(strand):
            raise IndexError("Strandset.removeStrand: strand not in set")
        if strand.sequence() is not None:
            cmds.append(strand.oligo().applySequenceCMD(None))
        cmds += strand.clearDecoratorCommands()
        cmds.append(RemoveStrandCommand(self, strand, solo=solo))
        util.execCommandList(self, cmds, desc="Remove strand", use_undostack=use_undostack)
    def upperLeftCornerOfBase(self, idx: int, strand: StrandT) -> Vec2T:
        """
        Args:
            idx: the base index within the virtual helix
            strand: Description

        Returns:
            Tuple of upperLeftCornerOfBase
        """
        x = idx * _BASE_WIDTH
        y = 0 if strand.isForward() else _BASE_WIDTH
        return x, y
Example #21
0
    def _addToStrandList(self, strand: StrandT, update_segments: bool = True):
        """Inserts strand into the strand_array at idx

        Args:
            strand: the strand to add
            update_segments (optional): whether to signal default=``True``
        """
        idx_low, idx_high = strand.idxs()
        for i in range(idx_low, idx_high+1):
            self.strand_array[i] = strand
        insort_left(self.strand_heap, strand)
        if update_segments:
            self._part.refreshSegments(self._id_num)
Example #22
0
    def __init__(self,
                 strand: StrandT,
                 new_idxs: SegmentT,
                 update_segments: bool = True):
        super(ResizeCommand, self).__init__("resize strand")
        self.strand = strand
        self.old_indices = o_i = strand.idxs()
        self.new_idxs = new_idxs
        # an increase in length leads to positive delta
        self.delta = (new_idxs[1] - new_idxs[0]) - (o_i[1] - o_i[0])
        # now handle insertion deltas
        oldInsertions = strand.insertionsOnStrand(*o_i)
        newInsertions = strand.insertionsOnStrand(*new_idxs)
        o_l = 0
        for i in oldInsertions:
            o_l += i.length()
        n_l = 0
        for i in newInsertions:
            n_l += i.length()
        self.delta += (n_l - o_l)

        self.update_segments = update_segments
Example #23
0
    def strandHasNewOligoSlot(self, strand: StrandT):
        """Slot for changing the `Oligo` of the model `Strand`

        Args:
            strand:
        """
        strand = self._model_strand
        self._controller.reconnectOligoSignals()
        self._updateColor(strand)
        if strand.connection3p():
            self.xover_3p_end._updateColor(strand)
        for insertion in self.insertionItems().values():
            insertion.updateItem()
Example #24
0
    def _addToStrandList(self, strand: StrandT, update_segments: bool = True):
        """Inserts strand into the strand_array at idx

        Args:
            strand: the strand to add
            update_segments (optional): whether to signal default=``True``
        """
        idx_low, idx_high = strand.idxs()
        for i in range(idx_low, idx_high + 1):
            self.strand_array[i] = strand
        insort_left(self.strand_heap, strand)
        if update_segments:
            self._part.refreshSegments(self._id_num)
Example #25
0
    def strandHasNewOligoSlot(self, strand: StrandT):
        """Slot for changing the `Oligo` of the model `Strand`

        Args:
            strand:
        """
        strand = self._model_strand
        self._controller.reconnectOligoSignals()
        self._updateColor(strand)
        if strand.connection3p():
            self.xover_3p_end._updateColor(strand)
        for insertion in self.insertionItems().values():
            insertion.updateItem()
Example #26
0
 def updateForFloatFromStrand(self, virtual_helix_item: PathVirtualHelixItemT,
                                     strand3p: StrandT,
                                     idx: int):
     """
     Args:
         virtual_helix_item: Description
         strand3p: reference to the 3' strand
         idx: the base index within the virtual helix
     """
     self._vhi = virtual_helix_item
     self._strand = strand3p
     self.setParentItem(virtual_helix_item)
     self._idx = idx
     self._is_on_top = self.is_forward = strand3p.strandSet().isForward()
     self.updatePositionAndAppearance()
Example #27
0
    def _removeFromStrandList(self, strand: StrandT, update_segments: bool = True):
        """Remove strand from strand_array.

        Args:
            strand: the strand
            update_segments (optional): whether to signal default=``True``
        """
        self._document.removeStrandFromSelection(strand)  # make sure the strand is no longer selected
        idx_low, idx_high = strand.idxs()
        for i in range(idx_low, idx_high + 1):
            self.strand_array[i] = None
        i = bisect_left(self.strand_heap, strand)
        self.strand_heap.pop(i)
        if update_segments:
            self._part.refreshSegments(self._id_num)
Example #28
0
 def updateForFloatFromStrand(self,
                              virtual_helix_item: PathVirtualHelixItemT,
                              strand3p: StrandT, idx: int):
     """
     Args:
         virtual_helix_item: Description
         strand3p: reference to the 3' strand
         idx: the base index within the virtual helix
     """
     self._vhi = virtual_helix_item
     self._strand = strand3p
     self.setParentItem(virtual_helix_item)
     self._idx = idx
     self._is_on_top = self.is_forward = strand3p.strandSet().isForward()
     self.updatePositionAndAppearance()
Example #29
0
    def _removeFromStrandList(self, strand: StrandT, update_segments: bool = True):
        """Remove strand from strand_array.

        Args:
            strand: the strand
            update_segments (optional): whether to signal default=``True``
        """
        self._document.removeStrandFromSelection(strand)  # make sure the strand is no longer selected
        idx_low, idx_high = strand.idxs()
        for i in range(idx_low, idx_high + 1):
            self.strand_array[i] = None
        i = bisect_left(self.strand_heap, strand)
        self.strand_heap.pop(i)
        if update_segments:
            self._part.refreshSegments(self._id_num)
Example #30
0
    def oligoStrandRemover(self, strand: StrandT,
                                cmds: List[UndoCommand],
                                solo: bool = True):
        """Used for removing all :class:`Strand`s from an :class:`Oligo`

        Args:
            strand: a strand to remove
            cmds: a list of :class:`UndoCommand` objects to append to
            solo (:optional): to pass on to ``RemoveStrandCommand``,
            default=``True``
        """
        if not self.isStrandInSet(strand):
            raise IndexError("Strandset.oligoStrandRemover: strand not in set")
        cmds += strand.clearDecoratorCommands()
        cmds.append(RemoveStrandCommand(self, strand, solo=solo))
Example #31
0
    def oligoStrandRemover(self, strand: StrandT,
                                cmds: List[UndoCommand],
                                solo: bool = True):
        """Used for removing all :class:`Strand`s from an :class:`Oligo`

        Args:
            strand: a strand to remove
            cmds: a list of :class:`UndoCommand` objects to append to
            solo (:optional): to pass on to ``RemoveStrandCommand``,
            default=``True``
        """
        if not self.isStrandInSet(strand):
            raise IndexError("Strandset.oligoStrandRemover: strand not in set")
        cmds += strand.clearDecoratorCommands()
        cmds.append(RemoveStrandCommand(self, strand, solo=solo))
Example #32
0
 def _updateColor(self, strand: StrandT):
     oligo = strand.oligo()
     color = SELECT_COLOR if self.isSelected() else oligo.getColor()
     if oligo.shouldHighlight():
         alpha = 128
         pen_width = styles.PATH_STRAND_HIGHLIGHT_STROKE_WIDTH
     else:
         pen_width = styles.PATH_STRAND_STROKE_WIDTH
         alpha = None
     self.xover_3p_end._updateColor(strand)
     pen = getPenObj(color, pen_width, alpha=alpha, capstyle=Qt.FlatCap)
     brush = getBrushObj(color, alpha=alpha)
     self.setPen(pen)
     self._low_cap.updateHighlight(brush)
     self._high_cap.updateHighlight(brush)
     self._dual_cap.updateHighlight(brush)
Example #33
0
    def strandModsChangedSlot(self, strand: StrandT, document: DocT,
                              mod_id: str, idx: int):
        """Slot for changing a modification on the Strand

        Args:
            strand:
            document:
            mod_id:
            idx:
        """
        idx_l, idx_h = strand.idxs()
        color = document.getModProperties(mod_id)['color']
        if idx == idx_h:
            self._high_cap.changeMod(mod_id, color)
        else:
            self._low_cap.changeMod(mod_id, color)
Example #34
0
    def strandModsRemovedSlot(self, strand: StrandT, document: DocT,
                              mod_id: str, idx: int):
        """Slot for removing a modification on the Strand

        Args:
            strand:
            document:
            mod_id:
            idx:
        """
        idx_l, idx_h = strand.idxs()
        # color = document.getModProperties(mod_id)['color']
        if idx == idx_h:
            self._high_cap.destroyMod()
        else:
            self._low_cap.destroyMod()
Example #35
0
 def __init__(self,  virtual_helix_item: PathVirtualHelixItemT,
                     strand: StrandT,
                     insertion: InsertionT):
     super(InsertionItem, self).__init__(virtual_helix_item)
     self.hide()
     self._strand = strand
     self._insertion = insertion
     self._seq_item = QGraphicsPathItem(parent=self)
     self._is_on_top = is_on_top = strand.isForward()
     y = 0 if is_on_top else _BW
     self.setPos(_BW*insertion.idx(), y)
     self.setZValue(styles.ZINSERTHANDLE)
     self._initLabel()
     self._initClickArea()
     self.updateItem()
     self.show()
Example #36
0
 def _updateColor(self, strand: StrandT):
     oligo = strand.oligo()
     color = SELECT_COLOR if self.isSelected() else oligo.getColor()
     if oligo.shouldHighlight():
         alpha = 128
         pen_width = styles.PATH_STRAND_HIGHLIGHT_STROKE_WIDTH
     else:
         pen_width = styles.PATH_STRAND_STROKE_WIDTH
         alpha = None
     self.xover_3p_end._updateColor(strand)
     pen = getPenObj(color, pen_width, alpha=alpha, capstyle=Qt.FlatCap)
     brush = getBrushObj(color, alpha=alpha)
     self.setPen(pen)
     self._low_cap.updateHighlight(brush)
     self._high_cap.updateHighlight(brush)
     self._dual_cap.updateHighlight(brush)
Example #37
0
    def strandModsAddedSlot(self, strand: StrandT, document: DocT, mod_id: str,
                            idx: int):
        """Slot for adding a modification on the Strand

        Args:
            strand:
            document:
            mod_id:
            idx:
        """
        if self._viewroot.are_signals_on:
            idx_l, idx_h = strand.idxs()
            color = document.getModProperties(mod_id)['color']
            if idx == idx_h:
                self._high_cap.showMod(mod_id, color)
            else:
                self._low_cap.showMod(mod_id, color)
Example #38
0
    def strandModsChangedSlot(self, strand: StrandT,
                                document: DocT,
                                mod_id: str,
                                idx: int):
        """Slot for changing a modification on the Strand

        Args:
            strand:
            document:
            mod_id:
            idx:
        """
        idx_l, idx_h = strand.idxs()
        color = document.getModProperties(mod_id)['color']
        if idx == idx_h:
            self._high_cap.changeMod(mod_id, color)
        else:
            self._low_cap.changeMod(mod_id, color)
Example #39
0
    def strandModsRemovedSlot(self, strand: StrandT,
                                document: DocT,
                                mod_id: str,
                                idx: int):
        """Slot for removing a modification on the Strand

        Args:
            strand:
            document:
            mod_id:
            idx:
        """
        idx_l, idx_h = strand.idxs()
        # color = document.getModProperties(mod_id)['color']
        if idx == idx_h:
            self._high_cap.destroyMod()
        else:
            self._low_cap.destroyMod()
Example #40
0
    def strandModsAddedSlot(self, strand: StrandT,
                                document: DocT,
                                mod_id: str,
                                idx: int):
        """Slot for adding a modification on the Strand

        Args:
            strand:
            document:
            mod_id:
            idx:
        """
        if self._viewroot.are_signals_on:
            idx_l, idx_h = strand.idxs()
            color = document.getModProperties(mod_id)['color']
            if idx == idx_h:
                self._high_cap.showMod(mod_id, color)
            else:
                self._low_cap.showMod(mod_id, color)
Example #41
0
 def _updateColor(self, strand: StrandT):
     """
     Args:
         strand (TYPE): Description
     """
     oligo = strand.oligo()
     color = self.pen().color().name() if self.isSelected(
     ) else oligo.getColor()
     if color is None:
         print("None color:", color, self.isSelected())
         color = '#cc0000'
     if oligo.shouldHighlight():
         pen_width = styles.PATH_STRAND_HIGHLIGHT_STROKE_WIDTH
         alpha = 128
     else:
         pen_width = styles.PATH_STRAND_STROKE_WIDTH
         alpha = 255
     pen = getPenObj(color, pen_width, alpha=alpha, capstyle=Qt.FlatCap)
     self.setPen(pen)
Example #42
0
    def __init__(self, virtual_helix_item: PathVirtualHelixItemT,
                 xover_item: PathXoverItemT, strand3p: StrandT, idx: int):
        """
        Args:
            virtual_helix_item: Description
            xover_item: Description
            strand3p: reference to the 3' strand
            idx: the base index within the virtual helix
        """
        super(XoverNode3, self).__init__(virtual_helix_item)
        self._vhi = virtual_helix_item
        self._xover_item = xover_item
        self._idx = idx
        self.is_forward = strand3p.strandSet().isForward()

        self.setPartnerVirtualHelix(strand3p)

        self.setPen(getNoPen())
        self._label = None
        self.setBrush(_NO_BRUSH)
        self.setRect(_RECT)
        self.setZValue(styles.ZXOVERITEM)
Example #43
0
    def refreshInsertionItems(self, strand: StrandT):
        i_items = self.insertionItems()
        i_model = strand.insertionsOnStrand()

        was_in_use = set(i_items)
        in_use = set()
        # add in the ones supposed to be there
        for insertion in i_model:
            idx = insertion.idx()
            in_use.add(idx)
            if idx in i_items:
                pass
            else:
                i_items[insertion.idx()] = \
                    InsertionItem(self._virtual_helix_item, strand, insertion)
        # end for

        # remove all in items
        not_in_use = was_in_use - in_use
        for index in not_in_use:
            i_items[index].destroyItem()
            del i_items[index]
Example #44
0
    def refreshInsertionItems(self, strand: StrandT):
        i_items = self.insertionItems()
        i_model = strand.insertionsOnStrand()

        was_in_use = set(i_items)
        in_use = set()
        # add in the ones supposed to be there
        for insertion in i_model:
            idx = insertion.idx()
            in_use.add(idx)
            if idx in i_items:
                pass
            else:
                i_items[insertion.idx()] = \
                    InsertionItem(self._virtual_helix_item, strand, insertion)
        # end for

        # remove all in items
        not_in_use = was_in_use - in_use
        for index in not_in_use:
            i_items[index].destroyItem()
            del i_items[index]
Example #45
0
 def isStrandInSet(self, strand: StrandT) -> bool:
     sl = self.strand_array
     if sl[strand.lowIdx()] == strand and sl[strand.highIdx()] == strand:
         return True
     else:
         return False
Example #46
0
    def setComplementSequence(self, sequence: str, strand: StrandT) -> str:
        """This version takes anothers strand and only sets the indices that
        align with the given complimentary strand.

        As it depends which direction this is going, and strings are stored in
        memory left to right, we need to test for is_forward to map the
        reverse compliment appropriately, as we traverse overlapping strands.

        We reverse the sequence ahead of time if we are applying it 5' to 3',
        otherwise we reverse the sequence post parsing if it's 3' to 5'

        Again, sequences are stored as strings in memory 5' to 3' so we need
        to jump through these hoops to iterate 5' to 3' through them correctly

        Perhaps it's wiser to merely store them left to right and reverse them
        at draw time, or export time

        Args:
            sequence (str):
            strand (Strand):

        Returns:
            str: the used portion of the sequence
        """
        s_low_idx, s_high_idx = self._base_idx_low, self._base_idx_high
        c_low_idx, c_high_idx = strand.idxs()
        is_forward = self._is_forward
        self_seq = self._sequence
        # get the ovelap
        low_idx, high_idx = util.overlap(s_low_idx, s_high_idx, c_low_idx, c_high_idx)

        # only get the characters we're using, while we're at it, make it the
        # reverse compliment

        total_length = self.totalLength()

        # see if we are applying
        if sequence is None:
            # clear out string for in case of not total overlap
            use_seq = ''.join([' ' for x in range(total_length)])
        else:  # use the string as is
            use_seq = sequence[::-1] if is_forward else sequence

        temp = array(ARRAY_TYPE, sixb(use_seq))
        if self_seq is None:
            temp_self = array(ARRAY_TYPE, sixb(''.join([' ' for x in range(total_length)])))
        else:
            temp_self = array(ARRAY_TYPE, sixb(self_seq) if is_forward else sixb(self_seq[::-1]))

        # generate the index into the compliment string
        a = self.insertionLengthBetweenIdxs(s_low_idx, low_idx - 1)
        b = self.insertionLengthBetweenIdxs(low_idx, high_idx)
        c = strand.insertionLengthBetweenIdxs(c_low_idx, low_idx - 1)
        start = low_idx - c_low_idx + c
        end = start + b + high_idx - low_idx + 1
        temp_self[low_idx - s_low_idx + a:high_idx - s_low_idx + 1 + a + b] = temp[start:end]
        # print("old sequence", self_seq)
        self._sequence = tostring(temp_self)

        # if we need to reverse it do it now
        if not is_forward:
            self._sequence = self._sequence[::-1]

        # test to see if the string is empty(), annoyingly expensive
        # if len(self._sequence.strip()) == 0:
        if not self._sequence:
            self._sequence = None

        # print("new sequence", self._sequence)
        return self._sequence
Example #47
0
    def _updateAppearance(self, strand: StrandT):
        """Prepare Strand for drawing, positions are relative to the
        :class:`PathVirtualHelixItem`:

        1. Show or hide caps depending on L and R connectivity.
        2. Determine line coordinates.
        3. Apply paint styles.
        """
        # 0. Setup
        vhi = self._virtual_helix_item
        bw = _BASE_WIDTH
        half_base_width = bw / 2.0
        low_idx, high_idx = strand.lowIdx(), strand.highIdx()

        l_upper_left_x, l_upper_left_y = vhi.upperLeftCornerOfBase(
            low_idx, strand)
        h_upper_left_x, h_upper_left_y = vhi.upperLeftCornerOfBase(
            high_idx, strand)
        low_cap = self._low_cap
        high_cap = self._high_cap
        dual_cap = self._dual_cap

        # 1. Cap visibilty
        lx = l_upper_left_x + bw  # draw from right edge of base
        low_cap.safeSetPos(l_upper_left_x, l_upper_left_y)
        if strand.connectionLow() is not None:  # has low xover
            # if we are hiding it, we might as well make sure it is reparented to the StrandItem
            low_cap.restoreParent()
            low_cap.hide()
        else:  # has low cap
            if not low_cap.isVisible():
                low_cap.show()

        hx = h_upper_left_x  # draw to edge of base
        high_cap.safeSetPos(h_upper_left_x, h_upper_left_y)
        if strand.connectionHigh() is not None:  # has high xover
            # if we are hiding it, we might as well make sure it is reparented to the StrandItem
            high_cap.restoreParent()
            high_cap.hide()
        else:  # has high cap
            if not high_cap.isVisible():
                high_cap.show()

        # special case: single-base strand with no L or H connections,
        # (unconnected caps were made visible in previous block of code)
        if strand.length() == 1 and (low_cap.isVisible()
                                     and high_cap.isVisible()):
            low_cap.hide()
            high_cap.hide()
            dual_cap.safeSetPos(l_upper_left_x, l_upper_left_y)
            dual_cap.show()
        else:
            dual_cap.hide()

        # 2. Xover drawing
        xo = self.xover_3p_end
        if strand.connection3p():
            xo.update(strand)
            xo.showIt()
        else:
            xo.restoreParent()
            xo.hideIt()

        # 3. Refresh insertionItems if necessary drawing
        self.refreshInsertionItems(strand)

        # 4. Line drawing
        hy = ly = l_upper_left_y + half_base_width
        self.setLine(lx, ly, hx, hy)
        rectf = QRectF(l_upper_left_x + bw, l_upper_left_y,
                       bw * (high_idx - low_idx - 1), bw)
        self._click_area.setRect(rectf)
        self._updateColor(strand)
Example #48
0
 def isStrandInSet(self, strand: StrandT) -> bool:
     sl = self.strand_array
     if sl[strand.lowIdx()] == strand and sl[strand.highIdx()] == strand:
         return True
     else:
         return False
Example #49
0
    def _updateAppearance(self, strand: StrandT):
        """Prepare Strand for drawing, positions are relative to the
        :class:`PathVirtualHelixItem`:

        1. Show or hide caps depending on L and R connectivity.
        2. Determine line coordinates.
        3. Apply paint styles.
        """
        # 0. Setup
        vhi = self._virtual_helix_item
        bw = _BASE_WIDTH
        half_base_width = bw / 2.0
        low_idx, high_idx = strand.lowIdx(), strand.highIdx()

        l_upper_left_x, l_upper_left_y = vhi.upperLeftCornerOfBase(low_idx, strand)
        h_upper_left_x, h_upper_left_y = vhi.upperLeftCornerOfBase(high_idx, strand)
        low_cap = self._low_cap
        high_cap = self._high_cap
        dual_cap = self._dual_cap

        # 1. Cap visibilty
        lx = l_upper_left_x + bw  # draw from right edge of base
        low_cap.safeSetPos(l_upper_left_x, l_upper_left_y)
        if strand.connectionLow() is not None:  # has low xover
            # if we are hiding it, we might as well make sure it is reparented to the StrandItem
            low_cap.restoreParent()
            low_cap.hide()
        else:  # has low cap
            if not low_cap.isVisible():
                low_cap.show()

        hx = h_upper_left_x  # draw to edge of base
        high_cap.safeSetPos(h_upper_left_x, h_upper_left_y)
        if strand.connectionHigh() is not None:  # has high xover
            # if we are hiding it, we might as well make sure it is reparented to the StrandItem
            high_cap.restoreParent()
            high_cap.hide()
        else:  # has high cap
            if not high_cap.isVisible():
                high_cap.show()

        # special case: single-base strand with no L or H connections,
        # (unconnected caps were made visible in previous block of code)
        if strand.length() == 1 and (low_cap.isVisible() and high_cap.isVisible()):
            low_cap.hide()
            high_cap.hide()
            dual_cap.safeSetPos(l_upper_left_x, l_upper_left_y)
            dual_cap.show()
        else:
            dual_cap.hide()

        # 2. Xover drawing
        xo = self.xover_3p_end
        if strand.connection3p():
            xo.update(strand)
            xo.showIt()
        else:
            xo.restoreParent()
            xo.hideIt()

        # 3. Refresh insertionItems if necessary drawing
        self.refreshInsertionItems(strand)

        # 4. Line drawing
        hy = ly = l_upper_left_y + half_base_width
        self.setLine(lx, ly, hx, hy)
        rectf = QRectF(l_upper_left_x + bw, l_upper_left_y, bw*(high_idx - low_idx - 1), bw)
        self._click_area.setRect(rectf)
        self._updateColor(strand)
 def __init__(self, strand_item, model_strand: StrandT):
     self._model_strand = model_strand
     self._model_oligo = model_strand.oligo()
     self._strand_item = strand_item
     self.connectSignals()
 def __init__(self, strand_item, model_strand: StrandT):
     self._model_strand = model_strand
     self._model_oligo = model_strand.oligo()
     self._strand_item = strand_item
     self.connectSignals()