예제 #1
0
    def shortestPathXY(start, end, neighbor_map, vh_set, point_map, grid_type,
                       scale_factor, radius):
        # TODO[NF]:  Docstring
        x_y_path = []
        coordinate_path = ShortestPathHelper.shortestPathAStar(
            start=start,
            end=end,
            neighbor_map=neighbor_map,
            vh_set=vh_set,
            point_map=point_map)
        for node in coordinate_path:
            row = -node[0]
            column = node[1]
            if grid_type is GridType.HONEYCOMB:
                parity = 0 if HoneycombDnaPart.isOddParity(
                    row=row, column=column) else 1
                node_pos = HoneycombDnaPart.latticeCoordToPositionXY(
                    radius=radius,
                    row=row,
                    column=column,
                    scale_factor=scale_factor)
            else:
                parity = None
                node_pos = SquareDnaPart.latticeCoordToPositionXY(
                    radius=radius,
                    row=row,
                    column=column,
                    scale_factor=scale_factor)
            x_y_path.append((node_pos[0], node_pos[1], parity))

        return x_y_path
예제 #2
0
 def shortestPathXY(start, end, vh_set, grid_type, scale_factor,
                    part_radius):
     # TODO[NF]:  Docstring
     assert part_radius == DEFAULT_RADIUS
     x_y_path = []
     coordinate_path = ShortestPathHelper.shortestPathAStar(
         start=start,
         end=end,
         vh_set=vh_set,
         part_radius=part_radius,
         grid_type=grid_type,
         scale_factor=scale_factor)
     for node in coordinate_path:
         row = -node[0]
         column = node[1]
         if grid_type is GridEnum.HONEYCOMB:
             parity = 0 if HoneycombDnaPart.isEvenParity(
                 row=row, column=column) else 1
             node_pos = HoneycombDnaPart.latticeCoordToModelXY(
                 radius=part_radius, row=row, column=column)
         else:
             parity = None
             node_pos = SquareDnaPart.latticeCoordToModelXY(
                 radius=part_radius, row=row, column=column)
         x_y_path.append((node_pos[0], node_pos[1], parity))
     return x_y_path
예제 #3
0
def determineLatticeType(part_dict: dict) -> EnumType:
    """Guess the lattice type based on the sum of the vector distances between
    VHs and the closest lattice position.


    Args:
        part_dict:  the ``dict`` corresponding to the part to be imported

    Returns:
        ``GridEnum.HONEYCOMB`` or ``GridEnum.SQUARE`` or ``GridEnum.NONE``
    """
    grid_type = part_dict.get('grid_type')
    if grid_type is not None:
        return grid_type

    vh_id_list = part_dict.get('vh_list')
    origins = part_dict.get('origins')

    square_delta_x = 0.
    square_delta_y = 0.

    honeycomb_delta_x = 0.
    honeycomb_delta_y = 0.

    for vh_id, _ in vh_id_list:
        vh_x, vh_y = origins[vh_id]
        hcd, honeycomb_guess_coordinates = HoneycombDnaPart.distanceFromClosestLatticeCoord(
            DEFAULT_RADIUS, vh_x, vh_y)
        sqd, square_guess_coordinates = SquareDnaPart.distanceFromClosestLatticeCoord(
            DEFAULT_RADIUS, vh_x, vh_y)

        honeycomb_guess_x, honeycomb_guess_y = HoneycombDnaPart.latticeCoordToQtXY(
            DEFAULT_RADIUS, honeycomb_guess_coordinates[0],
            honeycomb_guess_coordinates[1])
        square_guess_x, square_guess_y = SquareDnaPart.latticeCoordToQtXY(
            DEFAULT_RADIUS, square_guess_coordinates[0],
            square_guess_coordinates[1])

        honeycomb_delta_x += (vh_x - honeycomb_guess_x)
        honeycomb_delta_y += (vh_y - honeycomb_guess_y)

        square_delta_x += (vh_x - square_guess_x)
        square_delta_y += (vh_y - square_guess_y)

    sum_honeycomb_distance = (honeycomb_delta_x**2 + honeycomb_delta_y**2)**0.5
    sum_square_distance = (square_delta_x**2 + square_delta_y**2)**0.5

    if abs(sum_honeycomb_distance) < abs(sum_square_distance):
        return GridEnum.HONEYCOMB
    else:
        return GridEnum.SQUARE
예제 #4
0
def determineLatticeType(part_dict: dict) -> EnumType:
    """Guess the lattice type based on the sum of the vector distances between
    VHs and the closest lattice position.


    Args:
        part_dict:  the ``dict`` corresponding to the part to be imported

    Returns:
        ``GridEnum.HONEYCOMB`` or ``GridEnum.SQUARE`` or ``GridEnum.NONE``
    """
    grid_type = part_dict.get('grid_type')
    if grid_type is not None:
        return grid_type

    vh_id_list = part_dict.get('vh_list')
    origins = part_dict.get('origins')

    square_delta_x = 0.
    square_delta_y = 0.

    honeycomb_delta_x = 0.
    honeycomb_delta_y = 0.

    for vh_id, _ in vh_id_list:
        vh_x, vh_y = origins[vh_id]
        hcd, honeycomb_guess_coordinates = HoneycombDnaPart.distanceFromClosestLatticeCoord(DEFAULT_RADIUS, vh_x, vh_y)
        sqd, square_guess_coordinates = SquareDnaPart.distanceFromClosestLatticeCoord(DEFAULT_RADIUS, vh_x, vh_y)

        honeycomb_guess_x, honeycomb_guess_y = HoneycombDnaPart.latticeCoordToQtXY(DEFAULT_RADIUS,
                                                                                   honeycomb_guess_coordinates[0],
                                                                                   honeycomb_guess_coordinates[1])
        square_guess_x, square_guess_y = SquareDnaPart.latticeCoordToQtXY(DEFAULT_RADIUS,
                                                                          square_guess_coordinates[0],
                                                                          square_guess_coordinates[1])

        honeycomb_delta_x += (vh_x - honeycomb_guess_x)
        honeycomb_delta_y += (vh_y - honeycomb_guess_y)

        square_delta_x += (vh_x - square_guess_x)
        square_delta_y += (vh_y - square_guess_y)

    sum_honeycomb_distance = (honeycomb_delta_x**2 + honeycomb_delta_y**2)**0.5
    sum_square_distance = (square_delta_x**2 + square_delta_y**2)**0.5

    if abs(sum_honeycomb_distance) < abs(sum_square_distance):
        return GridEnum.HONEYCOMB
    else:
        return GridEnum.SQUARE
예제 #5
0
    def showCreateHint(self,
                       coord,
                       next_idnums=(0, 1),
                       show_hint=True,
                       color=None):
        point_item = self.points_dict.get(coord, None)
        if point_item is None:
            return

        if show_hint is False:
            point_item.showCreateHint(show_hint=False)

        if point_item:
            row, column = coord
            if self.grid_type is GridType.HONEYCOMB:
                parity = 0 if HoneycombDnaPart.isOddParity(
                    row=row, column=column) else 1
            elif self.grid_type is GridType.SQUARE:
                parity = 0 if SquareDnaPart.isEvenParity(row=row,
                                                         column=column) else 1
            else:
                return
            id_num = next_idnums[1] if parity else next_idnums[0]
            point_item.showCreateHint(id_num=id_num,
                                      show_hint=show_hint,
                                      color=color)
            return parity == 1
예제 #6
0
    def showCreateHint(self,
                       coord: Tuple[int, int],
                       next_idnums: Tuple[int, int] = (0, 1),
                       show_hint: bool = True,
                       color: str = None) -> Optional[bool]:
        point_item = self.points_dict.get(coord)
        if point_item is None:
            return

        if not show_hint:
            point_item.showCreateHint(show_hint=False)

        if point_item:
            row, column = coord
            if self.grid_type is GridEnum.HONEYCOMB:
                parity = 0 if HoneycombDnaPart.isEvenParity(
                    row=row, column=column) else 1
            elif self.grid_type is GridEnum.SQUARE:
                parity = 0 if SquareDnaPart.isEvenParity(row=row,
                                                         column=column) else 1
            else:
                return
            id_num = next_idnums[1] if parity else next_idnums[0]
            point_item.showCreateHint(id_num=id_num,
                                      show_hint=show_hint,
                                      color=color)
            return parity == 1
예제 #7
0
 def _getCoordinateParity(self, row, column):
     if self.griditem.grid_type is GridType.HONEYCOMB:
         return 0 if HoneycombDnaPart.isOddParity(row=row, column=column) else 1
     elif self.griditem.grid_type is GridType.SQUARE:
         return 0 if SquareDnaPart.isEvenParity(row=row, column=column) else 1
     else:
         return None
예제 #8
0
 def _getModelXYforCoord(self, row, column):
     radius = DEFAULT_RADIUS
     if self.griditem.grid_type is GridType.HONEYCOMB:
         return HoneycombDnaPart.latticeCoordToQtXY(radius, row, column)
     elif self.griditem.grid_type is GridType.SQUARE:
         return SquareDnaPart.latticeCoordToQtXY(radius, row, column)
     else:
         return None
예제 #9
0
 def getNeighborsForCoordinate(grid_type, row, column):
     # TODO[NF]:  Docstring
     if grid_type is GridEnum.HONEYCOMB:
         if not HoneycombDnaPart.isEvenParity(row, column):
             return ((row + 1, column), (row, column - 1), (row,
                                                            column + 1))
         else:
             return ((row - 1, column), (row, column + 1), (row,
                                                            column - 1))
     elif grid_type is GridEnum.SQUARE:
         return ((row, column + 1), (row, column - 1), (row - 1, column),
                 (row + 1, column))
     else:
         return ()
예제 #10
0
    def partVirtualHelixAddedSlot(self, sender, id_num, virtual_helix,
                                  neighbors):
        """Summary

        Args:
            sender (obj): Model object that emitted the signal.
            id_num (int): VirtualHelix ID number. See `NucleicAcidPart` for description and related methods.
            neighbors (TYPE): Description

        Args:
            TYPE: Description
        """
        #        print('[NAPI] ADDED SLOT CALLED ON VH %s; called by %s' % (id_num, sender))
        vhi = SliceVirtualHelixItem(virtual_helix, self)
        self._virtual_helix_item_hash[id_num] = vhi
        self._refreshVirtualHelixItemGizmos(id_num, vhi)
        for neighbor_id in neighbors:
            nvhi = self._virtual_helix_item_hash.get(neighbor_id, False)
            if nvhi:
                self._refreshVirtualHelixItemGizmos(neighbor_id, nvhi)
        self.enlargeRectToFit()

        position = sender.locationQt(id_num=id_num,
                                     scale_factor=self.scale_factor)

        if self.griditem.grid_type is GridType.HONEYCOMB:
            coordinates = HoneycombDnaPart.positionModelToLatticeCoord(
                DEFAULT_RADIUS,
                position[0],
                position[1],
                scale_factor=self.scale_factor)
        else:
            coordinates = SquareDnaPart.positionModelToLatticeCoord(
                DEFAULT_RADIUS,
                position[0],
                position[1],
                scale_factor=self.scale_factor)

        assert id_num not in self.coordinates_to_vhid.values()
        if coordinates in self.coordinates_to_vhid.values():
            print('COORDINATES DUPLICATE %s in %s' %
                  (coordinates, self.coordinates_to_vhid.values()))

        self.coordinates_to_vhid[coordinates] = id_num

        assert len(self.coordinates_to_vhid.keys()) == len(
            set(self.coordinates_to_vhid.keys()))
        assert len(self.coordinates_to_vhid.values()) == len(
            set(self.coordinates_to_vhid.values()))
예제 #11
0
def determineSliceViewType(document, part_dict, grid_type):
    THRESHOLD = 0.0005
    vh_id_list = part_dict.get('vh_list')
    origins = part_dict.get('origins')

    for vh_id, size in vh_id_list:
        vh_x, vh_y = origins[vh_id]

        if grid_type is GridType.HONEYCOMB:
            distance, point = HoneycombDnaPart.distanceFromClosestLatticeCoord(vh_x, vh_y, DEFAULT_RADIUS)
            if distance > THRESHOLD:
                return SliceViewType.GRID
        elif grid_type is GridType.SQUARE:
            if SquareDnaPart.distanceFromClosestLatticeCoord(vh_x, vh_y, DEFAULT_RADIUS)[0] > THRESHOLD:
                return SliceViewType.GRID
    return SliceViewType.SLICE
예제 #12
0
def determineOrthoViewType(part_dict: dict, grid_type: EnumType):
    THRESHOLD = 0.0005
    vh_id_list = part_dict.get('vh_list')
    origins = part_dict.get('origins')

    for vh_id, size in vh_id_list:
        vh_x, vh_y = origins[vh_id]

        if grid_type == GridEnum.HONEYCOMB:
            distance, point = HoneycombDnaPart.distanceFromClosestLatticeCoord(
                radius=DEFAULT_RADIUS, x=vh_x, y=vh_y)
            if distance > THRESHOLD:
                return OrthoViewEnum.GRID
        elif grid_type == GridEnum.SQUARE:
            if SquareDnaPart.distanceFromClosestLatticeCoord(
                    radius=DEFAULT_RADIUS, x=vh_x, y=vh_y)[0] > THRESHOLD:
                return OrthoViewEnum.GRID
    return OrthoViewEnum.GRID
예제 #13
0
def testCreateVirtualHelixGui(cnapp):
    """Create some VHs"""
    # Create a new Honeycomb part
    toolbar = cnapp.window.main_toolbar
    action_new_honeycomb = toolbar.widgetForAction(
        cnapp.window.action_new_dnapart_honeycomb)
    QTest.mouseClick(action_new_honeycomb, Qt.LeftButton, delay=DELAY)

    slicerootitem = cnapp.window.slice_root
    assert len(slicerootitem.instance_items) == 1
    slice_part_item = list(slicerootitem.instance_items.values())[0]
    QTest.keyClick(cnapp.window, Qt.Key_H, delay=DELAY)
    QTest.keyClick(cnapp.window, Qt.Key_C, delay=DELAY)
    cnapp.processEvents()

    cmd_count = 1  # already added the part
    for row in range(-2, 2):
        for col in range(-2, 2):
            # print(row, col)
            x, y = HoneycombDnaPart.latticeCoordToModelXY(RADIUS, row, col)
            pt = QPointF(x, y)
            cnapp.graphicsItemClick(slice_part_item,
                                    Qt.LeftButton,
                                    pos=pt,
                                    delay=DELAY)
            cmd_count += 1
    cnapp.processEvents()

    vh_count = len(cnapp.document.activePart().getidNums())

    # undo and redo all
    for i in range(cmd_count):
        cnapp.document.undoStack().undo()
    cnapp.processEvents()
    for i in range(cmd_count):
        cnapp.document.undoStack().redo()
    cnapp.processEvents()

    part = list(cnapp.document.children())[0]
    vh_count_after_redo = len(part.getidNums())

    assert vh_count == vh_count_after_redo
예제 #14
0
    def showCreateHint(self, coord: Tuple[int, int],
                            next_idnums: Tuple[int, int] = (0, 1),
                            show_hint: bool = True,
                            color: str = None) -> Optional[bool]:
        point_item = self.points_dict.get(coord)
        if point_item is None:
            return

        if not show_hint:
            point_item.showCreateHint(show_hint=False)

        if point_item:
            row, column = coord
            if self.grid_type is GridEnum.HONEYCOMB:
                parity = 0 if HoneycombDnaPart.isEvenParity(row=row, column=column) else 1
            elif self.grid_type is GridEnum.SQUARE:
                parity = 0 if SquareDnaPart.isEvenParity(row=row, column=column) else 1
            else:
                return
            id_num = next_idnums[1] if parity else next_idnums[0]
            point_item.showCreateHint(id_num=id_num, show_hint=show_hint, color=color)
            return parity == 1
예제 #15
0
def testCreateVirtualHelixGui(cnapp):
    """Create some VHs"""
    # Create a new Honeycomb part
    toolbar = cnapp.window.main_toolbar
    action_new_honeycomb = toolbar.widgetForAction(cnapp.window.action_new_dnapart_honeycomb)
    QTest.mouseClick(action_new_honeycomb, Qt.LeftButton, delay=DELAY)

    slicerootitem = cnapp.window.views['slice'].root_item
    assert len(slicerootitem.instance_items) == 1
    slice_part_item = list(slicerootitem.instance_items.values())[0]
    QTest.keyClick(cnapp.window, Qt.Key_H, delay=DELAY)
    QTest.keyClick(cnapp.window, Qt.Key_C, delay=DELAY)
    cnapp.processEvents()

    cmd_count = 1  # already added the part
    for row in range(-2, 2):
        for col in range(-2, 2):
            # print(row, col)
            x, y = HoneycombDnaPart.latticeCoordToModelXY(RADIUS, row, col)
            pt = QPointF(x, y)
            cnapp.graphicsItemClick(slice_part_item, Qt.LeftButton, pos=pt, delay=DELAY)
            cmd_count += 1
    cnapp.processEvents()

    vh_count = len(cnapp.document.activePart().getidNums())

    # undo and redo all
    for i in range(cmd_count):
        cnapp.document.undoStack().undo()
    cnapp.processEvents()
    for i in range(cmd_count):
        cnapp.document.undoStack().redo()
    cnapp.processEvents()

    part = list(cnapp.document.children())[0]
    vh_count_after_redo = len(part.getidNums())

    assert vh_count == vh_count_after_redo
예제 #16
0
    def createToolHoverMove(self, tool, event):
        """Summary

        Args:
            tool (TYPE): Description
            event (TYPE): Description

        Returns:
            TYPE: Description
        """
        is_alt = True if event.modifiers() & Qt.AltModifier else False
        mapped_position = self.griditem.mapFromScene(event.scenePos())
        event_xy = (mapped_position.x(), mapped_position.y())
        if self.griditem.grid_type is GridType.HONEYCOMB:
            event_coord = HoneycombDnaPart.positionModelToLatticeCoord(
                DEFAULT_RADIUS,
                event_xy[0],
                event_xy[1],
                scale_factor=self.scale_factor,
                strict=True)
        elif self.griditem.grid_type is GridType.SQUARE:
            event_coord = SquareDnaPart.positionModelToLatticeCoord(
                DEFAULT_RADIUS,
                event_xy[0],
                event_xy[1],
                scale_factor=self.scale_factor,
                strict=True)
        else:
            event_coord = None

        self.last_mouse_position = event_xy

        if event_coord:
            try:
                grid_point = self.griditem.points_dict[(event_coord)]
                self.setLastHoveredItem(grid_point)
            except KeyError:
                pass

        # Un-highlight GridItems if necessary by calling createToolHoverLeave
        if len(self._highlighted_path) > 1 or (
                self._highlighted_path
                and self._highlighted_path[0] != event_coord):
            self.removeAllCreateHints()

        self._highlighted_grid_point = event_coord
        if event_coord:
            self.griditem.highlightGridPoint(row=event_coord[0],
                                             column=event_coord[1],
                                             on=True)

        # Highlight GridItems if alt is being held down
        if is_alt and self.shortest_path_add_mode and event_coord is not None:
            self._previewSpa(event_xy)
        else:
            if is_alt and event_coord is not None:
                self.highlightOneGridPoint(self.getLastHoveredCoordinates(),
                                           styles.SPA_START_HINT_COLOR)
            elif not is_alt and event_coord is not None:
                part = self._model_part
                next_idnums = (part._getNewIdNum(0), part._getNewIdNum(1))
                self.griditem.showCreateHint(event_coord,
                                             next_idnums=next_idnums)
                self._highlighted_path.append(event_coord)

        tool.hoverMoveEvent(self, event)
        return QGraphicsItem.hoverMoveEvent(self, event)
예제 #17
0
    def createHoneycombGrid(self, part_item, radius, bounds):
        """Instantiate an area of griditems arranged on a honeycomb lattice.

        Args:
            part_item (TYPE): Description
            radius (TYPE): Description
            bounds (TYPE): Description

        Returns:
            TYPE: Description
        """
        doLattice = HoneycombDnaPart.latticeCoordToPositionXY
        doPosition = HoneycombDnaPart.positionToLatticeCoordRound
        isEven = HoneycombDnaPart.isEvenParity
        x_l, x_h, y_l, y_h = bounds
        x_l = x_l + HoneycombDnaPart.PAD_GRID_XL
        x_h = x_h + HoneycombDnaPart.PAD_GRID_XH
        y_h = y_h + HoneycombDnaPart.PAD_GRID_YL
        y_l = y_l + HoneycombDnaPart.PAD_GRID_YH
        dot_size, half_dot_size = self.dots
        sf = part_item.scale_factor
        points = self.points
        row_l, col_l = doPosition(radius,
                                  x_l,
                                  -y_l,
                                  False,
                                  False,
                                  scale_factor=sf)
        row_h, col_h = doPosition(radius,
                                  x_h,
                                  -y_h,
                                  True,
                                  True,
                                  scale_factor=sf)

        redo_neighbors = (row_l, col_l, row_h, col_h) != self.previous_grid_bounds or\
            self.previous_grid_type != self.grid_type
        self.previous_grid_type = self.grid_type

        path = QPainterPath()
        is_pen_down = False
        draw_lines = self.draw_lines

        if redo_neighbors:
            point_coordinates = dict()
            neighbor_map = dict()
            self.points_dict = dict()

        for row in range(row_l, row_h):
            for column in range(col_l, col_h + 1):
                x, y = doLattice(radius, row, column, scale_factor=sf)
                if draw_lines:
                    if is_pen_down:
                        path.lineTo(x, -y)
                    else:
                        is_pen_down = True
                        path.moveTo(x, -y)
                """
                +x is Left and +y is down
                origin of ellipse is Top Left corner so we subtract half in X and subtract in y
                """
                pt = GridPoint(x - half_dot_size,
                               -y - half_dot_size,
                               dot_size,
                               self,
                               coord=(row, column))

                if self._draw_gridpoint_coordinates:
                    font = QFont(styles.THE_FONT)
                    path.addText(x - 10, -y + 5, font,
                                 "%s,%s" % (-row, column))

                pt.setPen(
                    getPenObj(styles.GRAY_STROKE,
                              styles.EMPTY_HELIX_STROKE_WIDTH))

                # if x == 0 and y == 0:
                #     pt.setBrush(getBrushObj(Qt.gray))

                points.append(pt)
                self.points_dict[(-row, column)] = pt

                if redo_neighbors:
                    point_coordinates[(-row, column)] = (x, -y)

                    # This is reversed since the Y is mirrored
                    if not HoneycombDnaPart.isEvenParity(row, column):
                        neighbor_map[(-row, column)] = [(-row - 1, column),
                                                        (-row, column + 1),
                                                        (-row, column - 1)]
                    else:
                        neighbor_map[(-row, column)] = [(-row + 1, column),
                                                        (-row, column - 1),
                                                        (-row, column + 1)]
                    self.previous_grid_bounds = (row_l, col_l, row_h, col_h)

            is_pen_down = False

        if draw_lines:
            for column in range(col_l, col_h + 1):
                for row in range(row_l, row_h):
                    x, y = doLattice(radius, row, column, scale_factor=sf)
                    if is_pen_down and isEven(row, column):
                        path.lineTo(x, -y)
                        is_pen_down = False
                    else:
                        is_pen_down = True
                        path.moveTo(x, -y)
                is_pen_down = False
            # end for j
        self._path.setPath(path)

        if redo_neighbors:
            self.part_item.setNeighborMap(neighbor_map=neighbor_map)
            self.part_item.setPointMap(point_map=point_coordinates)