Example #1
0
    def apply(self, compound, orientation='', compound_port=''):
        """Arrange copies of a Compound as specified by the Pattern.

        Parameters
        ----------
        compound
        orientation

        Returns
        -------

        """
        compounds = list()
        if self.orientations.get(orientation):
            for port in self.orientations[orientation]:
                new_compound = clone(compound)
                new_port = new_compound.labels[compound_port]
                equivalence_transform(new_compound, new_port['up'], port['up'])

                compounds.append(new_compound)
        else:
            for point in self.points:
                new_compound = clone(compound)
                translate(new_compound, point)

                compounds.append(new_compound)
        return compounds
Example #2
0
    def __init__(self, proto, port_labels=("up", "down"), n=2):
        if n < 1:
            raise Exception('n must be 1 or more')
        super(Polymer, self).__init__()

        for label in port_labels:
            assert_port_exists(label, proto)

        last_part = None
        for _ in range(n):
            this_part = clone(proto)
            self.add(this_part, 'monomer[$]')
            if last_part is None:
                first_part = this_part
            else:
                # Transform this part, such that it's bottom port is rotated
                # and translated to the last part's top port.


                equivalence_transform(this_part, this_part.labels[port_labels[1]],
                                      last_part.labels[port_labels[0]])
            last_part = this_part

        # Hoist the last part's top port to be the top port of the polymer.
        self.add(last_part.labels[port_labels[0]], port_labels[0], containment=False)

        # Hoist the first part's bottom port to be the bottom port of the polymer.
        self.add(first_part.labels[port_labels[1]], port_labels[1], containment=False)
Example #3
0
    def apply_to_compound(self, guest, guest_port_name='down', host=None,
                          backfill=None, backfill_port_name='up'):
        """Attach copies of a guest Compound to Ports on a host Compound.

        Parameters
        ----------
        guest
        guest_port_name
        host
        backfill
        backfill_port_name

        Returns
        -------

        """
        n_ports = len(host.available_ports())
        assert n_ports >= self.points.shape[0], "Not enough ports for pattern."

        assert_port_exists(guest_port_name, guest)
        box = host.boundingbox
        pattern = self.points * box.lengths + box.mins

        port_positions = np.empty(shape=(n_ports, 3))
        port_list = list()
        for port_idx, port in enumerate(host.available_ports()):
            port_positions[port_idx, :] = port['up']['middle'].pos
            port_list.append(port)

        used_ports = set()  # Keep track of used ports for backfilling.
        guests = []
        for point in pattern:
            closest_point_idx = np.argmin(host.min_periodic_distance(point, port_positions))
            closest_port = port_list[closest_point_idx]
            used_ports.add(closest_port)

            # Attach the guest to the closest port.
            new_guest = clone(guest)
            equivalence_transform(new_guest, new_guest.labels[guest_port_name], closest_port)
            guests.append(new_guest)

            # Move the port as far away as possible (simpler than removing it).
            # There may well be a more elegant/efficient way of doing this.
            port_positions[closest_point_idx, :] = np.array([np.inf, np.inf, np.inf])

        backfills = []
        if backfill:
            assert_port_exists(backfill_port_name, backfill)
            # Attach the backfilling Compound to unused ports.
            for port in port_list:
                if port not in used_ports:
                    new_backfill = clone(backfill)
                    # Might make sense to have a backfill_port_name option...
                    equivalence_transform(
                        new_backfill, new_backfill.labels[backfill_port_name], port)
                    backfills.append(new_backfill)
        return guests, backfills
    def test_equivalence_transform(self, ch2, ch3, methane):
        ch2_atoms = list(ch2.particles())
        methane_atoms = list(methane.particles())
        equivalence_transform(ch2, ch2_atoms[0], methane_atoms[0], add_bond=False)
        assert (ch2_atoms[0].pos == methane_atoms[0].pos).all()
        equivalence_transform(ch2, ch2['up'], ch3['up'])
        assert ch2.n_bonds == 2

        assert nx.number_of_edges(ch2.root.bond_graph) == 3
        assert nx.number_of_edges(ch3.root.bond_graph) == 4

        ethyl = mb.Compound([ch2, ch3])
        assert ethyl.n_bonds == 6
Example #5
0
    def __init__(self, monomers, sequence="A", n=2, port_labels=("up", "down")):
        if n < 1:
            raise ValueError("n must be 1 or more")
        super(Polymer, self).__init__()
        if isinstance(monomers, Compound):
            monomers = (monomers,)
        for monomer in monomers:
            for label in port_labels:
                assert_port_exists(label, monomer)

        unique_seq_ids = sorted(set(sequence))

        if len(monomers) != len(unique_seq_ids):
            raise ValueError(
                "Number of monomers passed to `Polymer` class must"
                " match number of unique entries in the specified"
                " sequence."
            )

        # 'A': monomer_1, 'B': monomer_2....
        seq_map = dict(zip(unique_seq_ids, monomers))

        last_part = None
        for n_added, seq_item in enumerate(it.cycle(sequence)):
            this_part = clone(seq_map[seq_item])
            self.add(this_part, "monomer[$]")
            if last_part is None:
                first_part = this_part
            else:
                # Transform this part, such that it's bottom port is rotated
                # and translated to the last part's top port.
                equivalence_transform(this_part, this_part.labels[port_labels[1]], last_part.labels[port_labels[0]])
            last_part = this_part
            if n_added == n * len(sequence) - 1:
                break

        # Hoist the last part's top port to be the top port of the polymer.
        self.add(last_part.labels[port_labels[0]], port_labels[0], containment=False)

        # Hoist the first part's bottom port to be the bottom port of the polymer.
        self.add(first_part.labels[port_labels[1]], port_labels[1], containment=False)