samgen 0.1.2__tar.gz

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (57) hide show
  1. samgen-0.1.2/LICENSE +28 -0
  2. samgen-0.1.2/MANIFEST.in +6 -0
  3. samgen-0.1.2/PKG-INFO +238 -0
  4. samgen-0.1.2/README.md +217 -0
  5. samgen-0.1.2/configs/ch3_density.yaml +43 -0
  6. samgen-0.1.2/configs/ch3_grid.yaml +33 -0
  7. samgen-0.1.2/configs/ch3_onesided.yaml +26 -0
  8. samgen-0.1.2/configs/example-patterns/dense-grid.dat +36 -0
  9. samgen-0.1.2/configs/example-patterns/four-lig.dat +12 -0
  10. samgen-0.1.2/configs/example-patterns/one-lig.dat +12 -0
  11. samgen-0.1.2/configs/example-patterns/three-lig.dat +12 -0
  12. samgen-0.1.2/configs/example-patterns/two-lig.dat +12 -0
  13. samgen-0.1.2/configs/inputs/ch3.gro +24 -0
  14. samgen-0.1.2/configs/inputs/ch3.itp +147 -0
  15. samgen-0.1.2/configs/inputs/coh.gro +23 -0
  16. samgen-0.1.2/configs/inputs/coh.itp +150 -0
  17. samgen-0.1.2/configs/inputs/pattern.dat +12 -0
  18. samgen-0.1.2/pyproject.toml +44 -0
  19. samgen-0.1.2/samgen/__init__.py +17 -0
  20. samgen-0.1.2/samgen/_build.py +51 -0
  21. samgen-0.1.2/samgen/cli.py +118 -0
  22. samgen-0.1.2/samgen/core/__init__.py +1 -0
  23. samgen-0.1.2/samgen/core/anchor.py +140 -0
  24. samgen-0.1.2/samgen/core/gro.py +98 -0
  25. samgen-0.1.2/samgen/core/lattice.py +107 -0
  26. samgen-0.1.2/samgen/core/molecule.py +81 -0
  27. samgen-0.1.2/samgen/core/orient.py +89 -0
  28. samgen-0.1.2/samgen/core/periodicity.py +133 -0
  29. samgen-0.1.2/samgen/core/topfile.py +127 -0
  30. samgen-0.1.2/samgen/design/__init__.py +44 -0
  31. samgen-0.1.2/samgen/design/density.py +130 -0
  32. samgen-0.1.2/samgen/design/fraction.py +26 -0
  33. samgen-0.1.2/samgen/design/grid.py +36 -0
  34. samgen-0.1.2/samgen/design/multilig.py +14 -0
  35. samgen-0.1.2/samgen/design/uniform.py +13 -0
  36. samgen-0.1.2/samgen/geometry.py +271 -0
  37. samgen-0.1.2/samgen/gmx.py +56 -0
  38. samgen-0.1.2/samgen/interactive.py +136 -0
  39. samgen-0.1.2/samgen/topology.py +179 -0
  40. samgen-0.1.2/samgen.egg-info/PKG-INFO +238 -0
  41. samgen-0.1.2/samgen.egg-info/SOURCES.txt +55 -0
  42. samgen-0.1.2/samgen.egg-info/dependency_links.txt +1 -0
  43. samgen-0.1.2/samgen.egg-info/entry_points.txt +2 -0
  44. samgen-0.1.2/samgen.egg-info/requires.txt +6 -0
  45. samgen-0.1.2/samgen.egg-info/top_level.txt +1 -0
  46. samgen-0.1.2/setup.cfg +4 -0
  47. samgen-0.1.2/tests/test_core.py +99 -0
  48. samgen-0.1.2/tests/test_density.py +249 -0
  49. samgen-0.1.2/tests/test_designs.py +133 -0
  50. samgen-0.1.2/tests/test_interactive.py +54 -0
  51. samgen-0.1.2/tests/test_orient.py +63 -0
  52. samgen-0.1.2/tests/test_periodicity.py +100 -0
  53. samgen-0.1.2/tests/test_placement.py +16 -0
  54. samgen-0.1.2/tests/test_smoke.py +11 -0
  55. samgen-0.1.2/tests/test_synthetic.py +16 -0
  56. samgen-0.1.2/tests/test_topology.py +124 -0
  57. samgen-0.1.2/tests/test_twosided.py +165 -0
samgen-0.1.2/LICENSE ADDED
@@ -0,0 +1,28 @@
1
+ BSD 3-Clause License
2
+
3
+ Copyright (c) 2026, Mayank Vats
4
+
5
+ Redistribution and use in source and binary forms, with or without
6
+ modification, are permitted provided that the following conditions are met:
7
+
8
+ 1. Redistributions of source code must retain the above copyright notice, this
9
+ list of conditions and the following disclaimer.
10
+
11
+ 2. Redistributions in binary form must reproduce the above copyright notice,
12
+ this list of conditions and the following disclaimer in the documentation
13
+ and/or other materials provided with the distribution.
14
+
15
+ 3. Neither the name of the copyright holder nor the names of its
16
+ contributors may be used to endorse or promote products derived from
17
+ this software without specific prior written permission.
18
+
19
+ THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
20
+ AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
21
+ IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
22
+ DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
23
+ FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
24
+ DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
25
+ SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
26
+ CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
27
+ OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
28
+ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
@@ -0,0 +1,6 @@
1
+ graft configs
2
+ include README.md
3
+ include LICENSE
4
+ global-exclude *.manifest.json
5
+ global-exclude sam.gro sam-*.gro topol.top
6
+ global-exclude *.pyc
samgen-0.1.2/PKG-INFO ADDED
@@ -0,0 +1,238 @@
1
+ Metadata-Version: 2.4
2
+ Name: samgen
3
+ Version: 0.1.2
4
+ Summary: Build self-assembled monolayer (SAM) surfaces for GROMACS
5
+ Author-email: Mayank Vats <18255879+max3925vats@users.noreply.github.com>
6
+ License-Expression: BSD-3-Clause
7
+ Project-URL: Repository, https://github.com/max3925vats/samgen
8
+ Keywords: SAM,self-assembled-monolayer,GROMACS,molecular-dynamics,Au(111)
9
+ Classifier: Programming Language :: Python :: 3
10
+ Classifier: Intended Audience :: Science/Research
11
+ Classifier: Topic :: Scientific/Engineering :: Chemistry
12
+ Requires-Python: >=3.11
13
+ Description-Content-Type: text/markdown
14
+ License-File: LICENSE
15
+ Requires-Dist: numpy>=1.24
16
+ Requires-Dist: scipy>=1.10
17
+ Requires-Dist: pyyaml>=6.0
18
+ Provides-Extra: dev
19
+ Requires-Dist: pytest>=7.0; extra == "dev"
20
+ Dynamic: license-file
21
+
22
+ # samgen
23
+
24
+ [![tests](https://github.com/max3925vats/samgen/actions/workflows/tests.yml/badge.svg)](https://github.com/max3925vats/samgen/actions/workflows/tests.yml)
25
+ [![PyPI](https://img.shields.io/pypi/v/samgen)](https://pypi.org/project/samgen/)
26
+ [![Python 3.11+](https://img.shields.io/badge/python-3.11%2B-blue)](https://www.python.org/)
27
+ [![License: BSD-3-Clause](https://img.shields.io/badge/license-BSD--3--Clause-green)](LICENSE)
28
+
29
+ Build self-assembled monolayer (SAM) surfaces as GROMACS `.gro` / `.top` files.
30
+
31
+ `samgen`'s job is to place strands correctly on a periodic Au(111) grid per a
32
+ chosen design, for one-sided and two-sided (shared-sulfur midplane) monolayers.
33
+ Orientation/tilt and topology assembly are provided as conveniences that **you
34
+ must verify** before running MD.
35
+
36
+ ## What it does
37
+
38
+ - **Hexagonal Au(111) lattice** — `(√3×√3)R30°` tiling with the staggered-row
39
+ offset, periodic-correct box.
40
+ - **SAM orientation** — apply the tilt (`alpha` ≈ 28°, `beta` ≈ 53°; Love et
41
+ al. 2005) with an always-on orientation sanity check and opt-in,
42
+ chemistry-anchored canonicalization.
43
+ - **Five placement designs** — density (default), uniform, two-component grid,
44
+ fraction/random (seeded), and multi-ligand (3+).
45
+ - **Anchor / cap detection** — prompt-first with consent-to-guess.
46
+ - **Topology assembly** — residue reordering, merged `[defaults]`/`[atomtypes]`,
47
+ per-component bonded params, and a `[molecules]` block with correct counts,
48
+ optionally gated by `gmx grompp`.
49
+ - **Periodicity check** — verifies the built surface tiles seamlessly under PBC.
50
+ - **Two-sided SAMs** — fuse two arms onto a single shared sulfur via a proper,
51
+ chirality-preserving 180° rotation; emits geometry for you to parameterize.
52
+
53
+ ## Install
54
+
55
+ Requires **Python 3.11+**. Dependencies (`numpy`, `scipy`, `pyyaml`) install
56
+ automatically.
57
+
58
+ ```bash
59
+ # from PyPI
60
+ pip install samgen
61
+
62
+ # or the latest from GitHub
63
+ pip install git+https://github.com/max3925vats/samgen.git
64
+
65
+ # or editable, for development (adds pytest)
66
+ git clone https://github.com/max3925vats/samgen.git
67
+ cd samgen
68
+ pip install -e ".[dev]"
69
+ ```
70
+
71
+ **GROMACS is optional** — it's only used for the `gmx grompp` topology check
72
+ (`--validate`) and any boxing/centering you do yourself. Install it however you
73
+ like (e.g. `brew install gromacs`, conda, or your cluster module).
74
+
75
+ ## Quick start
76
+
77
+ The default design places a methyl-terminated (`ch3`) ligand on a
78
+ hydroxyl-terminated (`coh`) matrix at a target areal density:
79
+
80
+ ```bash
81
+ samgen build configs/ch3_density.yaml -o sam.gro --top topol.top
82
+ # -> 132 CH3 ligands on a COH matrix (528 strands), with topol.top
83
+ ```
84
+
85
+ ## Three stages (run together or separately)
86
+
87
+ All stages share one config, so you can run them piecewise or in one shot:
88
+
89
+ ```bash
90
+ # 1) tile the surface geometry (no force field needed)
91
+ samgen geometry configs/ch3_grid.yaml -o sam.gro
92
+
93
+ # 2) assemble the topology for that surface (--validate runs the gmx grompp gate)
94
+ samgen topology configs/ch3_grid.yaml --gro sam.gro -o topol.top --validate
95
+
96
+ # ...or do both at once:
97
+ samgen build configs/ch3_grid.yaml -o sam.gro --top topol.top
98
+
99
+ # two-sided (shared-S) strand + geometry-only surface:
100
+ samgen twosided configs/ch3_grid.yaml --component ch3 -o strand.gro --surface twosided-sam.gro
101
+ ```
102
+
103
+ For `twosided`, the anchor is prompt-first: it uses the config's `anchor:` if
104
+ set, otherwise prompts in an interactive terminal and only auto-detects with your
105
+ consent. In batch (no TTY) it requires `anchor:` in the config unless
106
+ `allow_anchor_autodetect: true`.
107
+
108
+ From Python:
109
+
110
+ ```python
111
+ from samgen import generate_geometry, assemble_topology, build
112
+ ```
113
+
114
+ ## Placement designs
115
+
116
+ A design decides which component sits at each Au(111) lattice site. Set it in the
117
+ `design:` block of the config.
118
+
119
+ - **`density`** (default) — ligands at a target areal density (ligands/nm²),
120
+ placed on a uniform sub-lattice of the gold sites. samgen keeps the grid
121
+ perfectly periodic; the realized density is quantized to the Au spacing and is
122
+ reported. If your box and density don't tile uniquely, samgen offers two
123
+ periodic choices (a smaller box with fewer ligands, or a larger box with more)
124
+ and you pick — or set `density_choice: below|above` for batch runs.
125
+
126
+ ```yaml
127
+ design: {type: density, base: coh, ligand: ch3, density: 1.0}
128
+ ```
129
+
130
+ Example: density 1.0/nm² in a ~10×10 nm box → a 22×24 Au grid, stride 2 →
131
+ **11×12 = 132 ligands** (box 10.978×10.368 nm in rounded-lattice mode).
132
+
133
+ For full manual control, `ligand_grid: [nx, ny]` places exactly nx×ny ligands
134
+ (the box is grown so the grid stays periodic; per-axis spacing may differ, so
135
+ anisotropic grids are allowed). It overrides `density` when both are set.
136
+
137
+ - **`fraction`** — random ligands at a target fraction (0–1), seeded for
138
+ reproducibility.
139
+
140
+ ```yaml
141
+ design: {type: fraction, base: coh, ligand: ch3, fraction: 0.25, seed: 42}
142
+ ```
143
+
144
+ - **`uniform`** — one component on every site.
145
+
146
+ ```yaml
147
+ design: {type: uniform, component: ch3}
148
+ ```
149
+
150
+ - **`grid`** — two components from a 0/1 pattern file.
151
+
152
+ ```yaml
153
+ design: {type: grid, pattern: inputs/pattern.dat, mapping: {0: coh, 1: ch3}}
154
+ ```
155
+
156
+ - **`multilig`** — 3+ components from an integer pattern file.
157
+
158
+ The config `box: {x, y}` sets the surface area; the lattice fills it and snaps
159
+ x,y to whole Au cells for periodicity. The pattern file (for `grid`/`multilig`)
160
+ does not set the box — it is sampled per site and padded with the base component
161
+ beyond its extent.
162
+
163
+ ### Lattice constants
164
+
165
+ The default Au(111) spacing is the exact `colsep = √3·a` (`a = 0.288 nm`). Set
166
+ `lattice: {rounded: true}` to use rounded constants (`colsep = 0.499`) when you
167
+ need to reproduce a specific box exactly (e.g. 10.978 × 10.368 nm); ligand counts
168
+ are identical either way.
169
+
170
+ ### Periodicity check
171
+
172
+ Every build is checked for periodicity under PBC (on by default, warn-only): the
173
+ box is a whole Au-lattice multiple, the ligand grid has no seam (uniform
174
+ nearest-neighbour spacing including the wrap), and no two strands fall closer
175
+ than `min_spacing` across the periodic boundary. Configure or disable it:
176
+
177
+ ```yaml
178
+ periodicity_check: {enabled: true, on_failure: warn, min_spacing: 0.40, tol: 0.002}
179
+ ```
180
+
181
+ Set `on_failure: error` to make a non-periodic surface a hard failure instead of
182
+ a warning.
183
+
184
+ ## Input files
185
+
186
+ The examples ship with ready-to-run strands under `configs/inputs/`: a
187
+ methyl-terminated (`ch3`) and a hydroxyl-terminated (`coh`) alkanethiol, each as
188
+ a single-strand `.gro` (pre-oriented along z) plus a self-contained `.itp`, and a
189
+ design `pattern.dat` for the grid. So `configs/ch3_density.yaml`,
190
+ `configs/ch3_onesided.yaml`, and `configs/ch3_grid.yaml` run out of the box.
191
+
192
+ To use **your own** molecules, drop a single-strand `.gro` (canonically oriented
193
+ along z, or pre-tilted with `apply_tilt: false`) and a matching `.itp`/`.top`
194
+ into `configs/inputs/` and point the config's component paths at them.
195
+
196
+ ## You finish run-readiness
197
+
198
+ `samgen` builds the geometry and assembles a topology, but deliberately leaves two
199
+ simulation-setup steps to you (it prints a reminder when you assemble a
200
+ topology):
201
+
202
+ 1. **Position restraints** — restrain the anchor sulfur (and typically the 7th
203
+ chain carbon) so the SAM stays anchored. Add a `[ position_restraints ]`
204
+ block / `#ifdef POSRES` to each component `.itp` and define `POSRES` in your
205
+ `.mdp`.
206
+ 2. **Center / box the structure** — e.g.
207
+ `gmx editconf -f sam.gro -o centered.gro -c -d <pad>` before
208
+ solvation/equilibration.
209
+
210
+ ## Orientation applicability
211
+
212
+ samgen derives a strand's tilt/twist frame from the anchor sulfur and the first N
213
+ backbone carbons of a linear alkyl spacer (default N=9, set per component with
214
+ `backbone_carbons`). This matches the canonical alkanethiol-on-Au(111) SAM motif.
215
+ Strands that depart from it — non-thiol anchors; branched, short, rigid, or
216
+ aromatic spacers; or headgroups attached within the first N carbons — may not be
217
+ oriented correctly. In those cases, supply a pre-oriented strand
218
+ (`apply_tilt: false`) or verify and correct the generated frame yourself. samgen
219
+ does not guarantee orientation for arbitrary strand chemistries.
220
+
221
+ ## Surface types
222
+
223
+ samgen places strands on a periodic Au(111) grid — that placement is the
224
+ guarantee. One-sided and two-sided (shared-sulfur midplane) surfaces are
225
+ supported. Orientation and topology assembly are provided as conveniences;
226
+ **verify both before running MD** (see "You finish run-readiness" and
227
+ "Orientation applicability" above).
228
+
229
+ ## Two-sided SAMs
230
+
231
+ The tool builds the **geometry** of a two-sided (shared-S) strand and surface.
232
+ Because forming the shared sulfur removes the methyl caps and changes local
233
+ charges, you **parameterize the generated strand yourself** (acpype/RESP), then
234
+ hand the `.itp`/`.top` back to assemble the integrated topology.
235
+
236
+ ## License
237
+
238
+ BSD-3-Clause — see [LICENSE](LICENSE).
samgen-0.1.2/README.md ADDED
@@ -0,0 +1,217 @@
1
+ # samgen
2
+
3
+ [![tests](https://github.com/max3925vats/samgen/actions/workflows/tests.yml/badge.svg)](https://github.com/max3925vats/samgen/actions/workflows/tests.yml)
4
+ [![PyPI](https://img.shields.io/pypi/v/samgen)](https://pypi.org/project/samgen/)
5
+ [![Python 3.11+](https://img.shields.io/badge/python-3.11%2B-blue)](https://www.python.org/)
6
+ [![License: BSD-3-Clause](https://img.shields.io/badge/license-BSD--3--Clause-green)](LICENSE)
7
+
8
+ Build self-assembled monolayer (SAM) surfaces as GROMACS `.gro` / `.top` files.
9
+
10
+ `samgen`'s job is to place strands correctly on a periodic Au(111) grid per a
11
+ chosen design, for one-sided and two-sided (shared-sulfur midplane) monolayers.
12
+ Orientation/tilt and topology assembly are provided as conveniences that **you
13
+ must verify** before running MD.
14
+
15
+ ## What it does
16
+
17
+ - **Hexagonal Au(111) lattice** — `(√3×√3)R30°` tiling with the staggered-row
18
+ offset, periodic-correct box.
19
+ - **SAM orientation** — apply the tilt (`alpha` ≈ 28°, `beta` ≈ 53°; Love et
20
+ al. 2005) with an always-on orientation sanity check and opt-in,
21
+ chemistry-anchored canonicalization.
22
+ - **Five placement designs** — density (default), uniform, two-component grid,
23
+ fraction/random (seeded), and multi-ligand (3+).
24
+ - **Anchor / cap detection** — prompt-first with consent-to-guess.
25
+ - **Topology assembly** — residue reordering, merged `[defaults]`/`[atomtypes]`,
26
+ per-component bonded params, and a `[molecules]` block with correct counts,
27
+ optionally gated by `gmx grompp`.
28
+ - **Periodicity check** — verifies the built surface tiles seamlessly under PBC.
29
+ - **Two-sided SAMs** — fuse two arms onto a single shared sulfur via a proper,
30
+ chirality-preserving 180° rotation; emits geometry for you to parameterize.
31
+
32
+ ## Install
33
+
34
+ Requires **Python 3.11+**. Dependencies (`numpy`, `scipy`, `pyyaml`) install
35
+ automatically.
36
+
37
+ ```bash
38
+ # from PyPI
39
+ pip install samgen
40
+
41
+ # or the latest from GitHub
42
+ pip install git+https://github.com/max3925vats/samgen.git
43
+
44
+ # or editable, for development (adds pytest)
45
+ git clone https://github.com/max3925vats/samgen.git
46
+ cd samgen
47
+ pip install -e ".[dev]"
48
+ ```
49
+
50
+ **GROMACS is optional** — it's only used for the `gmx grompp` topology check
51
+ (`--validate`) and any boxing/centering you do yourself. Install it however you
52
+ like (e.g. `brew install gromacs`, conda, or your cluster module).
53
+
54
+ ## Quick start
55
+
56
+ The default design places a methyl-terminated (`ch3`) ligand on a
57
+ hydroxyl-terminated (`coh`) matrix at a target areal density:
58
+
59
+ ```bash
60
+ samgen build configs/ch3_density.yaml -o sam.gro --top topol.top
61
+ # -> 132 CH3 ligands on a COH matrix (528 strands), with topol.top
62
+ ```
63
+
64
+ ## Three stages (run together or separately)
65
+
66
+ All stages share one config, so you can run them piecewise or in one shot:
67
+
68
+ ```bash
69
+ # 1) tile the surface geometry (no force field needed)
70
+ samgen geometry configs/ch3_grid.yaml -o sam.gro
71
+
72
+ # 2) assemble the topology for that surface (--validate runs the gmx grompp gate)
73
+ samgen topology configs/ch3_grid.yaml --gro sam.gro -o topol.top --validate
74
+
75
+ # ...or do both at once:
76
+ samgen build configs/ch3_grid.yaml -o sam.gro --top topol.top
77
+
78
+ # two-sided (shared-S) strand + geometry-only surface:
79
+ samgen twosided configs/ch3_grid.yaml --component ch3 -o strand.gro --surface twosided-sam.gro
80
+ ```
81
+
82
+ For `twosided`, the anchor is prompt-first: it uses the config's `anchor:` if
83
+ set, otherwise prompts in an interactive terminal and only auto-detects with your
84
+ consent. In batch (no TTY) it requires `anchor:` in the config unless
85
+ `allow_anchor_autodetect: true`.
86
+
87
+ From Python:
88
+
89
+ ```python
90
+ from samgen import generate_geometry, assemble_topology, build
91
+ ```
92
+
93
+ ## Placement designs
94
+
95
+ A design decides which component sits at each Au(111) lattice site. Set it in the
96
+ `design:` block of the config.
97
+
98
+ - **`density`** (default) — ligands at a target areal density (ligands/nm²),
99
+ placed on a uniform sub-lattice of the gold sites. samgen keeps the grid
100
+ perfectly periodic; the realized density is quantized to the Au spacing and is
101
+ reported. If your box and density don't tile uniquely, samgen offers two
102
+ periodic choices (a smaller box with fewer ligands, or a larger box with more)
103
+ and you pick — or set `density_choice: below|above` for batch runs.
104
+
105
+ ```yaml
106
+ design: {type: density, base: coh, ligand: ch3, density: 1.0}
107
+ ```
108
+
109
+ Example: density 1.0/nm² in a ~10×10 nm box → a 22×24 Au grid, stride 2 →
110
+ **11×12 = 132 ligands** (box 10.978×10.368 nm in rounded-lattice mode).
111
+
112
+ For full manual control, `ligand_grid: [nx, ny]` places exactly nx×ny ligands
113
+ (the box is grown so the grid stays periodic; per-axis spacing may differ, so
114
+ anisotropic grids are allowed). It overrides `density` when both are set.
115
+
116
+ - **`fraction`** — random ligands at a target fraction (0–1), seeded for
117
+ reproducibility.
118
+
119
+ ```yaml
120
+ design: {type: fraction, base: coh, ligand: ch3, fraction: 0.25, seed: 42}
121
+ ```
122
+
123
+ - **`uniform`** — one component on every site.
124
+
125
+ ```yaml
126
+ design: {type: uniform, component: ch3}
127
+ ```
128
+
129
+ - **`grid`** — two components from a 0/1 pattern file.
130
+
131
+ ```yaml
132
+ design: {type: grid, pattern: inputs/pattern.dat, mapping: {0: coh, 1: ch3}}
133
+ ```
134
+
135
+ - **`multilig`** — 3+ components from an integer pattern file.
136
+
137
+ The config `box: {x, y}` sets the surface area; the lattice fills it and snaps
138
+ x,y to whole Au cells for periodicity. The pattern file (for `grid`/`multilig`)
139
+ does not set the box — it is sampled per site and padded with the base component
140
+ beyond its extent.
141
+
142
+ ### Lattice constants
143
+
144
+ The default Au(111) spacing is the exact `colsep = √3·a` (`a = 0.288 nm`). Set
145
+ `lattice: {rounded: true}` to use rounded constants (`colsep = 0.499`) when you
146
+ need to reproduce a specific box exactly (e.g. 10.978 × 10.368 nm); ligand counts
147
+ are identical either way.
148
+
149
+ ### Periodicity check
150
+
151
+ Every build is checked for periodicity under PBC (on by default, warn-only): the
152
+ box is a whole Au-lattice multiple, the ligand grid has no seam (uniform
153
+ nearest-neighbour spacing including the wrap), and no two strands fall closer
154
+ than `min_spacing` across the periodic boundary. Configure or disable it:
155
+
156
+ ```yaml
157
+ periodicity_check: {enabled: true, on_failure: warn, min_spacing: 0.40, tol: 0.002}
158
+ ```
159
+
160
+ Set `on_failure: error` to make a non-periodic surface a hard failure instead of
161
+ a warning.
162
+
163
+ ## Input files
164
+
165
+ The examples ship with ready-to-run strands under `configs/inputs/`: a
166
+ methyl-terminated (`ch3`) and a hydroxyl-terminated (`coh`) alkanethiol, each as
167
+ a single-strand `.gro` (pre-oriented along z) plus a self-contained `.itp`, and a
168
+ design `pattern.dat` for the grid. So `configs/ch3_density.yaml`,
169
+ `configs/ch3_onesided.yaml`, and `configs/ch3_grid.yaml` run out of the box.
170
+
171
+ To use **your own** molecules, drop a single-strand `.gro` (canonically oriented
172
+ along z, or pre-tilted with `apply_tilt: false`) and a matching `.itp`/`.top`
173
+ into `configs/inputs/` and point the config's component paths at them.
174
+
175
+ ## You finish run-readiness
176
+
177
+ `samgen` builds the geometry and assembles a topology, but deliberately leaves two
178
+ simulation-setup steps to you (it prints a reminder when you assemble a
179
+ topology):
180
+
181
+ 1. **Position restraints** — restrain the anchor sulfur (and typically the 7th
182
+ chain carbon) so the SAM stays anchored. Add a `[ position_restraints ]`
183
+ block / `#ifdef POSRES` to each component `.itp` and define `POSRES` in your
184
+ `.mdp`.
185
+ 2. **Center / box the structure** — e.g.
186
+ `gmx editconf -f sam.gro -o centered.gro -c -d <pad>` before
187
+ solvation/equilibration.
188
+
189
+ ## Orientation applicability
190
+
191
+ samgen derives a strand's tilt/twist frame from the anchor sulfur and the first N
192
+ backbone carbons of a linear alkyl spacer (default N=9, set per component with
193
+ `backbone_carbons`). This matches the canonical alkanethiol-on-Au(111) SAM motif.
194
+ Strands that depart from it — non-thiol anchors; branched, short, rigid, or
195
+ aromatic spacers; or headgroups attached within the first N carbons — may not be
196
+ oriented correctly. In those cases, supply a pre-oriented strand
197
+ (`apply_tilt: false`) or verify and correct the generated frame yourself. samgen
198
+ does not guarantee orientation for arbitrary strand chemistries.
199
+
200
+ ## Surface types
201
+
202
+ samgen places strands on a periodic Au(111) grid — that placement is the
203
+ guarantee. One-sided and two-sided (shared-sulfur midplane) surfaces are
204
+ supported. Orientation and topology assembly are provided as conveniences;
205
+ **verify both before running MD** (see "You finish run-readiness" and
206
+ "Orientation applicability" above).
207
+
208
+ ## Two-sided SAMs
209
+
210
+ The tool builds the **geometry** of a two-sided (shared-S) strand and surface.
211
+ Because forming the shared sulfur removes the methyl caps and changes local
212
+ charges, you **parameterize the generated strand yourself** (acpype/RESP), then
213
+ hand the `.itp`/`.top` back to assemble the integrated topology.
214
+
215
+ ## License
216
+
217
+ BSD-3-Clause — see [LICENSE](LICENSE).
@@ -0,0 +1,43 @@
1
+ # configs/ch3_density.yaml
2
+ # Default design: areal-density placement of a CH3 ligand on a COH base.
3
+ # Paths resolve relative to this file. Bundled inputs are pre-oriented along z.
4
+ # samgen keeps the ligand grid perfectly periodic on Au(111); if your box +
5
+ # density don't tile uniquely it offers a 'below'/'above' choice (interactive),
6
+ # or set design.density_choice for batch runs.
7
+ lattice:
8
+ a: 0.288
9
+ tilt_alpha: 28
10
+ tilt_beta: 53
11
+ # rounded: true # opt in for exact legacy box dims (10.978 x 10.368)
12
+ box:
13
+ x: 10.0
14
+ y: 10.0
15
+ z: 10.0
16
+ leaflets: 1
17
+ components:
18
+ coh:
19
+ gro: inputs/coh.gro
20
+ itp: inputs/coh.itp
21
+ resname: COH
22
+ anchor: S13
23
+ ch3:
24
+ gro: inputs/ch3.gro
25
+ itp: inputs/ch3.itp
26
+ resname: CH3
27
+ anchor: S12
28
+ design:
29
+ type: density # the default; may be omitted
30
+ base: coh
31
+ ligand: ch3
32
+ density: 1.0 # ligands/nm^2
33
+ # density_choice: above # batch pick when the box doesn't tile uniquely
34
+ # ligand_grid: [11, 12] # explicit override (exact nx x ny; wins over density)
35
+ output:
36
+ gro: sam.gro
37
+ order: [COH, CH3]
38
+ periodicity_check: # on by default, warn-only; shown here for reference
39
+ enabled: true
40
+ on_failure: warn # warn | error
41
+ min_spacing: 0.40 # nm
42
+ tol: 0.002 # nm
43
+ allow_anchor_autodetect: false
@@ -0,0 +1,33 @@
1
+ # Two-component mixed CH3/OH SAM from a 0/1 design grid:
2
+ # methyl-terminated (CH3) ligand on a hydroxyl-terminated (COH) base.
3
+ # Paths are resolved relative to this config file's directory.
4
+ # The bundled inputs/ strands are pre-oriented (chain along z); samgen applies
5
+ # the SAM tilt. Swap in your own strand .gro/.itp the same way.
6
+ lattice:
7
+ a: 0.288
8
+ tilt_alpha: 28
9
+ tilt_beta: 53
10
+ box:
11
+ x: 5.0
12
+ y: 5.0
13
+ z: 10.0
14
+ leaflets: 1
15
+ components:
16
+ coh:
17
+ gro: inputs/coh.gro
18
+ itp: inputs/coh.itp
19
+ resname: COH
20
+ anchor: S13 # gold-facing (methyl-capped) sulfur
21
+ ch3:
22
+ gro: inputs/ch3.gro
23
+ itp: inputs/ch3.itp
24
+ resname: CH3
25
+ anchor: S12
26
+ design:
27
+ type: grid
28
+ pattern: inputs/pattern.dat
29
+ mapping: {0: coh, 1: ch3}
30
+ output:
31
+ gro: sam.gro
32
+ order: [COH, CH3] # [molecules] order; base first
33
+ allow_anchor_autodetect: false
@@ -0,0 +1,26 @@
1
+ # Single-component CH3 SAM (one-sided), methyl-terminated alkanethiol.
2
+ # Paths are resolved relative to this config file's directory.
3
+ # The bundled inputs/ strands are pre-oriented (chain along z); samgen applies
4
+ # the SAM tilt. Swap in your own strand .gro/.itp the same way.
5
+ lattice:
6
+ a: 0.288 # Au(111) lattice constant, nm
7
+ tilt_alpha: 28 # tilt from surface normal, deg (Love et al. 2005)
8
+ tilt_beta: 53 # twist about chain axis, deg
9
+ box:
10
+ x: 8.0
11
+ y: 8.0
12
+ z: 5.0
13
+ leaflets: 1
14
+ components:
15
+ ch3:
16
+ gro: inputs/ch3.gro
17
+ itp: inputs/ch3.itp
18
+ resname: CH3
19
+ anchor: S12 # gold-facing (methyl-capped) sulfur
20
+ design:
21
+ type: uniform
22
+ component: ch3
23
+ output:
24
+ gro: sam.gro
25
+ order: [CH3]
26
+ allow_anchor_autodetect: false
@@ -0,0 +1,36 @@
1
+ 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0
2
+ 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
3
+ 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1
4
+ 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
5
+ 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0
6
+ 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
7
+ 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1
8
+ 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
9
+ 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0
10
+ 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
11
+ 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1
12
+ 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
13
+ 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0
14
+ 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
15
+ 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1
16
+ 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
17
+ 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0
18
+ 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
19
+ 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1
20
+ 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
21
+ 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0
22
+ 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
23
+ 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1
24
+ 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
25
+ 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0
26
+ 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
27
+ 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1
28
+ 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
29
+ 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0
30
+ 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
31
+ 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1
32
+ 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
33
+ 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0
34
+ 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
35
+ 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1
36
+ 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
@@ -0,0 +1,12 @@
1
+ 0 0 0 0 0 0 0 0 0 0 0 0
2
+ 0 0 0 0 0 0 0 0 0 0 0 0
3
+ 0 0 0 0 0 0 0 0 0 0 0 0
4
+ 0 0 0 0 0 0 1 0 0 0 0 0
5
+ 0 0 0 0 0 0 0 0 0 0 0 0
6
+ 0 0 0 0 0 1 0 1 0 0 0 0
7
+ 0 0 0 0 0 0 0 0 0 0 0 0
8
+ 0 0 0 0 0 0 1 0 0 0 0 0
9
+ 0 0 0 0 0 0 0 0 0 0 0 0
10
+ 0 0 0 0 0 0 0 0 0 0 0 0
11
+ 0 0 0 0 0 0 0 0 0 0 0 0
12
+ 0 0 0 0 0 0 0 0 0 0 0 0
@@ -0,0 +1,12 @@
1
+ 0 0 0 0 0 0 0 0 0 0 0 0
2
+ 0 0 0 0 0 0 0 0 0 0 0 0
3
+ 0 0 0 0 0 0 0 0 0 0 0 0
4
+ 0 0 0 0 0 0 0 0 0 0 0 0
5
+ 0 0 0 0 0 0 0 0 0 0 0 0
6
+ 0 0 0 0 0 1 0 0 0 0 0 0
7
+ 0 0 0 0 0 0 0 0 0 0 0 0
8
+ 0 0 0 0 0 0 0 0 0 0 0 0
9
+ 0 0 0 0 0 0 0 0 0 0 0 0
10
+ 0 0 0 0 0 0 0 0 0 0 0 0
11
+ 0 0 0 0 0 0 0 0 0 0 0 0
12
+ 0 0 0 0 0 0 0 0 0 0 0 0
@@ -0,0 +1,12 @@
1
+ 0 0 0 0 0 0 0 0 0 0 0 0
2
+ 0 0 0 0 0 0 0 0 0 0 0 0
3
+ 0 0 0 0 0 0 0 0 0 0 0 0
4
+ 0 0 0 0 0 0 0 0 0 0 0 0
5
+ 0 0 0 0 0 0 0 0 0 0 0 0
6
+ 0 0 0 0 0 1 0 1 0 0 0 0
7
+ 0 0 0 0 0 0 0 0 0 0 0 0
8
+ 0 0 0 0 0 0 1 0 0 0 0 0
9
+ 0 0 0 0 0 0 0 0 0 0 0 0
10
+ 0 0 0 0 0 0 0 0 0 0 0 0
11
+ 0 0 0 0 0 0 0 0 0 0 0 0
12
+ 0 0 0 0 0 0 0 0 0 0 0 0