Builder¶
The builder module provides tools for building molecular systems, such as crystals and polymers.
Crystal¶
Crystal lattice builder module - LAMMPS-style crystal structure generator.
This module provides tools for creating crystal structures: - Define Bravais lattices with basis sites - Predefined common lattice types (SC, BCC, FCC, rocksalt) - Define regions in lattice or Cartesian coordinates - Efficient vectorized unit cell tiling and atom generation
Example
lat = Lattice.cubic_fcc(a=3.52, species="Ni") region = BlockRegion(0, 10, 0, 10, 0, 10, coord_system="lattice") builder = CrystalBuilder(lat) structure = builder.build_block(region)
BlockRegion ¶
BlockRegion(xmin, xmax, ymin, ymax, zmin, zmax, coord_system='lattice')
Bases: Region
Axis-aligned box region
Define a box region specified by x, y, z ranges.
Parameters¶
xmin, xmax : float x-direction range [xmin, xmax] ymin, ymax : float y-direction range [ymin, ymax] zmin, zmax : float z-direction range [zmin, zmax] coord_system : CoordSystem, optional Coordinate system, default is "lattice"
Examples¶
Region in lattice coordinates¶
region = BlockRegion(0, 10, 0, 10, 0, 10, coord_system="lattice")
Region in Cartesian coordinates¶
region = BlockRegion(0, 30, 0, 30, 0, 30, coord_system="cartesian")
Initialize box region
Parameters¶
xmin, xmax : float x-direction range ymin, ymax : float y-direction range zmin, zmax : float z-direction range coord_system : CoordSystem, optional Coordinate system
Source code in src/molpy/builder/crystal.py
408 409 410 411 412 413 414 415 416 417 418 419 420 421 422 423 424 425 426 427 428 429 430 431 432 433 434 435 436 437 438 | |
contains_mask ¶
contains_mask(points)
Check if points are in the box (vectorized)
Parameters¶
points : np.ndarray Point coordinates array of shape (N, 3)
Returns¶
np.ndarray Boolean array of shape (N,)
Examples¶
region = BlockRegion(0, 10, 0, 10, 0, 10) points = np.array([[5, 5, 5], [15, 5, 5]]) mask = region.contains_mask(points) print(mask) # [True, False]
Source code in src/molpy/builder/crystal.py
440 441 442 443 444 445 446 447 448 449 450 451 452 453 454 455 456 457 458 459 460 461 462 463 464 465 466 467 468 469 470 471 472 473 474 475 476 477 478 479 | |
CrystalBuilder ¶
CrystalBuilder(lattice)
Crystal structure builder
Efficiently generate crystal structures using NumPy vectorized operations. Supports tiling lattices and creating atoms in specified regions.
Parameters¶
lattice : Lattice Lattice definition to use
Examples¶
Create a simple FCC structure¶
lat = Lattice.cubic_fcc(a=3.52, species="Ni") region = BlockRegion(0, 10, 0, 10, 0, 10, coord_system="lattice") builder = CrystalBuilder(lat) structure = builder.build_block(region) print(len(structure.atoms))
Initialize crystal builder
Parameters¶
lattice : Lattice Lattice definition
Source code in src/molpy/builder/crystal.py
504 505 506 507 508 509 510 511 512 513 | |
build_block ¶
build_block(region, *, i_range=None, j_range=None, k_range=None)
Build crystal structure within a box region
This method efficiently generates crystal structures using vectorized operations: 1. Determine cell index ranges to tile 2. Use NumPy meshgrid and broadcasting to generate all atom positions 3. Apply region filtering 4. Create and return Atomistic structure
Parameters¶
region : BlockRegion Box defining the region for atom generation i_range, j_range, k_range : range | None, optional Explicitly specify cell index ranges. If not provided: - For "lattice" coordinate system: inferred from region boundaries - For "cartesian" coordinate system: must be provided, otherwise raises error
Returns¶
Atomistic Generated crystal structure containing atoms and box information
Raises¶
ValueError If coord_system == "cartesian" and explicit ranges are not provided
Examples¶
Using lattice coordinates (auto-infer ranges)¶
lat = Lattice.cubic_sc(a=2.0, species="Cu") region = BlockRegion(0, 10, 0, 10, 0, 10, coord_system="lattice") builder = CrystalBuilder(lat) structure = builder.build_block(region)
Using explicit ranges¶
structure = builder.build_block( ... region, ... i_range=range(0, 5), ... j_range=range(0, 5), ... k_range=range(0, 5) ... )
Cartesian coordinates (must provide ranges)¶
region_cart = BlockRegion(0, 20, 0, 20, 0, 20, coord_system="cartesian") structure = builder.build_block( ... region_cart, ... i_range=range(0, 10), ... j_range=range(0, 10), ... k_range=range(0, 10) ... )
Notes¶
- This method uses no Python loops, fully based on NumPy vectorized operations
- Generated structure contains:
- Atom positions (Cartesian coordinates)
- Atom species
- Box information (lattice vectors)
- For empty basis (no basis sites), returns empty Atomistic structure
Source code in src/molpy/builder/crystal.py
515 516 517 518 519 520 521 522 523 524 525 526 527 528 529 530 531 532 533 534 535 536 537 538 539 540 541 542 543 544 545 546 547 548 549 550 551 552 553 554 555 556 557 558 559 560 561 562 563 564 565 566 567 568 569 570 571 572 573 574 575 576 577 578 579 580 581 582 583 584 585 586 587 588 589 590 591 592 593 594 595 596 597 598 599 600 601 602 603 604 605 606 607 608 609 610 611 612 613 614 615 616 617 618 619 620 621 622 623 624 625 626 627 628 629 630 631 632 633 634 635 636 637 638 639 640 641 642 643 644 645 646 647 648 649 650 651 652 653 654 655 656 657 658 659 660 661 662 663 664 665 666 667 668 669 670 671 672 673 674 675 676 677 678 679 680 681 682 | |
Lattice ¶
Lattice(a1, a2, a3, basis)
Bravais lattice with basis sites.
This class defines a crystal lattice structure, including lattice vectors and basis sites. Lattice vectors define the shape and size of the unit cell, while basis sites define the positions of atoms within the cell (in fractional coordinates).
Parameters¶
a1, a2, a3 : np.ndarray Lattice vectors, each is a NumPy array of shape (3,) basis : list[Site] List of basis sites in fractional coordinates
Attributes¶
a1, a2, a3 : np.ndarray Lattice vectors basis : list[Site] List of basis sites
Examples¶
Create simple cubic lattice¶
lat = Lattice.cubic_sc(a=2.0, species="Cu")
Create face-centered cubic lattice¶
lat = Lattice.cubic_fcc(a=3.52, species="Ni")
Create rocksalt structure¶
lat = Lattice.rocksalt(a=5.64, species_a="Na", species_b="Cl")
Initialize lattice
Parameters¶
a1, a2, a3 : np.ndarray Lattice vectors of shape (3,) basis : list[Site] List of basis sites
Source code in src/molpy/builder/crystal.py
98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 | |
cell
property
¶
cell
Return 3×3 cell matrix with lattice vectors as rows
Returns¶
np.ndarray Matrix of shape (3, 3), each row is a lattice vector [a1; a2; a3]
add_site ¶
add_site(site)
Add a basis site
Parameters¶
site : Site Basis site to add
Source code in src/molpy/builder/crystal.py
133 134 135 136 137 138 139 140 141 142 | |
cubic_bcc
classmethod
¶
cubic_bcc(a, species)
Create body-centered cubic (Body-Centered Cubic, BCC) lattice
Body-centered cubic lattice has two atoms per unit cell: one at corner and one at body center.
Parameters¶
a : float Lattice constant (in Å) species : str Atomic species (e.g., "Fe", "W")
Returns¶
Lattice Body-centered cubic lattice
Examples¶
lat = Lattice.cubic_bcc(a=3.0, species="Fe") print(len(lat.basis)) # 2
Source code in src/molpy/builder/crystal.py
204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 | |
cubic_fcc
classmethod
¶
cubic_fcc(a, species)
Create face-centered cubic (Face-Centered Cubic, FCC) lattice
Face-centered cubic lattice has four atoms per unit cell: one at corner and one at each face center.
Parameters¶
a : float Lattice constant (in Å) species : str Atomic species (e.g., "Ni", "Cu", "Al")
Returns¶
Lattice Face-centered cubic lattice
Examples¶
lat = Lattice.cubic_fcc(a=3.52, species="Ni") print(len(lat.basis)) # 4
Source code in src/molpy/builder/crystal.py
239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 272 273 274 | |
cubic_sc
classmethod
¶
cubic_sc(a, species)
Create simple cubic (Simple Cubic, SC) lattice
Simple cubic lattice is the simplest lattice type with one atom per unit cell.
Parameters¶
a : float Lattice constant (in Å) species : str Atomic species (e.g., "Cu", "Fe")
Returns¶
Lattice Simple cubic lattice
Examples¶
lat = Lattice.cubic_sc(a=2.0, species="Cu") print(len(lat.basis)) # 1
Source code in src/molpy/builder/crystal.py
172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 | |
frac_to_cart ¶
frac_to_cart(frac)
Convert fractional coordinates to Cartesian coordinates
Fractional coordinates (u, v, w) represent position relative to lattice vectors: cart = ua1 + va2 + w*a3 = frac @ cell
Parameters¶
frac : np.ndarray Fractional coordinates of shape (N, 3) or (3,), containing (u, v, w) values
Returns¶
np.ndarray Cartesian coordinates, same shape as input
Examples¶
lat = Lattice.cubic_sc(a=2.0, species="Cu") frac = np.array([0.5, 0.5, 0.5]) cart = lat.frac_to_cart(frac) print(cart) # [1.0, 1.0, 1.0]
Source code in src/molpy/builder/crystal.py
144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 | |
rocksalt
classmethod
¶
rocksalt(a, species_a, species_b)
Create rocksalt (NaCl) structure
Rocksalt structure consists of two interpenetrating FCC sublattices. Each unit cell contains 4 A atoms and 4 B atoms.
Parameters¶
a : float Lattice constant (in Å) species_a : str First atomic species (e.g., "Na") species_b : str Second atomic species (e.g., "Cl")
Returns¶
Lattice Rocksalt structure lattice
Examples¶
lat = Lattice.rocksalt(a=5.64, species_a="Na", species_b="Cl") print(len(lat.basis)) # 8
Source code in src/molpy/builder/crystal.py
276 277 278 279 280 281 282 283 284 285 286 287 288 289 290 291 292 293 294 295 296 297 298 299 300 301 302 303 304 305 306 307 308 309 310 311 312 313 314 315 316 317 318 319 320 321 322 323 324 325 | |
Region ¶
Region(coord_system='lattice')
Bases: ABC
Abstract geometric region class
Define a spatial region that can be represented in lattice or Cartesian coordinates.
Parameters¶
coord_system : CoordSystem Coordinate system, "lattice" or "cartesian" - "lattice": point coordinates in lattice units - "cartesian": point coordinates in Cartesian coordinates (Å)
Notes¶
Subclasses must implement contains_mask method using NumPy
vectorized operations to efficiently check if multiple points are in the region.
Initialize region
Parameters¶
coord_system : CoordSystem, optional Coordinate system, default is "lattice"
Source code in src/molpy/builder/crystal.py
347 348 349 350 351 352 353 354 355 356 | |
contains_mask
abstractmethod
¶
contains_mask(points)
Check if points are in the region (vectorized)
Parameters¶
points : np.ndarray Point coordinates array of shape (N, 3)
Returns¶
np.ndarray Boolean array of shape (N,), True indicates point is in region
Notes¶
- If coord_system == "lattice": points are in lattice units
- If coord_system == "cartesian": points are in Cartesian coordinates
- Must use vectorized operations, no Python loops
Source code in src/molpy/builder/crystal.py
358 359 360 361 362 363 364 365 366 367 368 369 370 371 372 373 374 375 376 377 378 379 | |
Site
dataclass
¶
Site(label, species, frac, charge=0.0, meta=None)
Lattice basis site in fractional coordinates.
Attributes¶
label : str Site identifier or name (e.g., "A", "B1") species : str Chemical species or type name (e.g., "Ni", "Na", "Cl") frac : tuple[float, float, float] Fractional coordinates (u, v, w) relative to the Bravais cell, typically in [0, 1) charge : float, optional Charge, default is 0.0 meta : dict[str, Any] | None, optional Optional metadata dictionary
Examples¶
site = Site(label="A", species="Cu", frac=(0.0, 0.0, 0.0)) site_charged = Site(label="Na", species="Na", frac=(0.0, 0.0, 0.0), charge=1.0)
Polymer¶
Polymer assembly module.
Provides linear polymer assembly with both topology-only and chemical reaction connectors, plus optional geometric placement via Placer strategies.
AutoConnector ¶
Bases: Connector
BigSMILES-guided automatic port selection.
Strategy: 1. If left has port with role='right' and right has role='left' -> use those 2. Else if each side has exactly one unconsumed port -> use that pair 3. Else raise AmbiguousPortsError
This implements the common case where: - BigSMILES uses [<] for "left" role and [>] for "right" role - We connect left's "right" port to right's "left" port
Ports are stored directly on atoms using the "port" or "ports" attribute.
select_ports ¶
select_ports(left, right, left_ports, right_ports, ctx)
Select ports using BigSMILES role heuristics.
Source code in src/molpy/builder/polymer/connectors.py
92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 | |
CallbackConnector ¶
CallbackConnector(fn)
Bases: Connector
User-defined callback for port selection.
Example
def my_selector(left, right, left_ports, right_ports, ctx): # Custom logic here return ("port_out", "port_in", "-")
connector = CallbackConnector(my_selector)
Initialize callback connector.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
fn
|
Callable[[Atomistic, Atomistic, Mapping[str, PortInfo], Mapping[str, PortInfo], ConnectorContext], tuple[str, str] | tuple[str, str, BondKind]]
|
Callable that takes (left, right, left_ports, right_ports, ctx) and returns (left_port, right_port [, bond_kind]) |
required |
Source code in src/molpy/builder/polymer/connectors.py
259 260 261 262 263 264 265 266 267 268 269 270 271 272 273 274 275 276 277 278 279 | |
select_ports ¶
select_ports(left, right, left_ports, right_ports, ctx)
Select ports using user callback.
Source code in src/molpy/builder/polymer/connectors.py
281 282 283 284 285 286 287 288 289 290 291 292 293 294 295 296 297 | |
Chain
dataclass
¶
Chain(dp, monomers, mass)
Represents a single polymer chain.
Attributes:
| Name | Type | Description |
|---|---|---|
dp |
int
|
Degree of polymerization (number of monomers) |
monomers |
list[str]
|
List of monomer identifiers in the chain |
mass |
float
|
Total mass of the chain (g/mol) |
ChainConnector ¶
ChainConnector(connectors)
Bases: Connector
Try a list of connectors in order; first one that succeeds wins.
Example
connector = ChainConnector([ TableConnector(specific_rules), AutoConnector(), ])
Initialize chain connector.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
connectors
|
Iterable[Connector]
|
List of connectors to try in order |
required |
Source code in src/molpy/builder/polymer/connectors.py
311 312 313 314 315 316 317 318 | |
select_ports ¶
select_ports(left, right, left_ports, right_ports, ctx)
Try connectors in order until one succeeds.
Source code in src/molpy/builder/polymer/connectors.py
320 321 322 323 324 325 326 327 328 329 330 331 332 333 334 335 336 337 338 339 340 341 342 343 344 345 346 | |
ConnectionMetadata
dataclass
¶
ConnectionMetadata(port_L, port_R, reaction_name, formed_bonds=list(), new_angles=list(), new_dihedrals=list(), modified_atoms=set(), requires_retype=False, entity_maps=list())
Metadata about a single monomer connection step.
Attributes:
| Name | Type | Description |
|---|---|---|
port_L |
str
|
Name of the port used on the left monomer |
port_R |
str
|
Name of the port used on the right monomer |
reaction_name |
str
|
Name of the reaction used |
formed_bonds |
list[Any]
|
List of newly formed bonds |
new_angles |
list[Any]
|
List of newly created angles |
new_dihedrals |
list[Any]
|
List of newly created dihedrals |
modified_atoms |
set[Atom]
|
Set of atoms whose types may have changed |
requires_retype |
bool
|
Whether retypification is needed |
entity_maps |
list[dict[Atom, Atom]]
|
List of entity mappings for port remapping |
ConnectionResult
dataclass
¶
ConnectionResult(product, metadata)
Result of connecting two monomers.
Attributes:
| Name | Type | Description |
|---|---|---|
product |
Atomistic
|
The resulting Atomistic assembly after connection |
metadata |
ConnectionMetadata
|
Metadata about the connection |
Connector ¶
Abstract base for port selection between two adjacent Atomistic structures.
This is topology-only: connectors decide WHICH ports to connect, not HOW to position them geometrically.
select_ports ¶
select_ports(left, right, left_ports, right_ports, ctx)
Select which ports to connect between left and right structures.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
left
|
Atomistic
|
Left Atomistic structure in the sequence |
required |
right
|
Atomistic
|
Right Atomistic structure in the sequence |
required |
left_ports
|
Mapping[str, list[PortInfo]]
|
Available (unconsumed) ports on left structure (port name -> list of PortInfo) |
required |
right_ports
|
Mapping[str, list[PortInfo]]
|
Available (unconsumed) ports on right structure (port name -> list of PortInfo) |
required |
ctx
|
ConnectorContext
|
Shared context with step info, sequence, etc. |
required |
Returns:
| Type | Description |
|---|---|
str
|
Tuple of (left_port_name, left_port_index, right_port_name, right_port_index, optional_bond_kind_override) |
int
|
The indices specify which port to use when multiple ports have the same name. |
Raises:
| Type | Description |
|---|---|
AmbiguousPortsError
|
Cannot uniquely determine ports |
NoCompatiblePortsError
|
No valid port pair found |
MissingConnectorRule
|
Required rule not found (TableConnector) |
Source code in src/molpy/builder/polymer/connectors.py
46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 | |
ConnectorContext ¶
Bases: dict[str, Any]
Shared context passed to connectors during linear build.
Contains information like: - step: int (current connection step index) - sequence: str (full sequence being built) - left_label: str (label of left monomer) - right_label: str (label of right monomer) - audit: list (accumulated connection records)
FlorySchulzPolydisperse ¶
FlorySchulzPolydisperse(a, random_seed=None)
Bases: DPDistribution
Flory-Schulz distribution for degree of polymerization (DP).
Implements :class:DPDistribution - sampling is done directly in DP
space. In this formulation the Flory-Schulz distribution is a geometric
distribution over the chain length :math:N, commonly used for
step-growth polymerization.
The probability mass function (PMF) is
.. math::
P(N = k) = (1 - p)^{k-1} p, \qquad k = 1, 2, \dots,
where :math:p \in (0, 1) is related to the extent of reaction.
Parameters¶
p:
Success probability :math:p in the geometric PMF above
(:math:0 < p < 1).
random_seed:
Optional random seed used when sampling.
Initialize Flory-Schulz DP distribution.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
p
|
Success probability (0 < p < 1), related to extent of reaction |
required | |
random_seed
|
int | None
|
Random seed for reproducibility (optional) |
None
|
Source code in src/molpy/builder/polymer/system.py
647 648 649 650 651 652 653 654 655 656 657 658 659 660 661 662 663 | |
sample_dp ¶
sample_dp(rng)
Sample degree of polymerization from Flory-Schulz distribution.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
rng
|
Generator
|
NumPy random number generator |
required |
Returns:
| Type | Description |
|---|---|
int
|
Degree of polymerization (>= 1) |
Source code in src/molpy/builder/polymer/system.py
674 675 676 677 678 679 680 681 682 683 684 | |
GrowthKernel ¶
Bases: Protocol
Protocol for local transition function in port-level stochastic growth.
A GrowthKernel decides which monomer (if any) to add next for a given reactive port on the growing polymer. This encapsulates the reaction probability logic from G-BigSMILES notation.
choose_next_for_port ¶
choose_next_for_port(polymer, port, candidates, rng=None)
Choose next monomer for a given port.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
polymer
|
Atomistic
|
Current polymer structure |
required |
port
|
PortInfo
|
Port to extend from |
required |
candidates
|
Sequence[MonomerTemplate]
|
Available monomer templates |
required |
rng
|
Generator | None
|
Random number generator for sampling |
None
|
Returns:
| Name | Type | Description |
|---|---|---|
MonomerPlacement |
MonomerPlacement | None
|
Add this template at target port |
None |
MonomerPlacement | None
|
Terminate this port (implicit end-group) |
Source code in src/molpy/builder/polymer/growth_kernel.py
25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 | |
MonomerPlacement
dataclass
¶
MonomerPlacement(template, target_descriptor_id)
Decision for next monomer placement during stochastic growth.
Attributes:
| Name | Type | Description |
|---|---|---|
template |
MonomerTemplate
|
MonomerTemplate to add |
target_descriptor_id |
int
|
Which port descriptor on the new monomer to connect |
MonomerTemplate
dataclass
¶
MonomerTemplate(label, structure, port_descriptors, mass, metadata=dict())
Template for a monomer with port descriptors and metadata.
This represents a monomer type that can be instantiated multiple times during stochastic growth. Each instantiation creates a fresh copy of the structure.
Attributes:
| Name | Type | Description |
|---|---|---|
label |
str
|
Monomer label (e.g., "EO2", "PS") |
structure |
Atomistic
|
Base Atomistic structure (will be copied on instantiation) |
port_descriptors |
dict[int, PortDescriptor]
|
Mapping from descriptor_id to PortDescriptor |
mass |
float
|
Molecular weight (g/mol) |
metadata |
dict[str, Any]
|
Additional metadata (optional) |
get_all_descriptors ¶
get_all_descriptors()
Get all port descriptors for this template.
Returns:
| Type | Description |
|---|---|
list[PortDescriptor]
|
List of all PortDescriptor objects |
Source code in src/molpy/builder/polymer/types.py
134 135 136 137 138 139 140 | |
get_port_by_descriptor ¶
get_port_by_descriptor(descriptor_id)
Get port descriptor for a specific descriptor ID.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
descriptor_id
|
int
|
Descriptor ID to look up |
required |
Returns:
| Type | Description |
|---|---|
PortDescriptor | None
|
PortDescriptor if found, None otherwise |
Source code in src/molpy/builder/polymer/types.py
123 124 125 126 127 128 129 130 131 132 | |
instantiate ¶
instantiate()
Create a fresh copy of the structure.
Returns:
| Type | Description |
|---|---|
Atomistic
|
New Atomistic instance with independent atoms and bonds |
Source code in src/molpy/builder/polymer/types.py
115 116 117 118 119 120 121 | |
PoissonPolydisperse ¶
PoissonPolydisperse(lambda_param, random_seed=None)
Bases: DPDistribution
Poisson distribution for the degree of polymerization (DP).
Implements :class:DPDistribution - sampling is done directly in
DP space. The number of repeat units is modeled as a Poisson process
with mean :math:\lambda.
The (untruncated) Poisson probability mass function is
.. math::
P(N = k)
= \frac{\lambda^{k} e^{-\lambda}}{k!},
\qquad k = 0, 1, 2, \dots
In this implementation we restrict to :math:k \ge 1 when sampling
chains, i.e. a sampled value :math:k = 0 is mapped to :math:k = 1
so that every chain contains at least one monomer.
Parameters¶
lambda_param:
Mean :math:\lambda of the Poisson distribution.
random_seed:
Optional random seed used when sampling.
Initialize Poisson DP distribution.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
lambda_param
|
float
|
Mean (lambda) parameter of Poisson distribution |
required |
random_seed
|
int | None
|
Random seed for reproducibility (optional) |
None
|
Source code in src/molpy/builder/polymer/system.py
557 558 559 560 561 562 563 564 565 566 567 568 569 570 571 572 573 | |
dp_pmf ¶
dp_pmf(dp_array)
Compute the probability mass function (PMF) over DP values.
Poisson PMF: P(k; λ) = (λ^k * e^(-λ)) / k! for k >= 1
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
dp_array
|
ndarray
|
Array of DP values |
required |
Returns:
| Type | Description |
|---|---|
ndarray
|
Array of PMF values |
Source code in src/molpy/builder/polymer/system.py
575 576 577 578 579 580 581 582 583 584 585 586 587 588 589 590 591 592 593 594 595 596 597 598 599 600 601 602 603 604 605 | |
sample_dp ¶
sample_dp(rng)
Sample degree of polymerization from Poisson distribution.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
rng
|
Generator
|
NumPy random number generator |
required |
Returns:
| Type | Description |
|---|---|
int
|
Degree of polymerization (>= 1) |
Source code in src/molpy/builder/polymer/system.py
608 609 610 611 612 613 614 615 616 617 618 | |
PolydisperseChainGenerator ¶
PolydisperseChainGenerator(seq_generator, monomer_mass, end_group_mass=0.0, distribution=None)
Middle layer: Chain-level generator.
Responsible for: - Sampling chain size: - Either in DP-space via a DPDistribution (sample_dp) - Or in mass-space via a MassDistribution (sample_mass) - Using a SequenceGenerator to build the chain sequence - Computing the mass of a chain using monomer mass table and optional end-group mass
Does NOT know anything about total system mass. Only returns one chain at a time.
Initialize polydisperse chain generator.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
seq_generator
|
SequenceGenerator
|
Sequence generator for generating monomer sequences |
required |
monomer_mass
|
dict[str, float]
|
Dictionary mapping monomer identifiers to their masses (g/mol) |
required |
end_group_mass
|
float
|
Mass of end groups (g/mol), default 0.0 |
0.0
|
distribution
|
DPDistribution | MassDistribution | None
|
Distribution implementing DPDistribution or MassDistribution protocol |
None
|
Source code in src/molpy/builder/polymer/system.py
140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 | |
build_chain ¶
build_chain(rng)
Sample DP, generate monomer sequence, and compute mass.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
rng
|
Random
|
Random number generator |
required |
Returns:
| Type | Description |
|---|---|
Chain
|
Chain object with dp, monomers, and mass |
Source code in src/molpy/builder/polymer/system.py
219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 272 273 274 275 276 277 278 279 280 281 282 283 284 | |
sample_dp ¶
sample_dp(rng)
Sample a degree of polymerization from the distribution.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
rng
|
Random
|
Random number generator |
required |
Returns:
| Type | Description |
|---|---|
int
|
Degree of polymerization (>= 1) |
Source code in src/molpy/builder/polymer/system.py
164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 | |
sample_mass ¶
sample_mass(rng)
Sample a target chain mass from a mass-based distribution.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
rng
|
Random
|
Random number generator |
required |
Returns:
| Type | Description |
|---|---|
float
|
Target chain mass in g/mol (>= 0) |
Source code in src/molpy/builder/polymer/system.py
194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 | |
PolymerBuildResult
dataclass
¶
PolymerBuildResult(polymer, connection_history=list(), total_steps=0)
Result of building a polymer.
Attributes:
| Name | Type | Description |
|---|---|---|
polymer |
Atomistic
|
The assembled Atomistic structure |
connection_history |
list[ConnectionMetadata]
|
List of connection metadata for each step |
total_steps |
int
|
Total number of connection steps performed |
PolymerBuilder ¶
PolymerBuilder(library, connector, typifier=None, placer=None)
Build polymers from CGSmiles notation with support for arbitrary topologies.
This builder parses CGSmiles strings and constructs polymers using a graph-based approach, supporting: - Linear chains: {[#A][#B][#C]} - Branched structures: {#A[#C]} - Cyclic structures: {[#A]1[#B][#C]1} - Repeat operators: {[#A]|10}
Example
builder = PolymerBuilder( ... library={"EO2": eo2_monomer, "PS": ps_monomer}, ... connector=connector, ... typifier=typifier, ... ) result = builder.build("{[#EO2]|8[#PS]}")
Initialize the polymer builder.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
library
|
Mapping[str, Atomistic]
|
Mapping from CGSmiles labels to Atomistic monomer structures |
required |
connector
|
ReacterConnector
|
ReacterConnector for port selection and chemical reactions |
required |
typifier
|
TypifierBase | None
|
Optional typifier for automatic retypification |
None
|
placer
|
Placer | None
|
Optional Placer for positioning structures before connection |
None
|
Source code in src/molpy/builder/polymer/polymer_builder.py
53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 | |
build ¶
build(cgsmiles)
Build a polymer from a CGSmiles string.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
cgsmiles
|
str
|
CGSmiles notation string (e.g., "{[#EO2]|8[#PS]}") |
required |
Returns:
| Type | Description |
|---|---|
PolymerBuildResult
|
PolymerBuildResult containing the assembled polymer and metadata |
Raises:
| Type | Description |
|---|---|
ValueError
|
If CGSmiles is invalid |
SequenceError
|
If labels in CGSmiles are not found in library |
Source code in src/molpy/builder/polymer/polymer_builder.py
74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 | |
PortDescriptor
dataclass
¶
PortDescriptor(descriptor_id, port_name, role=None, bond_kind=None, compat=None)
Descriptor for a reactive port on a monomer template.
Attributes:
| Name | Type | Description |
|---|---|---|
descriptor_id |
int
|
Unique ID within template (e.g., 0, 1, 2) |
port_name |
str
|
Port name on atom (e.g., "<", ">", "branch") |
role |
str | None
|
Port role (e.g., "left", "right", "branch") |
bond_kind |
str | None
|
Bond type (e.g., "-", "=", "#") |
compat |
set[str] | None
|
Compatibility set for port matching |
ProbabilityTableKernel ¶
ProbabilityTableKernel(probability_tables, end_group_templates=None)
GrowthKernel based on G-BigSMILES probability tables.
This kernel uses pre-computed probability tables that map each port descriptor to weighted choices over (template, target_descriptor_id) pairs. Weights are integers that are normalized to probabilities during sampling.
Initialize probability table kernel.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
probability_tables
|
dict[int, list[tuple[MonomerTemplate, int, int]]]
|
Maps descriptor_id -> [(template, target_desc, integer_weight)] Integer weights are normalized to probabilities during sampling. |
required |
end_group_templates
|
dict[int, MonomerTemplate] | None
|
Maps descriptor_id -> end-group template (no ports) |
None
|
Source code in src/molpy/builder/polymer/growth_kernel.py
55 56 57 58 59 60 61 62 63 64 65 66 67 68 | |
choose_next_for_port ¶
choose_next_for_port(polymer, port, candidates, rng=None)
Choose next monomer based on probability table.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
polymer
|
Atomistic
|
Current polymer structure |
required |
port
|
PortInfo
|
Port to extend from |
required |
candidates
|
Sequence[MonomerTemplate]
|
Available monomer templates |
required |
rng
|
Generator | None
|
Random number generator (uses default if None) |
None
|
Returns:
| Type | Description |
|---|---|
MonomerPlacement | None
|
MonomerPlacement or None (terminate) |
Source code in src/molpy/builder/polymer/growth_kernel.py
70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 | |
ReacterConnector ¶
ReacterConnector(default, port_map, overrides=None)
Bases: Connector
Connector that uses chemical reactions (Reacter) for polymer assembly.
This connector integrates port selection and chemical reaction execution. It manages multiple Reacter instances and port mapping strategies for different structure pairs.
Port Selection Strategy:
Port selection is handled via a port_map which must be a dict:
- Dict: Explicit mapping {('A','B'): ('1','2'), ...}
There is NO 'auto' mode - port selection must be explicit via port_map. Ports are stored directly on atoms using the "port" or "ports" attribute.
Attributes:
| Name | Type | Description |
|---|---|---|
default |
Default Reacter for most connections |
|
overrides |
Dict mapping (left_type, right_type) -> specialized Reacter |
|
port_map |
Dict mapping (left_type, right_type) -> (port_L, port_R) |
Example
from molpy.reacter import Reacter from molpy.reacter.selectors import select_port_atom, select_one_hydrogen from molpy.reacter.transformers import form_single_bond
default_reacter = Reacter( ... name="C-C_coupling", ... port_selector_left=select_port_atom, ... port_selector_right=select_port_atom, ... leaving_selector_left=select_one_hydrogen, ... leaving_selector_right=select_one_hydrogen, ... bond_former=form_single_bond, ... )
Explicit port mapping for all structure pairs¶
connector = ReacterConnector( ... default=default_reacter, ... port_map={ ... ('A', 'B'): ('port_1', 'port_2'), ... ('B', 'C'): ('port_3', 'port_4'), ... }, ... overrides={('B', 'C'): special_reacter}, ... )
Initialize ReacterConnector.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
default
|
Reacter
|
Default Reacter for most connections |
required |
port_map
|
dict[tuple[str, str], tuple[str, str]]
|
Mapping from (left_type, right_type) to (port_L, port_R) |
required |
overrides
|
dict[tuple[str, str], Reacter] | None
|
Optional mapping from (left_type, right_type) to specialized Reacter instances |
None
|
Raises:
| Type | Description |
|---|---|
TypeError
|
If port_map is not a dict |
Source code in src/molpy/builder/polymer/connectors.py
394 395 396 397 398 399 400 401 402 403 404 405 406 407 408 409 410 411 412 413 414 415 416 417 418 | |
connect ¶
connect(left, right, left_type, right_type, port_atom_L, port_atom_R, typifier=None)
Execute chemical reaction between two Atomistic structures.
This method performs the full chemical reaction including: 1. Selecting appropriate reacter based on structure types 2. Executing reaction (merging, bond making, removing leaving groups) 3. Computing new topology (angles, dihedrals) 4. Collecting metadata for retypification
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
left
|
Atomistic
|
Left Atomistic structure |
required |
right
|
Atomistic
|
Right Atomistic structure |
required |
left_type
|
str
|
Type label of left structure |
required |
right_type
|
str
|
Type label of right structure |
required |
port_atom_L
|
Entity
|
Port atom from left structure |
required |
port_atom_R
|
Entity
|
Port atom from right structure |
required |
typifier
|
TypifierBase | None
|
Optional typifier |
None
|
Returns:
| Type | Description |
|---|---|
ConnectionResult
|
ConnectionResult containing product and metadata |
Source code in src/molpy/builder/polymer/connectors.py
485 486 487 488 489 490 491 492 493 494 495 496 497 498 499 500 501 502 503 504 505 506 507 508 509 510 511 512 513 514 515 516 517 518 519 520 521 522 523 524 525 526 527 528 529 530 531 532 533 534 535 536 537 538 539 540 541 542 543 544 545 546 547 548 549 550 551 | |
get_all_modified_atoms ¶
get_all_modified_atoms()
Get all atoms modified across all reactions.
Returns:
| Type | Description |
|---|---|
set[Entity]
|
Set of all atoms that were modified during reactions |
Source code in src/molpy/builder/polymer/connectors.py
557 558 559 560 561 562 563 564 565 566 | |
get_history ¶
get_history()
Get all reaction history (list of ReactionResult).
Source code in src/molpy/builder/polymer/connectors.py
553 554 555 | |
get_reacter ¶
get_reacter(left_type, right_type)
Get appropriate reacter for a structure pair.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
left_type
|
str
|
Type label of left structure (e.g., 'A', 'B') |
required |
right_type
|
str
|
Type label of right structure |
required |
Returns:
| Type | Description |
|---|---|
Reacter
|
The appropriate Reacter (override if exists, else default) |
Source code in src/molpy/builder/polymer/connectors.py
420 421 422 423 424 425 426 427 428 429 430 431 432 | |
needs_retypification ¶
needs_retypification()
Check if any reactions require retypification.
Returns:
| Type | Description |
|---|---|
bool
|
True if any reaction requires retypification |
Source code in src/molpy/builder/polymer/connectors.py
568 569 570 571 572 573 574 | |
select_ports ¶
select_ports(left, right, left_ports, right_ports, ctx)
Select ports using the configured port_map.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
left
|
Atomistic
|
Left Atomistic structure |
required |
right
|
Atomistic
|
Right Atomistic structure |
required |
left_ports
|
Mapping[str, list[PortInfo]]
|
Available ports on left (port name -> list of PortInfo) |
required |
right_ports
|
Mapping[str, list[PortInfo]]
|
Available ports on right (port name -> list of PortInfo) |
required |
ctx
|
ConnectorContext
|
Connector context with structure type information |
required |
Returns:
| Type | Description |
|---|---|
str
|
Tuple of (port_L, port_L_idx, port_R, port_R_idx, None) |
int
|
Uses index 0 when multiple ports share the same name. |
Raises:
| Type | Description |
|---|---|
ValueError
|
If port mapping not found or ports invalid |
Source code in src/molpy/builder/polymer/connectors.py
434 435 436 437 438 439 440 441 442 443 444 445 446 447 448 449 450 451 452 453 454 455 456 457 458 459 460 461 462 463 464 465 466 467 468 469 470 471 472 473 474 475 476 477 478 479 480 481 482 483 | |
SchulzZimmPolydisperse ¶
SchulzZimmPolydisperse(Mn, Mw, random_seed=None)
Bases: MassDistribution
Schulz-Zimm molecular weight distribution for polydisperse polymer chains.
Implements :class:MassDistribution - sampling is done directly in
molecular-weight (:math:M) space.
Following the notation in the paper, the probability density (often also called “PMF” there) is
.. math::
\operatorname{PMF}(M)
= \frac{z^{z+1}}{\Gamma(z+1)}
\frac{M^{z-1}}{M_n^{z}}
\exp\left(-\frac{z M}{M_n}\right),
where
.. math::
z = \frac{M_n}{M_w - M_n},
:math:M_n is the number-average molecular weight, and
:math:M_w is the weight-average molecular weight.
This expression is mathematically equivalent to a Gamma distribution
with shape :math:z and scale
.. math::
\theta = \frac{M_n}{z} = M_w - M_n,
which satisfies the prescribed :math:M_n and :math:M_w with
polydispersity index :math:\text{PDI} = M_w / M_n.
Parameters¶
Mn:
Number-average molecular weight :math:M_n (g/mol).
Mw:
Weight-average molecular weight :math:M_w (g/mol), must satisfy
:math:M_w > M_n.
random_seed:
Optional random seed used when sampling.
Initialize Schulz-Zimm polydisperse distribution.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
Mn
|
float
|
Number-average molecular weight (g/mol) |
required |
Mw
|
float
|
Weight-average molecular weight (g/mol) |
required |
random_seed
|
int | None
|
Random seed for reproducibility (optional) |
None
|
Source code in src/molpy/builder/polymer/system.py
347 348 349 350 351 352 353 354 355 356 357 358 359 360 361 362 363 364 365 366 367 368 369 370 371 372 373 374 375 376 377 | |
mass_pdf ¶
mass_pdf(mass_array)
Probability density function for mass values.
This implements the Gamma PDF described in the class docstring and
returns :math:f(M) evaluated at the entries of mass_array.
Args¶
mass_array:
Array of molecular weights :math:M (g/mol).
Returns¶
numpy.ndarray
Array of probability density values with the same shape as
mass_array.
Source code in src/molpy/builder/polymer/system.py
392 393 394 395 396 397 398 399 400 401 402 403 404 405 406 407 408 409 410 411 412 413 414 415 416 417 418 419 420 421 422 423 424 | |
sample_mass ¶
sample_mass(rng)
Sample molecular weight directly from Schulz-Zimm distribution.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
rng
|
Generator
|
NumPy random number generator |
required |
Returns:
| Type | Description |
|---|---|
float
|
Molecular weight (g/mol) |
Source code in src/molpy/builder/polymer/system.py
380 381 382 383 384 385 386 387 388 389 390 | |
SequenceGenerator ¶
Bases: Protocol
Protocol for sequence generators.
A sequence generator controls how monomers are arranged in a single chain. It encapsulates monomer reaction/selection probabilities and generates monomer sequences given a desired degree of polymerization (DP).
This is the bottom layer in the three-layer architecture, responsible only for local monomer selection and reaction probabilities.
expected_composition ¶
expected_composition()
Optional: Return expected long-chain monomer fractions.
Used for rough mass estimates. Returns a dictionary mapping monomer identifiers to their expected fraction in long chains.
Returns:
| Type | Description |
|---|---|
dict[str, float]
|
Dictionary mapping monomer identifiers to expected fractions |
Source code in src/molpy/builder/polymer/sequence_generator.py
46 47 48 49 50 51 52 53 54 55 56 | |
generate_sequence ¶
generate_sequence(dp, rng)
Generate a monomer sequence of specified degree of polymerization.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
dp
|
int
|
Degree of polymerization (number of monomers) |
required |
rng
|
Random
|
Random number generator for reproducible sampling |
required |
Returns:
| Type | Description |
|---|---|
list[str]
|
List of monomer identifiers (or monomer keys as strings) |
Source code in src/molpy/builder/polymer/sequence_generator.py
29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 | |
StochasticChain
dataclass
¶
StochasticChain(polymer, dp, mass, growth_history=list())
Result of stochastic BFS growth.
Attributes:
| Name | Type | Description |
|---|---|---|
polymer |
Atomistic
|
The assembled Atomistic structure |
dp |
int
|
Degree of polymerization (number of monomers added) |
mass |
float
|
Total molecular weight (g/mol) |
growth_history |
list[dict[str, Any]]
|
Metadata for each monomer addition step |
SystemPlan
dataclass
¶
SystemPlan(chains, total_mass, target_mass)
Represents a complete system plan with all chains.
Attributes:
| Name | Type | Description |
|---|---|---|
chains |
list[Chain]
|
List of all chains in the system |
total_mass |
float
|
Total mass of all chains (g/mol) |
target_mass |
float
|
Target total mass that was requested (g/mol) |
SystemPlanner ¶
SystemPlanner(chain_generator, target_total_mass, max_rel_error=0.02, max_chains=None, enable_trimming=True)
Top layer: System-level planner.
Responsible for: - Enforcing a target total mass for the overall system - Iteratively requesting chains from PolydisperseChainGenerator - Maintaining a running sum of total mass - Stopping when mass reaches target window, and optionally trimming the final chain
Does NOT micromanage sequence probabilities or DP distribution; only orchestrates at the ensemble level.
Initialize system planner.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
chain_generator
|
PolydisperseChainGenerator
|
Chain generator for building chains |
required |
target_total_mass
|
float
|
Target total system mass (g/mol) |
required |
max_rel_error
|
float
|
Maximum relative error allowed (default 0.02 = 2%) |
0.02
|
max_chains
|
int | None
|
Maximum number of chains to generate (None = no limit) |
None
|
enable_trimming
|
bool
|
Whether to enable chain trimming to better hit target mass |
True
|
Source code in src/molpy/builder/polymer/system.py
763 764 765 766 767 768 769 770 771 772 773 774 775 776 777 778 779 780 781 782 783 784 785 | |
plan_system ¶
plan_system(rng)
Repeatedly ask chain_generator for new chains until accumulated mass reaches target_total_mass within max_rel_error.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
rng
|
Random
|
Random number generator |
required |
Returns:
| Type | Description |
|---|---|
SystemPlan
|
SystemPlan with all chains and total mass |
Source code in src/molpy/builder/polymer/system.py
787 788 789 790 791 792 793 794 795 796 797 798 799 800 801 802 803 804 805 806 807 808 809 810 811 812 813 814 815 816 817 818 819 820 821 822 823 824 825 826 827 828 | |
TableConnector ¶
TableConnector(rules, fallback=None)
Bases: Connector
Rule-based port selection using a lookup table.
Maps (left_label, right_label) -> (left_port, right_port [, bond_kind])
Example
rules = { ("A", "B"): ("1", "2"), ("B", "A"): ("3", "1", "="), # with bond kind override ("T", "A"): ("t", "1"), } connector = TableConnector(rules, fallback=AutoConnector())
Initialize table connector.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
rules
|
Mapping[tuple[str, str], tuple[str, str] | tuple[str, str, BondKind]]
|
Mapping from (left_label, right_label) to port specifications |
required |
fallback
|
Connector | None
|
Optional connector to try if pair not in rules |
None
|
Source code in src/molpy/builder/polymer/connectors.py
200 201 202 203 204 205 206 207 208 209 210 211 212 213 | |
select_ports ¶
select_ports(left, right, left_ports, right_ports, ctx)
Select ports using table lookup.
Source code in src/molpy/builder/polymer/connectors.py
215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 | |
UniformPolydisperse ¶
UniformPolydisperse(min_dp, max_dp, random_seed=None)
Bases: DPDistribution
Uniform distribution over degree of polymerization (DP).
Implements :class:DPDistribution - sampling is done directly in
DP space. All integer DP values between :math:N_{\min} and
:math:N_{\max} (inclusive) are equally likely.
The probability mass function (PMF) is
.. math::
P(N = k) =
\begin{cases}
\dfrac{1}{N_{\max} - N_{\min} + 1},
& N_{\min} \le k \le N_{\max}, \\
0, & \text{otherwise},
\end{cases}
where :math:N denotes the degree of polymerization.
Parameters¶
min_dp:
Lower bound :math:N_{\min} for the degree of polymerization
(must be :math:\ge 1).
max_dp:
Upper bound :math:N_{\max} for the degree of polymerization
(must satisfy :math:N_{\max} \ge N_{\min}).
random_seed:
Optional random seed used when sampling.
Initialize uniform DP distribution.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
min_dp
|
int
|
Minimum degree of polymerization (must be >= 1) |
required |
max_dp
|
int
|
Maximum degree of polymerization (must be >= min_dp) |
required |
random_seed
|
int | None
|
Random seed for reproducible sampling (optional) |
None
|
Raises:
| Type | Description |
|---|---|
ValueError
|
If min_dp < 1 or max_dp < min_dp |
Source code in src/molpy/builder/polymer/system.py
460 461 462 463 464 465 466 467 468 469 470 471 472 473 474 475 476 477 478 479 480 481 482 483 484 | |
dp_pmf ¶
dp_pmf(dp_array)
Compute the probability mass function (PMF) over DP values.
The PMF assigns equal probability to all integer DP values between min_dp and max_dp (inclusive), and zero probability outside this range.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
dp_array
|
ndarray
|
Array of DP values (typically integer, but can be float) |
required |
Returns:
| Type | Description |
|---|---|
ndarray
|
Array of PMF values, same shape as dp_array. |
ndarray
|
PMF[i] = 1 / (max_dp - min_dp + 1) if min_dp <= dp_array[i] <= max_dp, 0 otherwise. |
Source code in src/molpy/builder/polymer/system.py
486 487 488 489 490 491 492 493 494 495 496 497 498 499 500 501 502 503 504 505 506 507 508 509 510 511 512 513 514 | |
sample_dp ¶
sample_dp(rng)
Sample degree of polymerization from uniform distribution.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
rng
|
Generator
|
NumPy random number generator |
required |
Returns:
| Type | Description |
|---|---|
int
|
Degree of polymerization (>= 1) |
Source code in src/molpy/builder/polymer/system.py
517 518 519 520 521 522 523 524 525 526 | |
WeightedSequenceGenerator ¶
WeightedSequenceGenerator(weights=None, n_monomers=None, monomer_weights=None)
Sequence generator based on monomer weights/proportions.
This generator selects monomers based on their relative weights. Each selection is independent (no memory of previous selections).
Conforms to the SequenceGenerator protocol.
Initialize weighted sequence generator.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
weights
|
dict[int, float] | None
|
Dictionary mapping monomer index to selection weight (legacy format) |
None
|
n_monomers
|
int | None
|
Total number of available monomers (legacy format) |
None
|
monomer_weights
|
dict[str, float] | None
|
Dictionary mapping monomer identifier to selection weight (new format) |
None
|
Note: Either (weights, n_monomers) or monomer_weights should be provided. If monomer_weights is provided, it takes precedence.
Source code in src/molpy/builder/polymer/sequence_generator.py
69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 | |
expected_composition ¶
expected_composition()
Return expected long-chain monomer fractions.
Returns:
| Type | Description |
|---|---|
dict[str, float]
|
Dictionary mapping monomer identifiers to their expected fractions |
Source code in src/molpy/builder/polymer/sequence_generator.py
145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 | |
generate_sequence ¶
generate_sequence(dp, rng)
Generate a sequence of specified degree of polymerization.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
dp
|
int
|
Degree of polymerization (number of monomers) |
required |
rng
|
Random
|
Random number generator for reproducible sampling |
required |
Returns:
| Type | Description |
|---|---|
list[str]
|
list of monomer identifiers (strings) |
Source code in src/molpy/builder/polymer/sequence_generator.py
122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 | |