Пример #1
0
 def place_building_block(self, building_block, edges):
     assert (
         building_block.get_num_functional_groups() > 2
     ), (
         f'{building_block} needs to have more than 2 functional '
         'groups but has '
         f'{building_block.get_num_functional_groups()}.'
     )
     building_block = building_block.with_centroid(
         position=self._position,
         atom_ids=building_block.get_placer_ids(),
     )
     edge_centroid = (
         sum(edge.get_position() for edge in edges) / len(edges)
     )
     edge_normal = get_acute_vector(
         reference=edge_centroid,
         vector=get_plane_normal(
             points=np.array([
                 edge.get_position() for edge in edges
             ]),
         ),
     )
     core_centroid = building_block.get_centroid(
         atom_ids=building_block.get_core_atom_ids(),
     )
     placer_centroid = building_block.get_centroid(
         atom_ids=building_block.get_placer_ids(),
     )
     building_block = building_block.with_rotation_between_vectors(
         start=get_acute_vector(
             reference=core_centroid - placer_centroid,
             vector=building_block.get_plane_normal(
                 atom_ids=building_block.get_placer_ids(),
             ),
         ),
         target=edge_normal,
         origin=self._position,
     )
     fg_bonder_centroid = building_block.get_centroid(
         atom_ids=next(
             building_block.get_functional_groups()
         ).get_placer_ids(),
     )
     edge_position = edges[self._aligner_edge].get_position()
     return building_block.with_rotation_to_minimize_angle(
         start=fg_bonder_centroid - self._position,
         target=edge_position - edge_centroid,
         axis=edge_normal,
         origin=self._position,
     ).get_position_matrix()
Пример #2
0
 def place_building_block(self, building_block, edges):
     building_block = building_block.with_centroid(
         position=self._position,
         atom_ids=building_block.get_placer_ids(),
     )
     edge_centroid = (sum(edge.get_position()
                          for edge in edges) / len(edges))
     core_centroid = building_block.get_centroid(
         atom_ids=building_block.get_core_atom_ids(), )
     placer_centroid = building_block.get_centroid(
         atom_ids=building_block.get_placer_ids(), )
     building_block = building_block.with_rotation_between_vectors(
         start=get_acute_vector(
             reference=core_centroid - placer_centroid,
             vector=building_block.get_plane_normal(
                 atom_ids=building_block.get_placer_ids(), ),
         ),
         target=self._edge_normal,
         origin=self._position,
     )
     fg_bonder_centroid = building_block.get_centroid(atom_ids=next(
         building_block.get_functional_groups()).get_placer_ids(), )
     start = fg_bonder_centroid - self._position
     edge_coord = edges[self._aligner_edge].get_position()
     building_block = (building_block.with_rotation_to_minimize_angle(
         start=start,
         target=edge_coord - edge_centroid,
         axis=self._edge_normal,
         origin=self._position,
     ))
     return building_block.get_position_matrix()
Пример #3
0
    def __init__(self, building_block):
        """
        Initialize a :class:`._FunctionalGroupSorter` instance.

        Parameters
        ----------
        building_block : :class:`.BuildingBlock`
            The building block, whose functional groups are to be
            sorted.

        """

        self._building_block = building_block
        fg0_position = building_block.get_centroid(atom_ids=next(
            building_block.get_functional_groups()).get_placer_ids(), )
        self._placer_centroid = placer_centroid = (building_block.get_centroid(
            atom_ids=building_block.get_placer_ids(), ))
        fg0_direction = fg0_position - placer_centroid
        core_centroid = building_block.get_centroid(
            atom_ids=building_block.get_core_atom_ids(), )
        axis = np.cross(
            fg0_direction,
            get_acute_vector(
                reference=core_centroid - placer_centroid,
                vector=building_block.get_plane_normal(),
            ),
        )
        axis.setflags(write=False)
        super().__init__(
            items=range(building_block.get_num_functional_groups()),
            reference=fg0_direction,
            axis=axis,
        )
Пример #4
0
    def place_building_block(self, building_block, edges):
        assert (
            building_block.get_num_functional_groups() > 2
        ), (
            f'{building_block} needs to have more than 2 functional '
            'groups but has '
            f'{building_block.get_num_functional_groups()}.'
        )
        # Sort to ensure that for two vertices, which are periodically
        # equivalent, "edges" has identical ordering. This means that
        # the aligner_edge is chosen consistently in both cases.
        edges = sorted(edges, key=lambda edge: edge.get_parent_id())

        building_block = building_block.with_centroid(
            position=self._position,
            atom_ids=building_block.get_placer_ids(),
        )
        core_centroid = building_block.get_centroid(
            atom_ids=building_block.get_core_atom_ids(),
        )
        normal = building_block.get_plane_normal(
            atom_ids=building_block.get_placer_ids(),
        )
        normal = get_acute_vector(
            reference=core_centroid - self._position,
            vector=normal,
        )
        building_block = building_block.with_rotation_between_vectors(
            start=normal,
            target=[0, 0, 1],
            origin=self._position,
        )
        fg, = building_block.get_functional_groups(0)
        fg_centroid = building_block.get_centroid(fg.get_placer_ids())
        edge_position = edges[self._aligner_edge].get_position()
        return building_block.with_rotation_to_minimize_angle(
            start=fg_centroid - self._position,
            target=edge_position - self._position,
            axis=np.array([0, 0, 1], dtype=np.float64),
            origin=self._position,
        ).get_position_matrix()
Пример #5
0
    def place_building_block(self, building_block, edges):
        assert (
            building_block.get_num_functional_groups() == 2
        ), (
            f'{building_block} needs to have exactly 2 functional '
            'groups but has '
            f'{building_block.get_num_functional_groups()}.'
        )
        building_block = building_block.with_centroid(
            position=self._position,
            atom_ids=building_block.get_placer_ids(),
        )

        # Align the normal of the plane of best fit, defined by
        # all atoms in the building block, with the z axis.
        core_centroid = building_block.get_centroid(
            atom_ids=building_block.get_core_atom_ids(),
        )
        normal = building_block.get_plane_normal()
        normal = get_acute_vector(
            reference=core_centroid - self._position,
            vector=normal,
        )
        building_block = building_block.with_rotation_between_vectors(
            start=normal,
            target=[0, 0, 1],
            origin=self._position,
        )

        # Rotate to place fg-fg vector along edge-edge vector.
        fg, = building_block.get_functional_groups(0)
        fg_centroid = building_block.get_centroid(fg.get_placer_ids())
        target = edges[0].get_position() - edges[1].get_position()
        target *= 1 if self._aligner_edge == 0 else -1

        building_block = building_block.with_rotation_between_vectors(
            start=fg_centroid - self._position,
            target=target,
            origin=self._position,
        )
        return building_block.get_position_matrix()