def baseAtPoint(self, virtual_helix_item, pt):
     """Returns the (strand_type, base_idx) corresponding
     to pt in virtual_helix_item."""
     x, strand_idx = self.helixIndex(pt)
     vh = virtual_helix_item.virtualHelix()
     if vh.isEvenParity():
         strand_type = (StrandType.SCAFFOLD, StrandType.STAPLE)[util.clamp(strand_idx, 0, 1)]
     else:
         strand_type = (StrandType.STAPLE, StrandType.SCAFFOLD)[util.clamp(strand_idx, 0, 1)]
     return (strand_type, x, strand_idx)
Example #2
0
 def baseAtPoint(self, virtual_helix_item, pt):
     """Returns the (strand_type, base_idx) corresponding
     to pt in virtual_helix_item."""
     x, strand_idx = self.helixIndex(pt)
     vh = virtual_helix_item.virtualHelix()
     if vh.isEvenParity():
         strand_type = (StrandType.SCAFFOLD,
                        StrandType.STAPLE)[util.clamp(strand_idx, 0, 1)]
     else:
         strand_type = (StrandType.STAPLE,
                        StrandType.SCAFFOLD)[util.clamp(strand_idx, 0, 1)]
     return (strand_type, x, strand_idx)
Example #3
0
 def attemptToCreateStrand(self, virtual_helix_item, strand_set, idx):
     self._temp_strand_item.hideIt()
     s_idx = self._start_idx
     if abs(s_idx - idx) > 1:
         idx = util.clamp(idx, self._low_drag_bound, self._high_drag_bound)
         idxs = (idx, s_idx) if self.isDragLow(idx) else (s_idx, idx)
         self._start_strand_set.createStrand(*idxs)
Example #4
0
 def attemptToCreateStrand(self, virtual_helix_item, strand_set, idx):
     self._temp_strand_item.hideIt()
     s_idx = self._start_idx
     if abs(s_idx - idx) > 1:
         idx = util.clamp(idx, self._low_drag_bound, self._high_drag_bound)
         idxs = (idx, s_idx) if self.isDragLow(idx) else (s_idx, idx)
         self._start_strand_set.createStrand(*idxs)
Example #5
0
 def selectToolMouseMove(self, modifiers, idx):
     """
     Given a new index (pre-validated as different from the prev index),
     calculate the new x coordinate for self, move there, and notify the
     parent strandItem to redraw its horizontal line.
     """
     idx = util.clamp(idx, self._low_drag_bound, self._high_drag_bound)
Example #6
0
 def selectToolMouseMove(self, modifiers, idx):
     """
     Given a new index (pre-validated as different from the prev index),
     calculate the new x coordinate for self, move there, and notify the
     parent strandItem to redraw its horizontal line.
     """
     idx = util.clamp(idx, self._low_drag_bound, self._high_drag_bound)
 def safeScale(self, delta):
     current_scale_level = self.transform().m11()
     scale_factor = 1 + delta * (self._scale_down_rate if delta < 0 else self._scale_up_rate) * \
         (app().prefs.zoom_speed/100.)
     new_scale_level = current_scale_level * scale_factor
     new_scale_level = util.clamp(current_scale_level * scale_factor, self._scale_limit_min, self._scale_limit_max)
     scale_change = new_scale_level / current_scale_level
     self.scale(scale_change, scale_change)
     self._resetLOD()
Example #8
0
 def safeScale(self, delta: float):
     current_scale_level = self.transform().m11()
     scale_factor = 1 + delta * (self._scale_down_rate if delta < 0 else self._scale_up_rate) * \
         (app().prefs.zoom_speed/100.)
     new_scale_level = current_scale_level * scale_factor
     new_scale_level = util.clamp(current_scale_level * scale_factor, self._scale_limit_min, self._scale_limit_max)
     scale_change = new_scale_level / current_scale_level
     self.scale(scale_change, scale_change)
     self._resetLOD()
Example #9
0
 def updateIndexSlot(self, part, base_index):
     """The slot that receives active slice changed notifications from
     the part and changes the receiver to reflect the part"""
     label = self._label
     bw = _BASE_WIDTH
     bi = util.clamp(int(base_index), 0, self.part().maxBaseIdx())
     self.setPos(bi * bw, -styles.PATH_HELIX_PADDING)
     self._active_slice = bi
     if label:
         label.setText("%d" % bi)
         label.setX((bw - label.boundingRect().width()) / 2)
Example #10
0
 def updateIndexSlot(self, part, base_index):
     """The slot that receives active slice changed notifications from
     the part and changes the receiver to reflect the part"""
     label = self._label
     bw = _BASE_WIDTH
     bi = util.clamp(int(base_index), 0, self.part().maxBaseIdx())
     self.setPos(bi * bw, -styles.PATH_HELIX_PADDING)
     self._active_slice = bi
     if label:
         label.setText("%d" % bi)
         label.setX((bw - label.boundingRect().width()) / 2)
Example #11
0
    def baseAtPoint(self, virtual_helix_item, pt):
        """Returns the (is_fwd, base_idx, strand_idx) corresponding
        to pt in virtual_helix_item.

        Args:
            virtual_helix_item (cadnano.gui.views.pathview.virtualhelixitem.VirtualHelixItem): Description
            pt (TYPE): Description
        """
        x, strand_idx = self.helixIndex(pt)

        is_fwd = False if util.clamp(strand_idx, 0, 1) else True
        return (is_fwd, x, strand_idx)
Example #12
0
    def baseAtPoint(self, virtual_helix_item, pt):
        """Returns the (is_fwd, base_idx, strand_idx) corresponding
        to pt in virtual_helix_item.

        Args:
            virtual_helix_item (cadnano.views.pathview.virtualhelixitem.VirtualHelixItem): Description
            pt (TYPE): Description
        """
        x, strand_idx = self.helixIndex(pt)

        is_fwd = False if util.clamp(strand_idx, 0, 1) else True
        return (is_fwd, x, strand_idx)
Example #13
0
    def baseAtPoint(self, pos):
        """
        Returns the (strand_type, index) under the location x,y or None.

        It shouldn't be possible to click outside a pathhelix and still call
        this function. However, this sometimes happens if you click exactly
        on the top or bottom edge, resulting in a negative y value.
        """
        x, y = pos.x(), pos.y()
        mVH = self._model_virtual_helix
        base_idx = int(floor(x / _BASE_WIDTH))
        min_base, max_base = 0, mVH.part().maxBaseIdx()
        if base_idx < min_base or base_idx >= max_base:
            base_idx = util.clamp(base_idx, min_base, max_base)
        if y < 0:
            y = 0  # HACK: zero out y due to erroneous click
        strandIdx = floor(y * 1. / _BASE_WIDTH)
        if strandIdx < 0 or strandIdx > 1:
            strandIdx = int(util.clamp(strandIdx, 0, 1))
        strand_set = mVH.getStrandSetByIdx(strandIdx)
        return (strand_set, base_idx)
Example #14
0
 def selectToolMouseMove(self, modifiers, idx):
     """
     Given a new index (pre-validated as different from the prev index),
     calculate the new x coordinate for self, move there, and notify the
     parent strandItem to redraw its horizontal line.
     """
     idx = util.clamp(idx, self._low_drag_bound, self._high_drag_bound)
     x = int(idx * _BASE_WIDTH)
     self.setPos(x, self.y())
     self.updateIndexSlot(None, idx)
     self._setActiveBaseIndex(idx)
     self._part_item.updateStatusBar("%d" % self.part().activeBaseIndex())
Example #15
0
 def selectToolMouseMove(self, modifiers, idx):
     """
     Given a new index (pre-validated as different from the prev index),
     calculate the new x coordinate for self, move there, and notify the
     parent strandItem to redraw its horizontal line.
     """
     idx = util.clamp(idx, self._low_drag_bound, self._high_drag_bound)
     x = int(idx * _BASE_WIDTH)
     self.setPos(x, self.y())
     self.updateIndexSlot(None, idx)
     self._setActiveBaseIndex(idx)
     self._part_item.updateStatusBar("%d" % self.part().activeBaseIndex())
    def baseAtPoint(self, virtual_helix_item: PathVirtualHelixItemT,
                    pt: QPointF) -> Tuple[bool, int, int]:
        """Returns the ``(is_fwd, base_idx, strand_idx)`` corresponding
        to pt in virtual_helix_item.

        Args:
            virtual_helix_item: :class:`PathVirtualHelixItem`
            pt: Point on helix
        """
        x, strand_idx = self.helixIndex(pt)

        is_fwd = False if util.clamp(strand_idx, 0, 1) else True
        return (is_fwd, x, strand_idx)
Example #17
0
    def baseAtPoint(self, virtual_helix_item: PathVirtualHelixItemT,
                        pt: QPointF) -> Tuple[bool, int, int]:
        """Returns the ``(is_fwd, base_idx, strand_idx)`` corresponding
        to pt in virtual_helix_item.

        Args:
            virtual_helix_item: :class:`PathVirtualHelixItem`
            pt: Point on helix
        """
        x, strand_idx = self.helixIndex(pt)

        is_fwd = False if util.clamp(strand_idx, 0, 1) else True
        return (is_fwd, x, strand_idx)
Example #18
0
    def baseAtPoint(self, pos: QPointF) -> Tuple[StrandSetT, int]:
        """Returns the (Strandset, index) under the location x, y or None.

        It shouldn't be possible to click outside a pathhelix and still call
        this function. However, this sometimes happens if you click exactly
        on the top or bottom edge, resulting in a negative y value.

        Args:
            pos: Description
        """
        x, y = pos.x(), pos.y()
        part = self._model_part
        id_num = self._id_num
        base_idx = int(floor(x / _BASE_WIDTH))
        min_base, max_base = 0, part.maxBaseIdx(id_num)
        if base_idx < min_base or base_idx >= max_base:
            base_idx = util.clamp(base_idx, min_base, max_base)
        if y < 0:
            y = 0  # HACK: zero out y due to erroneous click
        strand_type = floor(y * 1. / _BASE_WIDTH)   # 0 for fwd, 1 for rev
        strand_type = int(util.clamp(strand_type, 0, 1))
        strand_set = part.getStrandSets(id_num)[strand_type]
        return (strand_set, base_idx)
    def baseAtPoint(self, pos: QPointF) -> Tuple[StrandSetT, int]:
        """Returns the (Strandset, index) under the location x, y or None.

        It shouldn't be possible to click outside a pathhelix and still call
        this function. However, this sometimes happens if you click exactly
        on the top or bottom edge, resulting in a negative y value.

        Args:
            pos: Description
        """
        x, y = pos.x(), pos.y()
        part = self._model_part
        id_num = self._id_num
        base_idx = int(floor(x / _BASE_WIDTH))
        min_base, max_base = 0, part.maxBaseIdx(id_num)
        if base_idx < min_base or base_idx >= max_base:
            base_idx = util.clamp(base_idx, min_base, max_base)
        if y < 0:
            y = 0  # HACK: zero out y due to erroneous click
        strand_type = floor(y * 1. / _BASE_WIDTH)  # 0 for fwd, 1 for rev
        strand_type = int(util.clamp(strand_type, 0, 1))
        strand_set = part.getStrandSets(id_num)[strand_type]
        return (strand_set, base_idx)
Example #20
0
 def mouseMoveEvent(self, event: QGraphicsSceneMouseEvent):
     """Converts event coords into an idx delta and updates if changed.
     """
     delta = int(floor((self.x()+event.pos().x()) / BASE_WIDTH)) - self._offset_idx
     delta = util.clamp(delta,
                        self._low_drag_bound-self._start_idx_low,
                        self._high_drag_bound-self._start_idx_high+self.width())
     if self._delta != delta:
         self._idx_low = int(self._start_idx_low + delta)
         self._idx_high = int(self._start_idx_high + delta)
         self._delta = delta
         self.reconfigureRect((), ())
         self.resize_handle_group.updateText(HandleEnum.LEFT, self._idx_low)
         self.resize_handle_group.updateText(HandleEnum.RIGHT, self._idx_high)
     return QGraphicsItem.mouseMoveEvent(self, event)
Example #21
0
 def mouseReleaseEvent(self, event: QGraphicsSceneMouseEvent):
     """Repeates mouseMove calculation in case any new movement.
     """
     self.setCursor(Qt.ArrowCursor)
     delta = int(floor((self.x()+event.pos().x()) / BASE_WIDTH)) - self._offset_idx
     delta = util.clamp(delta,
                        self._low_drag_bound-self._start_idx_low,
                        self._high_drag_bound-self._start_idx_high+self.width())
     if self._delta != delta:
         self._idx_low = int(self._start_idx_low + delta)
         self._idx_high = int(self._start_idx_high + delta)
         self._delta = delta
         self.reconfigureRect((), ())
     self._high_drag_bound = self._model_part.getProperty('max_vhelix_length')  # reset for handles
     return QGraphicsItem.mouseReleaseEvent(self, event)
Example #22
0
 def mouseReleaseEvent(self, event):
     """
     Repeates mouseMove calculation in case any new movement.
     """
     self.setCursor(Qt.ArrowCursor)
     delta = int(floor((self.x()+event.pos().x()) / BASE_WIDTH)) - self._offset_idx
     delta = util.clamp(delta,
                        self._low_drag_bound-self._start_idx_low,
                        self._high_drag_bound-self._start_idx_high+self.width())
     if self._delta != delta:
         self._idx_low = int(self._start_idx_low + delta)
         self._idx_high = int(self._start_idx_high + delta)
         self._delta = delta
         self.reconfigureRect((), ())
     self._high_drag_bound = self._model_part.getProperty('max_vhelix_length')  # reset for handles
Example #23
0
 def mouseMoveEvent(self, event):
     """
     Converts event coords into an idx delta and updates if changed.
     """
     delta = int(floor((self.x()+event.pos().x()) / BASE_WIDTH)) - self._offset_idx
     delta = util.clamp(delta,
                        self._low_drag_bound-self._start_idx_low,
                        self._high_drag_bound-self._start_idx_high+self.width())
     if self._delta != delta:
         self._idx_low = int(self._start_idx_low + delta)
         self._idx_high = int(self._start_idx_high + delta)
         self._delta = delta
         self.reconfigureRect((), ())
         self.resize_handle_group.updateText(HandleType.LEFT, self._idx_low)
         self.resize_handle_group.updateText(HandleType.RIGHT, self._idx_high)
Example #24
0
    def attemptToCreateStrand(self, virtual_helix_item, strand_set, idx):
        """Attempt to create a new strand within the VHI `strand_set` with
        bounds of the original mouse press index (stored as `self._start_idx`)
        and the mouse release index `idx`.

        Args:
            virtual_helix_item (cadnano.gui.views.pathview.virtualhelixitem.VirtualHelixItem): from vhi
            strand_set (StrandSet): Description
            idx (int): mouse release index
        """
        self._temp_strand_item.hideIt()
        s_idx = self._start_idx
        if abs(s_idx - idx) > 1:
            idx = util.clamp(idx, self._low_drag_bound, self._high_drag_bound)
            idxs = (idx, s_idx) if self.isDragLow(idx) else (s_idx, idx)
            self._start_strand_set.createStrand(*idxs)
Example #25
0
    def attemptToCreateStrand(self, virtual_helix_item, strand_set, idx):
        """Attempt to create a new strand within the VHI `strand_set` with
        bounds of the original mouse press index (stored as `self._start_idx`)
        and the mouse release index `idx`.

        Args:
            virtual_helix_item (cadnano.views.pathview.virtualhelixitem.VirtualHelixItem): from vhi
            strand_set (StrandSet): Description
            idx (int): mouse release index
        """
        self._temp_strand_item.hideIt()
        s_idx = self._start_idx
        if abs(s_idx - idx) > 1:
            idx = util.clamp(idx, self._low_drag_bound, self._high_drag_bound)
            idxs = (idx, s_idx) if self.isDragLow(idx) else (s_idx, idx)
            self._start_strand_set.createStrand(*idxs)
Example #26
0
 def _removeBasesClicked(self):
     """
     Determines the minimum maxBase index where index modulo stepsize == 0
     and is to the right of the rightmost nonempty base, and then resize
     each calls the resizeVirtualHelices to adjust to that size.
     """
     part = self._model_part
     step_size = part.stepSize()
     # first find out the right edge of the part
     idx = part.indexOfRightmostNonemptyBase()
     # next snap to a multiple of stepsize
     idx = ceil((idx + 1) / step_size) * step_size
     # finally, make sure we're a minimum of step_size bases
     idx = util.clamp(idx, step_size, 10000)
     delta = idx - (part.maxBaseIdx() + 1)
     if delta < 0:
         part.resizeVirtualHelices(0, delta)
Example #27
0
    def attemptToCreateStrand(self, virtual_helix_item: PathVirtualHelixItemT,
                              strand_set: StrandSetT, idx: int):
        """Attempt to create a new strand within the VHI ``strand_set`` with
        bounds of the original mouse press index (stored as ``self._start_idx``)
        and the mouse release index ``idx``.

        Args:
            virtual_helix_item: from vhi
            strand_set: Description
            idx: mouse release index
        """
        self._temp_strand_item.hideIt()
        s_idx = self._start_idx
        if abs(s_idx - idx) > 1:
            idx = util.clamp(idx, self._low_drag_bound, self._high_drag_bound)
            idxs = (idx, s_idx) if self.isDragLow(idx) else (s_idx, idx)
            self._start_strand_set.createStrand(*idxs)
Example #28
0
 def _removeBasesClicked(self):
     """
     Determines the minimum maxBase index where index modulo stepsize == 0
     and is to the right of the rightmost nonempty base, and then resize
     each calls the resizeVirtualHelices to adjust to that size.
     """
     part = self._model_part
     step_size = part.stepSize()
     # first find out the right edge of the part
     idx = part.indexOfRightmostNonemptyBase()
     # next snap to a multiple of stepsize
     idx = ceil((idx + 1) / step_size)*step_size
     # finally, make sure we're a minimum of step_size bases
     idx = util.clamp(idx, step_size, 10000)
     delta = idx - (part.maxBaseIdx() + 1)
     if delta < 0:
         part.resizeVirtualHelices(0, delta)
Example #29
0
    def reconfigureRect(self,
                        top_left: Vec2T,
                        bottom_right: Vec2T,
                        finish: bool = False) -> QRectF:
        """Update the workplane rect to draw from top_left to bottom_right,
        snapping the x values to the nearest base width. Updates the outline
        and resize handles.

        Args:
            top_left: topLeft (x, y)
            bottom_right: bottomRight (x, y)

        Returns:
            the new rect.
        """
        if top_left:
            xTL = max(top_left[0], self._low_drag_bound)
            xTL = xTL - (xTL % BASE_WIDTH)  # snap to nearest base
            self._idx_low = int(xTL / BASE_WIDTH)
            self.resize_handle_group.updateText(HandleEnum.LEFT, self._idx_low)
        else:
            xTL = self._idx_low * BASE_WIDTH

        if bottom_right:
            xBR = util.clamp(bottom_right[0],
                             (self._idx_low + self._MIN_WIDTH) * BASE_WIDTH,
                             (self._high_drag_bound) * BASE_WIDTH)
            xBR = xBR - (xBR % BASE_WIDTH)  # snap to nearest base
            self._idx_high = int(xBR / BASE_WIDTH)
            self.resize_handle_group.updateText(HandleEnum.RIGHT,
                                                self._idx_high)
        else:
            xBR = self._idx_high * BASE_WIDTH

        yTL = self._part_item._vh_rect.top()
        yBR = self._part_item._vh_rect.bottom() - BASE_WIDTH * 3

        self.setRect(QRectF(QPointF(xTL, yTL), QPointF(xBR, yBR)))
        self.outline.setRect(self.rect())
        self.outline.updateAppearance()
        self.resize_handle_group.alignHandles(self.rect())
        self._model_part.setProperty('workplane_idxs',
                                     (self._idx_low, self._idx_high),
                                     use_undostack=False)
        return self.rect()
Example #30
0
    def attemptToCreateStrand(self, virtual_helix_item: PathVirtualHelixItemT,
                                    strand_set: StrandSetT,
                                    idx: int):
        """Attempt to create a new strand within the VHI ``strand_set`` with
        bounds of the original mouse press index (stored as ``self._start_idx``)
        and the mouse release index ``idx``.

        Args:
            virtual_helix_item: from vhi
            strand_set: Description
            idx: mouse release index
        """
        self._temp_strand_item.hideIt()
        s_idx = self._start_idx
        if abs(s_idx - idx) > 1:
            idx = util.clamp(idx, self._low_drag_bound, self._high_drag_bound)
            idxs = (idx, s_idx) if self.isDragLow(idx) else (s_idx, idx)
            self._start_strand_set.createStrand(*idxs)
Example #31
0
    def reconfigureRect(self,   top_left: Vec2T,
                                bottom_right: Vec2T,
                                finish: bool = False) -> QRectF:
        """Update the workplane rect to draw from top_left to bottom_right,
        snapping the x values to the nearest base width. Updates the outline
        and resize handles.

        Args:
            top_left: topLeft (x, y)
            bottom_right: bottomRight (x, y)

        Returns:
            the new rect.
        """
        if top_left:
            xTL = max(top_left[0], self._low_drag_bound)
            xTL = xTL - (xTL % BASE_WIDTH)  # snap to nearest base
            self._idx_low = int(xTL/BASE_WIDTH)
            self.resize_handle_group.updateText(HandleEnum.LEFT, self._idx_low)
        else:
            xTL = self._idx_low*BASE_WIDTH

        if bottom_right:
            xBR = util.clamp(bottom_right[0],
                             (self._idx_low+self._MIN_WIDTH)*BASE_WIDTH,
                             (self._high_drag_bound)*BASE_WIDTH)
            xBR = xBR - (xBR % BASE_WIDTH)  # snap to nearest base
            self._idx_high = int(xBR/BASE_WIDTH)
            self.resize_handle_group.updateText(HandleEnum.RIGHT, self._idx_high)
        else:
            xBR = self._idx_high*BASE_WIDTH

        yTL = self._part_item._vh_rect.top()
        yBR = self._part_item._vh_rect.bottom()-BASE_WIDTH*3

        self.setRect(QRectF(QPointF(xTL, yTL), QPointF(xBR, yBR)))
        self.outline.setRect(self.rect())
        self.outline.updateAppearance()
        self.resize_handle_group.alignHandles(self.rect())
        self._model_part.setProperty('workplane_idxs', (self._idx_low, self._idx_high), use_undostack=False)
        return self.rect()