Source code for mbuild.lib.recipes.polymer

import itertools as it

from mbuild.compound import Compound
from mbuild.coordinate_transform import force_overlap
from mbuild.utils.validation import assert_port_exists
from mbuild import clone


__all__ = ['Polymer']


[docs]class Polymer(Compound): """Connect one or more components in a specified sequence. Parameters ---------- monomers : mb.Compound or list of mb.Compound The compound(s) to replicate. n : int The number of times to replicate the sequence. sequence : str, optional, default='A' A string of characters where each unique character represents one repetition of a monomer. Characters in `sequence` are assigned to monomers in the order assigned by the built-in `sorted()`. port_labels : 2-tuple of strs, optional, default=('up', 'down') The names of the two ports to use to connect copies of proto. """ def __init__(self, monomers, n, sequence='A', 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. force_overlap(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)
if __name__ == "__main__": from mbuild.lib.moieties import CH2 ch2 = CH2() poly = Polymer(ch2, n=13, port_labels=("up", "down")) poly.save('polymer.mol2')