Skip to content

Instantly share code, notes, and snippets.

@JustABiologist
Created August 9, 2026 14:39
Show Gist options
  • Select an option

  • Save JustABiologist/35762069350e47ca4351397be07e5896 to your computer and use it in GitHub Desktop.

Select an option

Save JustABiologist/35762069350e47ca4351397be07e5896 to your computer and use it in GitHub Desktop.
GRASP Library Designer (Colab / PyPI)
Display the source blob
Display the rendered blob
Raw
{
"nbformat": 4,
"nbformat_minor": 5,
"metadata": {
"kernelspec": {
"display_name": "Python 3",
"language": "python",
"name": "python3"
},
"language_info": {
"name": "python",
"pygments_lexer": "ipython3"
},
"colab": {
"provenance": [],
"toc_visible": true
}
},
"cells": [
{
"cell_type": "markdown",
"metadata": {},
"source": [
"# GRASP Library Designer\n",
"\n",
"Redesign and anneal the **42-module combinatorial GRASP library** (Farley et al., *NAR* 2025), then compile a target RNA with GAP.\n",
"\n",
"1. Run **0 · Install** once \n",
"2. Fill the forms and run cells top → bottom \n",
"\n",
"Code is hidden by default (Colab Forms).\n"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {},
"outputs": [],
"source": [
"#@title 0 · Install (PyPI) { display-mode: \"form\" }\n",
"#@markdown Installs everything from PyPI. No GitHub token needed. Re-run if imports fail after a runtime restart.\n",
"\n",
"%pip install -q -U \"grasp-library-designer>=0.1.0\"\n",
"\n",
"import importlib\n",
"import grasp_library\n",
"from importlib.metadata import version\n",
"\n",
"print(\"grasp-library-designer\", version(\"grasp-library-designer\"))\n",
"print(\"import ok:\", grasp_library.__name__)\n"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {},
"outputs": [],
"source": [
"#@title 1 · Settings { display-mode: \"form\" }\n",
"#@markdown Organism, synthesis, ligation, architecture, and anneal depth — then run this cell.\n",
"\n",
"target_rna = \"UUACACGUG\" #@param {type:\"string\"}\n",
"organism = \"Escherichia coli (Kazusa)\" #@param [\"Escherichia coli (Kazusa)\", \"Saccharomyces cerevisiae (Kazusa)\", \"Homo sapiens (Kazusa)\", \"Euglena gracilis nuclear (Kazusa)\", \"Chlamydomonas reinhardtii nuclear (Kazusa)\", \"Chlamydomonas reinhardtii chloroplast (Kazusa)\"]\n",
"genetic_code = 1 #@param {type:\"integer\"}\n",
"nterm_overhang = \"AGGT\" #@param [\"AGGT\", \"AATG\"]\n",
"architecture = \"9S\" #@param [\"9S\", \"14S\", \"19S\"]\n",
"synthesis_vendor = \"Twist · Standard gene guidelines\" #@param [\"Twist · Express / Low complexity\", \"Twist · Standard gene guidelines\", \"Twist · Complex Genes tolerant\", \"IDT · gBlocks / eBlocks conservative\", \"Generic · conservative (default)\"]\n",
"assembly_enzyme = \"GRASP default · BsaI + BpiI + BsmBI\" #@param [\"GRASP default · BsaI + BpiI + BsmBI\", \"BsaI (GGTCTC)\", \"BpiI / BbsI (GAAGAC)\", \"BsmBI / Esp3I (CGTCTC)\", \"None (no enzyme filter)\"]\n",
"ligation_table = \"T4 · 18 h · 25 °C (Potapov)\" #@param [\"T4 · 18 h · 25 °C (Potapov)\", \"T4 · 18 h · 37 °C (Potapov)\", \"T4 · 1 h · 25 °C (Potapov)\", \"BsaI-HFv2 · constant 37 °C\", \"BsmBI-v2 · constant 42 °C\"]\n",
"overhang_redesign = True #@param {type:\"boolean\"}\n",
"redesign_selection = \"knee\" #@param [\"knee\", \"max_fidelity\"]\n",
"optimize_depth = 2000 #@param {type:\"integer\"}\n",
"\n",
"from grasp_library import build_default_config, materialize_project\n",
"from grasp_library.colab_forms import apply_form_settings\n",
"from grasp_library import notebook_ui as ui\n",
"\n",
"PROJECT_DIR = materialize_project()\n",
"INPUT_DIR = PROJECT_DIR / \"input\"\n",
"OUTPUT_DIR = PROJECT_DIR / \"output\"\n",
"PROFILE_GB = PROJECT_DIR / \"profiles\" / \"grasp_nar2025\" / \"genbank\"\n",
"\n",
"CONFIG = build_default_config(INPUT_DIR)\n",
"CONFIG[\"project_name\"] = \"GRASP_library_colab\"\n",
"\n",
"applied = apply_form_settings(\n",
" CONFIG,\n",
" organism=organism,\n",
" genetic_code=int(genetic_code),\n",
" target_rna=target_rna,\n",
" nterm_overhang=nterm_overhang,\n",
" architecture=architecture,\n",
" synthesis_vendor=synthesis_vendor,\n",
" assembly_enzyme=assembly_enzyme,\n",
" ligation_table=ligation_table,\n",
" overhang_redesign=bool(overhang_redesign),\n",
" redesign_selection=redesign_selection,\n",
" optimize_depth=int(optimize_depth),\n",
")\n",
"CONFIG = applied[\"config\"]\n",
"CODON_DATA = applied[\"codon_data\"]\n",
"CODON_TABLE = applied[\"codon_table\"]\n",
"SELECTED_ORGANISM = organism\n",
"\n",
"parts = None\n",
"target_map = None\n",
"PARETO_FRONT = None\n",
"SELECTED_OVERHANGS = None\n",
"parts_with_redesigned_junctions = None\n",
"optimized_library = None\n",
"PARETO_PLOT = None\n",
"ASSEMBLY = None\n",
"FIDELITY = None\n",
"\n",
"ui.status(\n",
" f\"Target <b>{CONFIG['target_rna']}</b> · <b>{organism}</b> · \"\n",
" f\"arch <b>{architecture}</b> · N-term <code>{nterm_overhang}</code> · \"\n",
" f\"redesign <b>{CONFIG['overhang_redesign']['enabled']}</b> ({redesign_selection}) · \"\n",
" f\"depth <b>{CONFIG['optimizer']['iterations_per_part']:,}</b><br/>\"\n",
" f\"Project → <code>{PROJECT_DIR}</code>\"\n",
")\n"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {},
"outputs": [],
"source": [
"#@title 2 · Import GRASP modules { display-mode: \"form\" }\n",
"#@markdown Copies bundled Farley et al. GenBank into the project and builds parts tables.\n",
"\n",
"FORCE_REIMPORT = False #@param {type:\"boolean\"}\n",
"\n",
"from IPython.display import display\n",
"from grasp_library import ensure_grasp_imported\n",
"from grasp_library import notebook_ui as ui\n",
"\n",
"if not CODON_DATA:\n",
" ui.note(\"Run Settings first.\")\n",
"else:\n",
" imported = ensure_grasp_imported(\n",
" profile_genbank_dir=PROFILE_GB,\n",
" input_dir=INPUT_DIR,\n",
" force=bool(FORCE_REIMPORT),\n",
" log=print,\n",
" )\n",
" parts = imported[\"parts\"]\n",
" target_map = imported.get(\"target_map\")\n",
" display(parts.head())\n",
" jm = imported[\"junction_map\"]\n",
" display(\n",
" jm.groupby(\"junction\", as_index=False)\n",
" .first()[[\"junction\", \"native_overhang\"]]\n",
" )\n",
" ui.status(\n",
" f\"<b>{len(parts)}</b> modules · \"\n",
" f\"<b>{jm['junction'].nunique()}</b> junctions · \"\n",
" f\"<b>{len(imported['overhang_candidates'])}</b> overhang candidates\"\n",
" )\n"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {},
"outputs": [],
"source": [
"#@title 3 · Redesign overhangs { display-mode: \"form\" }\n",
"#@markdown Pareto search over synonym overhangs at fixed GRASP cut indices.\n",
"\n",
"RUN_OVERHANG_REDESIGN = True #@param {type:\"boolean\"}\n",
"SEED = 42 #@param {type:\"integer\"}\n",
"\n",
"import random\n",
"import numpy as np\n",
"import pandas as pd\n",
"from IPython.display import display\n",
"from grasp_library import (\n",
" LigationFidelityCalculator,\n",
" load_and_validate_parts,\n",
" optimize_coding_sequence,\n",
" run_overhang_redesign,\n",
")\n",
"from grasp_library import notebook_ui as ui\n",
"\n",
"random.seed(int(SEED))\n",
"np.random.seed(int(SEED))\n",
"\n",
"PARETO_FRONT = None\n",
"SELECTED_OVERHANGS = None\n",
"parts_with_redesigned_junctions = None\n",
"\n",
"if not RUN_OVERHANG_REDESIGN:\n",
" ui.note(\"RUN_OVERHANG_REDESIGN is off.\")\n",
"elif not CODON_DATA:\n",
" ui.note(\"Run Settings first.\")\n",
"else:\n",
" if parts is None and CONFIG[\"parts_file\"].exists():\n",
" parts = load_and_validate_parts(CONFIG[\"parts_file\"])\n",
" lig = CONFIG[\"ligation\"]\n",
" FIDELITY = LigationFidelityCalculator(\n",
" temperature=lig[\"temperature\"],\n",
" hours=lig[\"hours\"],\n",
" ligation_table=lig.get(\"ligation_table\"),\n",
" min_efficiency=lig.get(\"min_efficiency\", 0.25),\n",
" min_fidelity=lig.get(\"min_fidelity\", 0.9),\n",
" )\n",
" if not CONFIG.get(\"overhang_redesign\", {}).get(\"enabled\", True):\n",
" ui.note(\"Overhang redesign disabled in Settings — keeping native overhangs.\")\n",
" parts_with_redesigned_junctions = parts\n",
" else:\n",
" PARETO_FRONT, SELECTED_OVERHANGS, parts_with_redesigned_junctions = run_overhang_redesign(\n",
" parts=parts,\n",
" codon_data=CODON_DATA,\n",
" config=CONFIG,\n",
" optimize_coding_sequence=optimize_coding_sequence,\n",
" input_dir=INPUT_DIR,\n",
" output_dir=OUTPUT_DIR,\n",
" seed=int(SEED),\n",
" fidelity=FIDELITY,\n",
" log=print,\n",
" )\n",
" display(PARETO_FRONT)\n",
" display(\n",
" pd.DataFrame([SELECTED_OVERHANGS], index=[\"overhang\"])\n",
" .T.rename(columns={\"overhang\": \"selected\"})\n",
" )\n",
" ui.status(\"Overhang redesign done — next: anneal library.\")\n"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {},
"outputs": [],
"source": [
"#@title 4 · Anneal library { display-mode: \"form\" }\n",
"#@markdown Full CDS simulated annealing for every module.\n",
"\n",
"RUN_LIBRARY_OPTIMIZE = True #@param {type:\"boolean\"}\n",
"\n",
"from IPython.display import display\n",
"from grasp_library import (\n",
" load_and_validate_parts,\n",
" optimize_library,\n",
" run_library_optimize,\n",
")\n",
"from grasp_library import notebook_ui as ui\n",
"\n",
"optimized_library = None\n",
"\n",
"if not RUN_LIBRARY_OPTIMIZE:\n",
" ui.note(\"RUN_LIBRARY_OPTIMIZE is off.\")\n",
"elif not CODON_DATA:\n",
" ui.note(\"Run Settings first.\")\n",
"else:\n",
" source_parts = (\n",
" parts_with_redesigned_junctions\n",
" if parts_with_redesigned_junctions is not None\n",
" else parts\n",
" )\n",
" if source_parts is None and CONFIG[\"parts_file\"].exists():\n",
" source_parts = load_and_validate_parts(CONFIG[\"parts_file\"])\n",
" optimized_library = run_library_optimize(\n",
" parts=source_parts,\n",
" codon_data=CODON_DATA,\n",
" config=CONFIG,\n",
" optimize_library=optimize_library,\n",
" output_dir=OUTPUT_DIR,\n",
" log=print,\n",
" )\n",
" if SELECTED_OVERHANGS:\n",
" tag = \";\".join(f\"{k}={v}\" for k, v in sorted(SELECTED_OVERHANGS.items()))\n",
" optimized_library = optimized_library.copy()\n",
" optimized_library[\"selected_overhangs\"] = tag\n",
" optimized_library.to_csv(OUTPUT_DIR / \"optimized_library.csv\", index=False)\n",
" display(optimized_library.head())\n",
" ui.status(\n",
" f\"Annealed <b>{len(optimized_library)}</b> sequences → \"\n",
" f\"<code>{OUTPUT_DIR / 'optimized_library.csv'}</code>\"\n",
" )\n"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {},
"outputs": [],
"source": [
"#@title 5 · Pareto plot { display-mode: \"form\" }\n",
"#@markdown Rescores the front after redesign + anneal.\n",
"\n",
"RUN_PARETO_PLOT = True #@param {type:\"boolean\"}\n",
"DEEP_RESCORE_ALL = False #@param {type:\"boolean\"}\n",
"\n",
"import pandas as pd\n",
"from IPython.display import display\n",
"from grasp_library import load_and_validate_parts, plot_library_pareto_after_anneal\n",
"from grasp_library.workflows import parse_overhang_selection\n",
"from grasp_library import notebook_ui as ui\n",
"\n",
"PARETO_PLOT = None\n",
"\n",
"if not RUN_PARETO_PLOT:\n",
" ui.note(\"RUN_PARETO_PLOT is off.\")\n",
"elif optimized_library is None or getattr(optimized_library, \"empty\", False):\n",
" ui.note(\"Run Anneal library first.\")\n",
"else:\n",
" front = PARETO_FRONT\n",
" selected = SELECTED_OVERHANGS\n",
" src_parts = parts\n",
"\n",
" if front is None or getattr(front, \"empty\", True):\n",
" path = OUTPUT_DIR / \"pareto_front.csv\"\n",
" if path.exists():\n",
" front = pd.read_csv(path)\n",
" PARETO_FRONT = front\n",
" else:\n",
" ui.note(\"No Pareto front — run Redesign overhangs first (or enable redesign).\")\n",
" front = None\n",
"\n",
" if front is not None and not front.empty:\n",
" if selected is None and (OUTPUT_DIR / \"selected_overhangs.csv\").exists():\n",
" sel = pd.read_csv(OUTPUT_DIR / \"selected_overhangs.csv\")\n",
" if \"overhangs\" in sel.columns:\n",
" selected = parse_overhang_selection(sel.iloc[0][\"overhangs\"])\n",
" SELECTED_OVERHANGS = selected\n",
" if src_parts is None and CONFIG[\"parts_file\"].exists():\n",
" src_parts = load_and_validate_parts(CONFIG[\"parts_file\"])\n",
" parts = src_parts\n",
"\n",
" junction_map = pd.read_csv(INPUT_DIR / \"junction_map.csv\")\n",
" PARETO_PLOT = plot_library_pareto_after_anneal(\n",
" front=front,\n",
" parts=src_parts,\n",
" junction_map=junction_map,\n",
" codon_data=CODON_DATA,\n",
" config=CONFIG,\n",
" optimized_library=optimized_library,\n",
" selected_overhangs=selected,\n",
" fidelity=FIDELITY,\n",
" deep_all=bool(DEEP_RESCORE_ALL),\n",
" output_dir=OUTPUT_DIR,\n",
" log=print,\n",
" )\n",
" display(PARETO_PLOT[\"front\"])\n",
" display(PARETO_PLOT[\"figure\"])\n",
" chosen = PARETO_PLOT[\"chosen\"]\n",
" ui.status(\n",
" f\"Selected · synthesis <b>{float(chosen['synthesis']):.3f}</b> · \"\n",
" f\"codon <b>{float(chosen['codon_optimality']):.3f}</b> · \"\n",
" f\"fidelity <b>{float(chosen['ligation_fidelity']):.6f}</b><br>\"\n",
" f\"Plot → <code>{OUTPUT_DIR / 'pareto_front.png'}</code>\"\n",
" )\n"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {},
"outputs": [],
"source": [
"#@title 6 · Export library { display-mode: \"form\" }\n",
"#@markdown Writes CSV / FASTA / Excel and downloads the Excel in Colab.\n",
"\n",
"from grasp_library import export_optimized_library\n",
"from grasp_library import notebook_ui as ui\n",
"\n",
"if optimized_library is None:\n",
" ui.note(\"Run Anneal library first.\")\n",
"else:\n",
" paths = export_optimized_library(\n",
" optimized_library,\n",
" OUTPUT_DIR,\n",
" selected_overhangs=SELECTED_OVERHANGS,\n",
" )\n",
" ui.status(\n",
" \"Exported:<br/>\"\n",
" f\"• <code>{paths['csv']}</code><br/>\"\n",
" f\"• <code>{paths['fasta']}</code><br/>\"\n",
" f\"• <code>{paths['xlsx']}</code>\"\n",
" )\n",
" if \"google.colab\" in __import__(\"sys\").modules:\n",
" from google.colab import files\n",
" files.download(str(paths[\"xlsx\"]))\n",
" for p in sorted(OUTPUT_DIR.glob(\"optimized_grasp_*\")):\n",
" if p.is_file():\n",
" print(p.name)\n"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {},
"outputs": [],
"source": [
"#@title 7 · Compile target RNA { display-mode: \"form\" }\n",
"#@markdown GAP-compile the Settings target against the annealed library and stitch the CDS.\n",
"\n",
"RUN_COMPILE = True #@param {type:\"boolean\"}\n",
"\n",
"from IPython.display import display\n",
"from grasp_library import compile_and_assemble_target\n",
"from grasp_library import notebook_ui as ui\n",
"\n",
"ASSEMBLY = None\n",
"\n",
"if not RUN_COMPILE:\n",
" ui.note(\"RUN_COMPILE is off.\")\n",
"elif optimized_library is None:\n",
" ui.note(\"Run Anneal library first.\")\n",
"else:\n",
" ASSEMBLY = compile_and_assemble_target(\n",
" target_rna=CONFIG[\"target_rna\"],\n",
" optimized_library=optimized_library,\n",
" config=CONFIG,\n",
" input_dir=INPUT_DIR,\n",
" output_dir=OUTPUT_DIR,\n",
" architecture=CONFIG.get(\"architecture\", \"9S\"),\n",
" nterm_overhang=CONFIG.get(\"nterm_overhang\", \"AGGT\"),\n",
" )\n",
" display(ASSEMBLY[\"assembly_plan\"])\n",
" asm = ASSEMBLY[\"assembled\"]\n",
" warn = asm.get(\"stitch_warning\") or \"\"\n",
" ui.status(\n",
" f\"Target <b>{ASSEMBLY['target_rna']}</b> · \"\n",
" f\"translation verified <b>{asm.get('translation_verified')}</b>\"\n",
" + (f\"<br/>{warn}\" if warn else \"\")\n",
" + f\"<br/>Plan → <code>{ASSEMBLY['plan_csv']}</code>\"\n",
" + f\"<br/>FASTA → <code>{ASSEMBLY['assembled_fasta']}</code>\"\n",
" )\n",
" for key, value in asm.items():\n",
" if key not in {\"assembled_cds\", \"expected_protein\", \"observed_protein\"}:\n",
" print(f\"{key}: {value}\")\n"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"## Notes\n",
"\n",
"| Step | What happens |\n",
"|---|---|\n",
"| Install | `pip install grasp-library-designer` from PyPI |\n",
"| Import | Bundled GenBank → parts / junctions / candidates |\n",
"| Redesign | Synonym overhangs at fixed cut indices |\n",
"| Anneal | Masked SA for every module |\n",
"| Compile | GAP part order + CDS stitch |\n",
"\n",
"For a **single binder without the combinatorial library**, open `grasp_oneshot_designer.ipynb`.\n",
"\n",
"Package: https://pypi.org/project/grasp-library-designer/\n"
]
}
]
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment