grasp-library-designer 0.1.0__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 (91) hide show
  1. grasp_library_designer-0.1.0/LICENSE +26 -0
  2. grasp_library_designer-0.1.0/MANIFEST.in +10 -0
  3. grasp_library_designer-0.1.0/PKG-INFO +216 -0
  4. grasp_library_designer-0.1.0/README.md +177 -0
  5. grasp_library_designer-0.1.0/THIRD_PARTY_LICENSES.md +11 -0
  6. grasp_library_designer-0.1.0/grasp_library/__init__.py +123 -0
  7. grasp_library_designer-0.1.0/grasp_library/binder.py +76 -0
  8. grasp_library_designer-0.1.0/grasp_library/codon_tables.py +145 -0
  9. grasp_library_designer-0.1.0/grasp_library/codon_validation.py +299 -0
  10. grasp_library_designer-0.1.0/grasp_library/colab_forms.py +65 -0
  11. grasp_library_designer-0.1.0/grasp_library/control_panel.py +497 -0
  12. grasp_library_designer-0.1.0/grasp_library/data/profiles/grasp_nar2025/README.md +32 -0
  13. grasp_library_designer-0.1.0/grasp_library/data/profiles/grasp_nar2025/genbank/GRASP_-1.gb +4651 -0
  14. grasp_library_designer-0.1.0/grasp_library/data/profiles/grasp_nar2025/genbank/pPR-1_14A_LD5N.gb +132 -0
  15. grasp_library_designer-0.1.0/grasp_library/data/profiles/grasp_nar2025/genbank/pPR-1_14A_LD5T.gb +132 -0
  16. grasp_library_designer-0.1.0/grasp_library/data/profiles/grasp_nar2025/genbank/pPR-1_14A_LN5N.gb +131 -0
  17. grasp_library_designer-0.1.0/grasp_library/data/profiles/grasp_nar2025/genbank/pPR-1_14A_LN5T.gb +131 -0
  18. grasp_library_designer-0.1.0/grasp_library/data/profiles/grasp_nar2025/genbank/pPR-1_14E_LD5N.gb +115 -0
  19. grasp_library_designer-0.1.0/grasp_library/data/profiles/grasp_nar2025/genbank/pPR-1_14E_LD5T.gb +115 -0
  20. grasp_library_designer-0.1.0/grasp_library/data/profiles/grasp_nar2025/genbank/pPR-1_14E_LN5N.gb +115 -0
  21. grasp_library_designer-0.1.0/grasp_library/data/profiles/grasp_nar2025/genbank/pPR-1_14E_LN5T.gb +115 -0
  22. grasp_library_designer-0.1.0/grasp_library/data/profiles/grasp_nar2025/genbank/pPR-1_19A_LD5N.gb +132 -0
  23. grasp_library_designer-0.1.0/grasp_library/data/profiles/grasp_nar2025/genbank/pPR-1_19A_LD5T.gb +131 -0
  24. grasp_library_designer-0.1.0/grasp_library/data/profiles/grasp_nar2025/genbank/pPR-1_19A_LN5N.gb +131 -0
  25. grasp_library_designer-0.1.0/grasp_library/data/profiles/grasp_nar2025/genbank/pPR-1_19A_LN5T.gb +131 -0
  26. grasp_library_designer-0.1.0/grasp_library/data/profiles/grasp_nar2025/genbank/pPR-1_19E_LD5N.gb +115 -0
  27. grasp_library_designer-0.1.0/grasp_library/data/profiles/grasp_nar2025/genbank/pPR-1_19E_LD5T.gb +115 -0
  28. grasp_library_designer-0.1.0/grasp_library/data/profiles/grasp_nar2025/genbank/pPR-1_19E_LN5N.gb +115 -0
  29. grasp_library_designer-0.1.0/grasp_library/data/profiles/grasp_nar2025/genbank/pPR-1_19E_LN5T.gb +116 -0
  30. grasp_library_designer-0.1.0/grasp_library/data/profiles/grasp_nar2025/genbank/pPR-1_1A_5N_AATG.gb +128 -0
  31. grasp_library_designer-0.1.0/grasp_library/data/profiles/grasp_nar2025/genbank/pPR-1_1A_5N_AGGT.gb +128 -0
  32. grasp_library_designer-0.1.0/grasp_library/data/profiles/grasp_nar2025/genbank/pPR-1_1A_5T_AATG.gb +129 -0
  33. grasp_library_designer-0.1.0/grasp_library/data/profiles/grasp_nar2025/genbank/pPR-1_1A_5T_AGGT.gb +129 -0
  34. grasp_library_designer-0.1.0/grasp_library/data/profiles/grasp_nar2025/genbank/pPR-1_1E_LD5N.gb +131 -0
  35. grasp_library_designer-0.1.0/grasp_library/data/profiles/grasp_nar2025/genbank/pPR-1_1E_LD5T.gb +131 -0
  36. grasp_library_designer-0.1.0/grasp_library/data/profiles/grasp_nar2025/genbank/pPR-1_1E_LN5N.gb +131 -0
  37. grasp_library_designer-0.1.0/grasp_library/data/profiles/grasp_nar2025/genbank/pPR-1_1E_LN5T.gb +131 -0
  38. grasp_library_designer-0.1.0/grasp_library/data/profiles/grasp_nar2025/genbank/pPR-1_2A_LD5N.gb +136 -0
  39. grasp_library_designer-0.1.0/grasp_library/data/profiles/grasp_nar2025/genbank/pPR-1_2A_LD5T.gb +127 -0
  40. grasp_library_designer-0.1.0/grasp_library/data/profiles/grasp_nar2025/genbank/pPR-1_2A_LN5N.gb +136 -0
  41. grasp_library_designer-0.1.0/grasp_library/data/profiles/grasp_nar2025/genbank/pPR-1_2A_LN5T.gb +141 -0
  42. grasp_library_designer-0.1.0/grasp_library/data/profiles/grasp_nar2025/genbank/pPR-1_2E_LD.gb +132 -0
  43. grasp_library_designer-0.1.0/grasp_library/data/profiles/grasp_nar2025/genbank/pPR-1_2E_LN.gb +131 -0
  44. grasp_library_designer-0.1.0/grasp_library/data/profiles/grasp_nar2025/genbank/pPR-1_B_LD5N.gb +129 -0
  45. grasp_library_designer-0.1.0/grasp_library/data/profiles/grasp_nar2025/genbank/pPR-1_B_LD5T.gb +136 -0
  46. grasp_library_designer-0.1.0/grasp_library/data/profiles/grasp_nar2025/genbank/pPR-1_B_LN5N.gb +136 -0
  47. grasp_library_designer-0.1.0/grasp_library/data/profiles/grasp_nar2025/genbank/pPR-1_B_LN5T.gb +124 -0
  48. grasp_library_designer-0.1.0/grasp_library/data/profiles/grasp_nar2025/genbank/pPR-1_C_LD5N.gb +115 -0
  49. grasp_library_designer-0.1.0/grasp_library/data/profiles/grasp_nar2025/genbank/pPR-1_C_LD5T.gb +115 -0
  50. grasp_library_designer-0.1.0/grasp_library/data/profiles/grasp_nar2025/genbank/pPR-1_C_LN5N.gb +115 -0
  51. grasp_library_designer-0.1.0/grasp_library/data/profiles/grasp_nar2025/genbank/pPR-1_C_LN5T.gb +115 -0
  52. grasp_library_designer-0.1.0/grasp_library/data/profiles/grasp_nar2025/genbank/pPR-1_D_LD5N.gb +115 -0
  53. grasp_library_designer-0.1.0/grasp_library/data/profiles/grasp_nar2025/genbank/pPR-1_D_LD5T.gb +115 -0
  54. grasp_library_designer-0.1.0/grasp_library/data/profiles/grasp_nar2025/genbank/pPR-1_D_LN5N.gb +115 -0
  55. grasp_library_designer-0.1.0/grasp_library/data/profiles/grasp_nar2025/genbank/pPR-1_D_LN5T.gb +115 -0
  56. grasp_library_designer-0.1.0/grasp_library/dna.py +145 -0
  57. grasp_library_designer-0.1.0/grasp_library/gga_split.py +221 -0
  58. grasp_library_designer-0.1.0/grasp_library/import_grasp.py +705 -0
  59. grasp_library_designer-0.1.0/grasp_library/ligation_fidelity.py +95 -0
  60. grasp_library_designer-0.1.0/grasp_library/notebook_ui.py +199 -0
  61. grasp_library_designer-0.1.0/grasp_library/objectives.py +418 -0
  62. grasp_library_designer-0.1.0/grasp_library/oneshot.py +232 -0
  63. grasp_library_designer-0.1.0/grasp_library/optimizer.py +507 -0
  64. grasp_library_designer-0.1.0/grasp_library/pareto.py +223 -0
  65. grasp_library_designer-0.1.0/grasp_library/paths.py +60 -0
  66. grasp_library_designer-0.1.0/grasp_library/plotting.py +276 -0
  67. grasp_library_designer-0.1.0/grasp_library/py.typed +0 -0
  68. grasp_library_designer-0.1.0/grasp_library/sample_codon_tables.py +224 -0
  69. grasp_library_designer-0.1.0/grasp_library/synthesis_vendors.py +265 -0
  70. grasp_library_designer-0.1.0/grasp_library/workflows.py +609 -0
  71. grasp_library_designer-0.1.0/grasp_library_designer.egg-info/PKG-INFO +216 -0
  72. grasp_library_designer-0.1.0/grasp_library_designer.egg-info/SOURCES.txt +89 -0
  73. grasp_library_designer-0.1.0/grasp_library_designer.egg-info/dependency_links.txt +1 -0
  74. grasp_library_designer-0.1.0/grasp_library_designer.egg-info/requires.txt +15 -0
  75. grasp_library_designer-0.1.0/grasp_library_designer.egg-info/top_level.txt +2 -0
  76. grasp_library_designer-0.1.0/grasp_library_designer.ipynb +520 -0
  77. grasp_library_designer-0.1.0/grasp_oneshot_designer.ipynb +295 -0
  78. grasp_library_designer-0.1.0/pyproject.toml +74 -0
  79. grasp_library_designer-0.1.0/requirements.txt +9 -0
  80. grasp_library_designer-0.1.0/setup.cfg +4 -0
  81. grasp_library_designer-0.1.0/third_party/dawdlib_golden_gate/__init__.py +2 -0
  82. grasp_library_designer-0.1.0/third_party/dawdlib_golden_gate/gate_data.py +252 -0
  83. grasp_library_designer-0.1.0/third_party/dawdlib_golden_gate/resources/.ipynb_checkpoints/BsaI-HFv2-checkpoint.csv +257 -0
  84. grasp_library_designer-0.1.0/third_party/dawdlib_golden_gate/resources/BsaI-HFv2.csv +257 -0
  85. grasp_library_designer-0.1.0/third_party/dawdlib_golden_gate/resources/BsaI-HFv2_T4_constant_37.csv +257 -0
  86. grasp_library_designer-0.1.0/third_party/dawdlib_golden_gate/resources/BsmBI-v2_T4_constant_42.csv +257 -0
  87. grasp_library_designer-0.1.0/third_party/dawdlib_golden_gate/resources/FileS_T4_01h_25C.csv +257 -0
  88. grasp_library_designer-0.1.0/third_party/dawdlib_golden_gate/resources/FileS_T4_18h_25C.csv +257 -0
  89. grasp_library_designer-0.1.0/third_party/dawdlib_golden_gate/resources/FileS_T4_18h_37C.csv +257 -0
  90. grasp_library_designer-0.1.0/third_party/dawdlib_golden_gate/resources/SapI.csv +65 -0
  91. grasp_library_designer-0.1.0/third_party/dawdlib_golden_gate/resources/__init__.py +7 -0
@@ -0,0 +1,26 @@
1
+ GNU AFFERO GENERAL PUBLIC LICENSE
2
+ Version 3, 19 November 2007
3
+
4
+ Copyright (C) 2026 JustABiologist and contributors
5
+
6
+ This program is free software: you can redistribute it and/or modify
7
+ it under the terms of the GNU Affero General Public License as published
8
+ by the Free Software Foundation, either version 3 of the License, or
9
+ (at your option) any later version.
10
+
11
+ This program is distributed in the hope that it will be useful,
12
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
13
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14
+ GNU Affero General Public License for more details.
15
+
16
+ You should have received a copy of the GNU Affero General Public License
17
+ along with this program. If not, see <https://www.gnu.org/licenses/>.
18
+
19
+ ---------------------------------------------------------------------------
20
+
21
+ This distribution includes vendored ligation-fidelity code and Potapov
22
+ frequency matrices from Fleishman-Lab / GGAssembler (dawdlib), licensed
23
+ under AGPL-3.0. See THIRD_PARTY_LICENSES.md.
24
+
25
+ The full AGPL-3.0 text is available at:
26
+ https://www.gnu.org/licenses/agpl-3.0.html
@@ -0,0 +1,10 @@
1
+ include README.md
2
+ include LICENSE
3
+ include THIRD_PARTY_LICENSES.md
4
+ include pyproject.toml
5
+ include requirements.txt
6
+ include grasp_library_designer.ipynb
7
+ include grasp_oneshot_designer.ipynb
8
+ recursive-include grasp_library/data *.gb *.md
9
+ recursive-include third_party/dawdlib_golden_gate *.py *.csv
10
+ global-exclude __pycache__ *.py[cod] .ipynb_checkpoints* *.checkpoint.*
@@ -0,0 +1,216 @@
1
+ Metadata-Version: 2.4
2
+ Name: grasp-library-designer
3
+ Version: 0.1.0
4
+ Summary: Codon-optimize GRASP binder DNA for Golden Gate assembly (library + one-shot).
5
+ Author: JustABiologist
6
+ License: AGPL-3.0-only
7
+ Project-URL: Homepage, https://github.com/JustABiologist/grasp-library-designer
8
+ Project-URL: Repository, https://github.com/JustABiologist/grasp-library-designer
9
+ Project-URL: Issues, https://github.com/JustABiologist/grasp-library-designer/issues
10
+ Keywords: GRASP,Golden Gate,codon optimization,synthetic biology,PPR,ligation fidelity
11
+ Classifier: Development Status :: 4 - Beta
12
+ Classifier: Intended Audience :: Science/Research
13
+ Classifier: License :: OSI Approved :: GNU Affero General Public License v3
14
+ Classifier: Operating System :: OS Independent
15
+ Classifier: Programming Language :: Python :: 3
16
+ Classifier: Programming Language :: Python :: 3 :: Only
17
+ Classifier: Programming Language :: Python :: 3.10
18
+ Classifier: Programming Language :: Python :: 3.11
19
+ Classifier: Programming Language :: Python :: 3.12
20
+ Classifier: Programming Language :: Python :: 3.13
21
+ Classifier: Topic :: Scientific/Engineering :: Bio-Informatics
22
+ Requires-Python: >=3.10
23
+ Description-Content-Type: text/markdown
24
+ License-File: LICENSE
25
+ Requires-Dist: pandas>=2.0
26
+ Requires-Dist: numpy>=1.24
27
+ Requires-Dist: biopython>=1.81
28
+ Requires-Dist: pyyaml>=6.0
29
+ Requires-Dist: openpyxl>=3.1
30
+ Requires-Dist: matplotlib>=3.7
31
+ Requires-Dist: ipywidgets>=8.0
32
+ Provides-Extra: notebook
33
+ Requires-Dist: jupyter>=1.0; extra == "notebook"
34
+ Requires-Dist: ipykernel>=6.0; extra == "notebook"
35
+ Provides-Extra: dev
36
+ Requires-Dist: build>=1.0; extra == "dev"
37
+ Requires-Dist: twine>=5.0; extra == "dev"
38
+ Dynamic: license-file
39
+
40
+ # GRASP Library Designer
41
+
42
+ Codon-optimize [GRASP](https://academic.oup.com/nar/article/53/20/gkaf1169/8321212) (Farley et al., *NAR* 2025) binder DNA for Golden Gate assembly.
43
+
44
+ **PyPI package:** `grasp-library-designer`
45
+ **Import name:** `grasp_library`
46
+
47
+ Two Colab Forms notebooks:
48
+
49
+ | Notebook | Purpose |
50
+ |---|---|
51
+ | [`grasp_oneshot_designer.ipynb`](grasp_oneshot_designer.ipynb) | **One target RNA** → binder protein → free GGA cut sites → oligos |
52
+ | [`grasp_library_designer.ipynb`](grasp_library_designer.ipynb) | Redesign / anneal the **42-module combinatorial library**, then GAP-compile a target |
53
+
54
+ Hard constraints (library path): protein sequence fixed (synonymous codons only); coding Golden Gate overhang bases stay locked in `coding_mask`. Objectives: ligation fidelity (Potapov / GGAssembler), codon optimality, synthesis fitness.
55
+
56
+ > **License:** AGPL-3.0 (required by the vendored GGAssembler / dawdlib ligation engine). See [`LICENSE`](LICENSE) and [`THIRD_PARTY_LICENSES.md`](THIRD_PARTY_LICENSES.md).
57
+
58
+ ---
59
+
60
+ ## Install (PyPI)
61
+
62
+ ```bash
63
+ pip install grasp-library-designer
64
+ # optional notebook extras
65
+ pip install "grasp-library-designer[notebook]"
66
+ ```
67
+
68
+ Minimal API check:
69
+
70
+ ```python
71
+ from grasp_library import materialize_project, build_default_config, LigationFidelityCalculator
72
+
73
+ project = materialize_project() # creates ./grasp_library_project + GenBank
74
+ config = build_default_config(project / "input")
75
+ print(LigationFidelityCalculator(25, 18).set_fidelity(["AATG", "GATA"]))
76
+ ```
77
+
78
+ Until the package is published on PyPI, install from GitHub (private repo needs a PAT):
79
+
80
+ ```bash
81
+ pip install "git+https://<TOKEN>@github.com/JustABiologist/grasp-library-designer.git@main"
82
+ ```
83
+
84
+ Or clone and install editable:
85
+
86
+ ```bash
87
+ git clone https://github.com/JustABiologist/grasp-library-designer.git
88
+ cd grasp-library-designer
89
+ python3 -m venv .venv
90
+ source .venv/bin/activate
91
+ pip install -e ".[notebook,dev]"
92
+ ```
93
+
94
+ ---
95
+
96
+ ## Run in Google Colab
97
+
98
+ Both notebooks use **Colab Forms** (`#@title` / `#@param`, `{display-mode: "form"}`).
99
+
100
+ ### 1. Open a notebook
101
+
102
+ From GitHub → **Open in Colab**, or upload the `.ipynb`.
103
+
104
+ ### 2. Install
105
+
106
+ In **0 · Install**, choose:
107
+
108
+ | Mode | When |
109
+ |---|---|
110
+ | **PyPI** | After the package is on PyPI (`pip install grasp-library-designer`) |
111
+ | **Private GitHub** | Clone this private repo with a `repo`-scoped PAT |
112
+ | **Local editable** | Notebook already lives in a checkout |
113
+
114
+ ### 3a. One-shot
115
+
116
+ Settings → Preview binder → Design oligos → Export Excel
117
+ Outputs: `grasp_library_project/output/oneshot/{RNA}/`
118
+
119
+ ### 3b. Combinatorial library
120
+
121
+ Settings → Import → Redesign overhangs → Anneal → Pareto plot → Export → Compile target
122
+ Outputs: `grasp_library_project/output/`
123
+
124
+ Bundled Farley et al. GenBank modules are copied into the project folder on first run via `materialize_project()`.
125
+
126
+ ---
127
+
128
+ ## Run locally (Cursor / Jupyter / VS Code)
129
+
130
+ ```bash
131
+ pip install -e ".[notebook]"
132
+ python -m ipykernel install --user --name grasp-library-designer --display-name "grasp-library-designer"
133
+ ```
134
+
135
+ Select that kernel, open either notebook, run top-to-bottom.
136
+
137
+ ---
138
+
139
+ ## Package layout
140
+
141
+ ```
142
+ grasp_library/ # installable Python package
143
+ data/profiles/.../genbank/ # bundled GRASP GenBank modules
144
+ paths.py # materialize_project()
145
+ ...
146
+ third_party/dawdlib_golden_gate/ # Potapov ligation fidelity (AGPL; also installed)
147
+ grasp_*_designer.ipynb # Colab Forms UIs (also in sdist)
148
+ ```
149
+
150
+ ---
151
+
152
+ ## Build / publish (maintainers)
153
+
154
+ ```bash
155
+ pip install -e ".[dev]"
156
+ python -m build
157
+ twine check dist/*
158
+ # Test PyPI first (recommended):
159
+ twine upload --repository testpypi dist/*
160
+ # Production:
161
+ twine upload dist/*
162
+ ```
163
+
164
+ Requires a PyPI API token (`TWINE_USERNAME=__token__`, `TWINE_PASSWORD=pypi-...`).
165
+
166
+ ---
167
+
168
+ ## Hiding code (Colab / Jupyter / VS Code)
169
+
170
+ | Frontend | How |
171
+ |---|---|
172
+ | **Google Colab** | Forms: `#@title … {display-mode: "form"}` + `#@param` |
173
+ | **Cursor / VS Code** | **Notebook: Collapse All Cell Inputs** |
174
+
175
+ **Hide ≠ protect.** Source remains in the `.ipynb`.
176
+
177
+ ---
178
+
179
+ ## License notes
180
+
181
+ - Distributed package license: **AGPL-3.0** (see [`LICENSE`](LICENSE)).
182
+ - Vendored ligation engine under `third_party/dawdlib_golden_gate/` is AGPL-3.0 (Fleishman-Lab / GGAssembler).
183
+ - GRASP sequences: Farley et al., *Nucleic Acids Res.* 2025.
184
+
185
+ ---
186
+
187
+ ## Quick smoke test
188
+
189
+ ```bash
190
+ python - <<'PY'
191
+ from pathlib import Path
192
+ from grasp_library import (
193
+ materialize_project,
194
+ build_default_config,
195
+ run_oneshot_design,
196
+ LigationFidelityCalculator,
197
+ )
198
+ from grasp_library.codon_tables import apply_organism_codon_table, load_codon_usage
199
+
200
+ project = materialize_project()
201
+ input_dir = project / "input"
202
+ cfg = build_default_config(input_dir)
203
+ cfg["optimizer"]["iterations_per_part"] = 200
204
+ apply_organism_codon_table("Escherichia coli (Kazusa)", input_dir / "codon_usage.csv")
205
+ _, codon_data = load_codon_usage(input_dir / "codon_usage.csv", genetic_code=1)
206
+ run_oneshot_design(
207
+ target_rna="UUACACGUG",
208
+ codon_data=codon_data,
209
+ config=cfg,
210
+ output_dir=project / "output" / "oneshot" / "UUACACGUG",
211
+ n_fragments=4,
212
+ fidelity=LigationFidelityCalculator(25, 18),
213
+ )
214
+ print("ok")
215
+ PY
216
+ ```
@@ -0,0 +1,177 @@
1
+ # GRASP Library Designer
2
+
3
+ Codon-optimize [GRASP](https://academic.oup.com/nar/article/53/20/gkaf1169/8321212) (Farley et al., *NAR* 2025) binder DNA for Golden Gate assembly.
4
+
5
+ **PyPI package:** `grasp-library-designer`
6
+ **Import name:** `grasp_library`
7
+
8
+ Two Colab Forms notebooks:
9
+
10
+ | Notebook | Purpose |
11
+ |---|---|
12
+ | [`grasp_oneshot_designer.ipynb`](grasp_oneshot_designer.ipynb) | **One target RNA** → binder protein → free GGA cut sites → oligos |
13
+ | [`grasp_library_designer.ipynb`](grasp_library_designer.ipynb) | Redesign / anneal the **42-module combinatorial library**, then GAP-compile a target |
14
+
15
+ Hard constraints (library path): protein sequence fixed (synonymous codons only); coding Golden Gate overhang bases stay locked in `coding_mask`. Objectives: ligation fidelity (Potapov / GGAssembler), codon optimality, synthesis fitness.
16
+
17
+ > **License:** AGPL-3.0 (required by the vendored GGAssembler / dawdlib ligation engine). See [`LICENSE`](LICENSE) and [`THIRD_PARTY_LICENSES.md`](THIRD_PARTY_LICENSES.md).
18
+
19
+ ---
20
+
21
+ ## Install (PyPI)
22
+
23
+ ```bash
24
+ pip install grasp-library-designer
25
+ # optional notebook extras
26
+ pip install "grasp-library-designer[notebook]"
27
+ ```
28
+
29
+ Minimal API check:
30
+
31
+ ```python
32
+ from grasp_library import materialize_project, build_default_config, LigationFidelityCalculator
33
+
34
+ project = materialize_project() # creates ./grasp_library_project + GenBank
35
+ config = build_default_config(project / "input")
36
+ print(LigationFidelityCalculator(25, 18).set_fidelity(["AATG", "GATA"]))
37
+ ```
38
+
39
+ Until the package is published on PyPI, install from GitHub (private repo needs a PAT):
40
+
41
+ ```bash
42
+ pip install "git+https://<TOKEN>@github.com/JustABiologist/grasp-library-designer.git@main"
43
+ ```
44
+
45
+ Or clone and install editable:
46
+
47
+ ```bash
48
+ git clone https://github.com/JustABiologist/grasp-library-designer.git
49
+ cd grasp-library-designer
50
+ python3 -m venv .venv
51
+ source .venv/bin/activate
52
+ pip install -e ".[notebook,dev]"
53
+ ```
54
+
55
+ ---
56
+
57
+ ## Run in Google Colab
58
+
59
+ Both notebooks use **Colab Forms** (`#@title` / `#@param`, `{display-mode: "form"}`).
60
+
61
+ ### 1. Open a notebook
62
+
63
+ From GitHub → **Open in Colab**, or upload the `.ipynb`.
64
+
65
+ ### 2. Install
66
+
67
+ In **0 · Install**, choose:
68
+
69
+ | Mode | When |
70
+ |---|---|
71
+ | **PyPI** | After the package is on PyPI (`pip install grasp-library-designer`) |
72
+ | **Private GitHub** | Clone this private repo with a `repo`-scoped PAT |
73
+ | **Local editable** | Notebook already lives in a checkout |
74
+
75
+ ### 3a. One-shot
76
+
77
+ Settings → Preview binder → Design oligos → Export Excel
78
+ Outputs: `grasp_library_project/output/oneshot/{RNA}/`
79
+
80
+ ### 3b. Combinatorial library
81
+
82
+ Settings → Import → Redesign overhangs → Anneal → Pareto plot → Export → Compile target
83
+ Outputs: `grasp_library_project/output/`
84
+
85
+ Bundled Farley et al. GenBank modules are copied into the project folder on first run via `materialize_project()`.
86
+
87
+ ---
88
+
89
+ ## Run locally (Cursor / Jupyter / VS Code)
90
+
91
+ ```bash
92
+ pip install -e ".[notebook]"
93
+ python -m ipykernel install --user --name grasp-library-designer --display-name "grasp-library-designer"
94
+ ```
95
+
96
+ Select that kernel, open either notebook, run top-to-bottom.
97
+
98
+ ---
99
+
100
+ ## Package layout
101
+
102
+ ```
103
+ grasp_library/ # installable Python package
104
+ data/profiles/.../genbank/ # bundled GRASP GenBank modules
105
+ paths.py # materialize_project()
106
+ ...
107
+ third_party/dawdlib_golden_gate/ # Potapov ligation fidelity (AGPL; also installed)
108
+ grasp_*_designer.ipynb # Colab Forms UIs (also in sdist)
109
+ ```
110
+
111
+ ---
112
+
113
+ ## Build / publish (maintainers)
114
+
115
+ ```bash
116
+ pip install -e ".[dev]"
117
+ python -m build
118
+ twine check dist/*
119
+ # Test PyPI first (recommended):
120
+ twine upload --repository testpypi dist/*
121
+ # Production:
122
+ twine upload dist/*
123
+ ```
124
+
125
+ Requires a PyPI API token (`TWINE_USERNAME=__token__`, `TWINE_PASSWORD=pypi-...`).
126
+
127
+ ---
128
+
129
+ ## Hiding code (Colab / Jupyter / VS Code)
130
+
131
+ | Frontend | How |
132
+ |---|---|
133
+ | **Google Colab** | Forms: `#@title … {display-mode: "form"}` + `#@param` |
134
+ | **Cursor / VS Code** | **Notebook: Collapse All Cell Inputs** |
135
+
136
+ **Hide ≠ protect.** Source remains in the `.ipynb`.
137
+
138
+ ---
139
+
140
+ ## License notes
141
+
142
+ - Distributed package license: **AGPL-3.0** (see [`LICENSE`](LICENSE)).
143
+ - Vendored ligation engine under `third_party/dawdlib_golden_gate/` is AGPL-3.0 (Fleishman-Lab / GGAssembler).
144
+ - GRASP sequences: Farley et al., *Nucleic Acids Res.* 2025.
145
+
146
+ ---
147
+
148
+ ## Quick smoke test
149
+
150
+ ```bash
151
+ python - <<'PY'
152
+ from pathlib import Path
153
+ from grasp_library import (
154
+ materialize_project,
155
+ build_default_config,
156
+ run_oneshot_design,
157
+ LigationFidelityCalculator,
158
+ )
159
+ from grasp_library.codon_tables import apply_organism_codon_table, load_codon_usage
160
+
161
+ project = materialize_project()
162
+ input_dir = project / "input"
163
+ cfg = build_default_config(input_dir)
164
+ cfg["optimizer"]["iterations_per_part"] = 200
165
+ apply_organism_codon_table("Escherichia coli (Kazusa)", input_dir / "codon_usage.csv")
166
+ _, codon_data = load_codon_usage(input_dir / "codon_usage.csv", genetic_code=1)
167
+ run_oneshot_design(
168
+ target_rna="UUACACGUG",
169
+ codon_data=codon_data,
170
+ config=cfg,
171
+ output_dir=project / "output" / "oneshot" / "UUACACGUG",
172
+ n_fragments=4,
173
+ fidelity=LigationFidelityCalculator(25, 18),
174
+ )
175
+ print("ok")
176
+ PY
177
+ ```
@@ -0,0 +1,11 @@
1
+ # Third-party components
2
+
3
+ ## Fleishman-Lab / GGAssembler (dawdlib golden-gate fidelity)
4
+
5
+ - Path: `third_party/dawdlib_golden_gate/`
6
+ - Upstream: https://github.com/Fleishman-Lab/GGAssembler
7
+ - Related package: https://github.com/Fleishman-Lab/dawdlib
8
+ - License: AGPL-3.0
9
+ - What was vendored: `gate_data.py` and Potapov/NEB ligation frequency CSVs used by `GGData.reaction_fidelity`
10
+
11
+ Ligation frequency data originate from Potapov et al., ACS Synth. Biol. (2018).
@@ -0,0 +1,123 @@
1
+ """GRASP library designer: masked codon optimization with Pareto trade-offs."""
2
+
3
+ from .ligation_fidelity import LigationFidelityCalculator
4
+ from .objectives import ObjectiveScores, evaluate_design
5
+ from .pareto import (
6
+ ParetoPoint,
7
+ dominates,
8
+ knee_point,
9
+ optimize_pareto_overhangs,
10
+ pareto_front,
11
+ )
12
+ from .sample_codon_tables import (
13
+ SAMPLE_CODON_TABLES,
14
+ codon_table_dataframe,
15
+ sample_names,
16
+ write_sample_codon_table,
17
+ )
18
+ from .import_grasp import (
19
+ compile_target_gap,
20
+ import_grasp_profile,
21
+ pick_parts_for_target,
22
+ )
23
+ from .synthesis_vendors import (
24
+ ASSEMBLY_ENZYMES,
25
+ LIGATION_TABLES,
26
+ SYNTHESIS_VENDORS,
27
+ apply_enzyme_to_config,
28
+ apply_ligation_table_to_config,
29
+ apply_vendor_to_config,
30
+ enzyme_names,
31
+ ligation_table_names,
32
+ twist_length_advice,
33
+ vendor_names,
34
+ )
35
+ from .control_panel import GraspControlPanel, build_default_config, wire_reload_button
36
+ from .workflows import (
37
+ run_overhang_redesign,
38
+ run_library_optimize,
39
+ rescore_pareto_front_after_anneal,
40
+ load_and_validate_parts,
41
+ ensure_grasp_imported,
42
+ export_optimized_library,
43
+ compile_and_assemble_target,
44
+ plot_library_pareto_after_anneal,
45
+ run_library_redesign_and_anneal,
46
+ )
47
+ from .codon_tables import load_codon_usage, apply_organism_codon_table, validate_parts_for_organism
48
+ from .codon_validation import analyze_cut_site_aa_risks, validate_codon_table_aas
49
+ from .plotting import plot_pareto_front
50
+ from .optimizer import (
51
+ optimize_coding_sequence,
52
+ optimize_library,
53
+ synthesis_qc,
54
+ simulate_assembled_cds,
55
+ )
56
+ from .oneshot import run_oneshot_design, sanitize_rna_name
57
+ from .binder import rna_to_binder_aa, describe_binder, normalize_target_rna
58
+ from .gga_split import plan_gga_from_optimized_cds, suggest_fragment_count
59
+ from .paths import (
60
+ bundled_profile_genbank,
61
+ materialize_project,
62
+ project_paths,
63
+ )
64
+
65
+ __all__ = [
66
+ "LigationFidelityCalculator",
67
+ "ObjectiveScores",
68
+ "evaluate_design",
69
+ "ParetoPoint",
70
+ "dominates",
71
+ "pareto_front",
72
+ "optimize_pareto_overhangs",
73
+ "knee_point",
74
+ "SAMPLE_CODON_TABLES",
75
+ "codon_table_dataframe",
76
+ "sample_names",
77
+ "write_sample_codon_table",
78
+ "import_grasp_profile",
79
+ "compile_target_gap",
80
+ "pick_parts_for_target",
81
+ "SYNTHESIS_VENDORS",
82
+ "ASSEMBLY_ENZYMES",
83
+ "LIGATION_TABLES",
84
+ "vendor_names",
85
+ "enzyme_names",
86
+ "ligation_table_names",
87
+ "apply_vendor_to_config",
88
+ "apply_enzyme_to_config",
89
+ "apply_ligation_table_to_config",
90
+ "twist_length_advice",
91
+ "GraspControlPanel",
92
+ "build_default_config",
93
+ "wire_reload_button",
94
+ "run_overhang_redesign",
95
+ "run_library_optimize",
96
+ "rescore_pareto_front_after_anneal",
97
+ "load_and_validate_parts",
98
+ "ensure_grasp_imported",
99
+ "export_optimized_library",
100
+ "compile_and_assemble_target",
101
+ "plot_library_pareto_after_anneal",
102
+ "run_library_redesign_and_anneal",
103
+ "load_codon_usage",
104
+ "apply_organism_codon_table",
105
+ "validate_parts_for_organism",
106
+ "analyze_cut_site_aa_risks",
107
+ "validate_codon_table_aas",
108
+ "plot_pareto_front",
109
+ "optimize_coding_sequence",
110
+ "optimize_library",
111
+ "synthesis_qc",
112
+ "simulate_assembled_cds",
113
+ "run_oneshot_design",
114
+ "sanitize_rna_name",
115
+ "rna_to_binder_aa",
116
+ "describe_binder",
117
+ "normalize_target_rna",
118
+ "plan_gga_from_optimized_cds",
119
+ "suggest_fragment_count",
120
+ "bundled_profile_genbank",
121
+ "materialize_project",
122
+ "project_paths",
123
+ ]
@@ -0,0 +1,76 @@
1
+ """RNA → GRASP binder protein (PPR recognition code), no library parts required."""
2
+
3
+ from __future__ import annotations
4
+
5
+ from typing import List, Sequence, Tuple
6
+
7
+ # Classic PPR code: (5th AA, last AA) of each repeat
8
+ _RNA_TO_CODE = {
9
+ "A": ("T", "N"),
10
+ "C": ("N", "N"),
11
+ "G": ("T", "D"),
12
+ "U": ("N", "D"),
13
+ "T": ("N", "D"),
14
+ }
15
+
16
+ # Solvating N-helix from Farley et al. GRASP 9S native assemblies
17
+ NTERM_HELIX = "QGGNSEEPRKSFDERPERGVVS"
18
+
19
+ # One ~31-aa PPR-like repeat; only the W?AM 5th and PER? last positions vary
20
+ REPEAT_TEMPLATE = "W{fifth}AMISGYAQNGRIDEARELFDKMPER{last}VVS"
21
+
22
+
23
+ def normalize_target_rna(sequence: str) -> str:
24
+ rna = str(sequence).upper().replace("T", "U")
25
+ rna = "".join(b for b in rna if b in "ACGU")
26
+ if not rna:
27
+ raise ValueError("Empty target RNA")
28
+ if len(rna) not in (9, 14, 19):
29
+ raise ValueError(
30
+ f"Target RNA length must be 9, 14, or 19 (got {len(rna)}). "
31
+ "GRASP binder scaffolds are defined for those sizes."
32
+ )
33
+ if any(b not in _RNA_TO_CODE for b in rna):
34
+ raise ValueError(f"Non-ACGU base in target RNA: {sequence!r}")
35
+ return rna
36
+
37
+
38
+ def rna_to_ppr_pairs(target_rna: str) -> List[Tuple[str, str]]:
39
+ """Return [(5th, last), ...] recognition pairs for each RNA base."""
40
+ rna = normalize_target_rna(target_rna)
41
+ return [_RNA_TO_CODE[b] for b in rna]
42
+
43
+
44
+ def rna_to_binder_aa(target_rna: str) -> str:
45
+ """
46
+ Build the continuous GRASP binder protein for a target RNA.
47
+
48
+ Does **not** use combinatorial library modules — only the PPR code and
49
+ the validated GRASP repeat scaffold (matches oh-bounded native 9S assemblies).
50
+ """
51
+ pairs = rna_to_ppr_pairs(target_rna)
52
+ parts = [NTERM_HELIX]
53
+ for fifth, last in pairs:
54
+ parts.append(REPEAT_TEMPLATE.format(fifth=fifth, last=last))
55
+ return "".join(parts)
56
+
57
+
58
+ def ppr_code_string(target_rna: str) -> str:
59
+ """Classic concatenated code, e.g. UUACACGUG → NDNDTNNNTNNNTDNDTD."""
60
+ return "".join(f"{a}{b}" for a, b in rna_to_ppr_pairs(target_rna))
61
+
62
+
63
+ def describe_binder(target_rna: str) -> dict:
64
+ rna = normalize_target_rna(target_rna)
65
+ aa = rna_to_binder_aa(rna)
66
+ pairs = rna_to_ppr_pairs(rna)
67
+ return {
68
+ "target_rna": rna,
69
+ "n_bases": len(rna),
70
+ "ppr_code": ppr_code_string(rna),
71
+ "ppr_pairs": [f"{a}{b}" for a, b in pairs],
72
+ "aa_sequence": aa,
73
+ "aa_length": len(aa),
74
+ "cds_length": 3 * len(aa),
75
+ "n_repeats": len(pairs),
76
+ }