[{"data":1,"prerenderedAt":-1},["ShallowReactive",2],{"skill:01M6XFEY3B4C2905VGXA8JY607":3,"skill-same:01M6XFEY3B4C2905VGXA8JY607":91},{"skillNo":4,"name":5,"nameZh":6,"description":7,"descriptionZh":6,"repositoryFullName":8,"ownerLogin":9,"ownerAvatarUrl":10,"ownerAccountNo":11,"ownerDisplayName":12,"repositoryNo":13,"starsCount":14,"licenseSpdxId":15,"licenseFileUrl":6,"sourceHtmlUrl":16,"categories":17,"keywords":23,"publishedAt":45,"linkOnly":46,"markdownContent":47,"markdownBody":48,"frontMatter":49,"refName":53,"commitSha":54,"skillDirectory":55,"forksCount":14,"repositoryHtmlUrl":56,"repositoryHomepageUrl":6,"ownerHtmlUrl":57,"ownerBlogUrl":6,"ownerDescription":6,"updatedAt":58,"install":59,"resources":72},"01M6XFEY3B4C2905VGXA8JY607","synthetic-biology",null,"Synthetic biology design and simulation tools. Codon optimization, gene circuit ODE modeling with growth feedback, SBML model creation, bifurcation analysis, barcode sequencing fitness analysis, and therapeutic genome engineering. For metabolic modeling use cobrapy; for sequence tools use biopython.","fadrienne\u002FMyGitHub","fadrienne","https:\u002F\u002Favatars.githubusercontent.com\u002Fu\u002F197874571?v=4","01M6X64V8VWCRSMFZ4EPS2BWXG","Francesca Adrienne","01M6X64VD5MW4F9PHDWQKS7ZAF",0,"MIT","https:\u002F\u002Fgithub.com\u002Ffadrienne\u002FMyGitHub\u002Fblob\u002Fmain\u002Fopenscience\u002Fbackend\u002Fcli\u002Fskills\u002Fbiology\u002Fsynthetic-biology\u002FSKILL.md",[18],{"categoryNo":19,"categoryName":20,"taxonomyType":21,"taxonomyTypeDesc":22},"01JBSEEDCAT000000000000015","视觉设计","SCENARIO","使用场景",[24,25,26,27,28,29,30,31,32,33,34,35,36,37,38,39,40,41,42,43,44],"synthetic biology","biology","synthetic","creation","Bifurcation","fitness","sequence","gene","sequence tools","circuit","sequencing","barcode","design","modeling","feedback","model","simulation","analysis","cobrapy","biopython","Tools","2026-11-10 10:12:30",false,"---\nname: synthetic-biology\ndescription: Synthetic biology design and simulation tools. Codon optimization, gene circuit ODE modeling with growth feedback, SBML model creation, bifurcation analysis, barcode sequencing fitness analysis, and therapeutic genome engineering. For metabolic modeling use cobrapy; for sequence tools use biopython.\ncategory: biology\nlicense: MIT license\nmetadata:\n    skill-author: InkVell Inc.\n---\n\n# Synthetic Biology: Design & Simulation\n\n## Overview\n\nSynthetic Biology provides computational tools for designing and simulating engineered biological systems. This skill covers codon optimization with species-specific usage tables, gene circuit ODE modeling (repressilator, toggle switch, inducible promoters) with growth dilution coupling, SBML model creation and validation using python-libsbml, bifurcation analysis for bistable circuits, barcode sequencing fitness analysis, and genome engineering with expression cassette insertion. All simulations produce quantitative outputs suitable for guiding experimental design.\n\n## When to Use This Skill\n\n- Optimizing gene sequences for heterologous expression (codon adaptation)\n- Simulating gene circuit dynamics (toggle switches, repressilators, inducible systems)\n- Creating standardized SBML models of biological networks\n- Analyzing bistability and bifurcation behavior in synthetic circuits\n- Processing barcode sequencing data for fitness landscape analysis\n- Designing expression cassettes and generating annotated plasmid maps\n- Sensitivity analysis of circuit parameters for robust design\n\n**Related Skills:** For constraint-based metabolic modeling use `cobrapy`. For sequence manipulation and file parsing use `biopython`. For molecular cloning simulation use `molecular-cloning`.\n\n## Installation\n\n```bash\nuv pip install python-libsbml scipy biopython numpy pandas matplotlib\n```\n\n## Quick Start\n\n```python\nimport numpy as np\nfrom scipy.integrate import solve_ivp\n\n# Toggle switch: two mutually repressing genes\ndef toggle_switch(t, y, alpha1, alpha2, beta, n, gamma):\n    u, v = y  # Protein concentrations\n    du = alpha1 \u002F (1 + v**n) - (beta + gamma) * u  # gamma = growth dilution\n    dv = alpha2 \u002F (1 + u**n) - (beta + gamma) * v\n    return [du, dv]\n\nsol = solve_ivp(toggle_switch, [0, 50], [0.1, 3.0],\n                args=(5.0, 5.0, 0.5, 2.0, 0.1),\n                t_eval=np.linspace(0, 50, 500))\n\nprint(f\"Final state: u={sol.y[0,-1]:.3f}, v={sol.y[1,-1]:.3f}\")\nprint(f\"Bistable: {'Yes' if abs(sol.y[0,-1] - sol.y[1,-1]) > 0.5 else 'No'}\")\n```\n\n## Core Capabilities\n\n### 1. Codon Optimization\n\nOptimize gene sequences for expression in target organisms.\n\n```python\nimport numpy as np\nfrom collections import Counter\n\n# E. coli codon usage table (fraction per amino acid)\nECOLI_CODON_TABLE = {\n    'F': {'TTT': 0.58, 'TTC': 0.42},\n    'L': {'TTA': 0.11, 'TTG': 0.11, 'CTT': 0.10, 'CTC': 0.10, 'CTA': 0.04, 'CTG': 0.54},\n    'I': {'ATT': 0.49, 'ATC': 0.39, 'ATA': 0.07},\n    'M': {'ATG': 1.0},\n    'V': {'GTT': 0.28, 'GTC': 0.20, 'GTA': 0.17, 'GTG': 0.35},\n    'S': {'TCT': 0.17, 'TCC': 0.15, 'TCA': 0.14, 'TCG': 0.14, 'AGT': 0.16, 'AGC': 0.25},\n    'P': {'CCT': 0.18, 'CCC': 0.13, 'CCA': 0.20, 'CCG': 0.49},\n    'T': {'ACT': 0.19, 'ACC': 0.40, 'ACA': 0.17, 'ACG': 0.25},\n    'A': {'GCT': 0.18, 'GCC': 0.26, 'GCA': 0.23, 'GCG': 0.33},\n    'Y': {'TAT': 0.59, 'TAC': 0.41},\n    '*': {'TAA': 0.61, 'TAG': 0.09, 'TGA': 0.30},\n    'H': {'CAT': 0.57, 'CAC': 0.43},\n    'Q': {'CAA': 0.34, 'CAG': 0.66},\n    'N': {'AAT': 0.49, 'AAC': 0.51},\n    'K': {'AAA': 0.74, 'AAG': 0.26},\n    'D': {'GAT': 0.63, 'GAC': 0.37},\n    'E': {'GAA': 0.68, 'GAG': 0.32},\n    'C': {'TGT': 0.46, 'TGC': 0.54},\n    'W': {'TGG': 1.0},\n    'R': {'CGT': 0.36, 'CGC': 0.36, 'CGA': 0.07, 'CGG': 0.11, 'AGA': 0.07, 'AGG': 0.04},\n    'G': {'GGT': 0.35, 'GGC': 0.37, 'GGA': 0.13, 'GGG': 0.15},\n}\n\nCODON_TO_AA = {}\nfor aa, codons in ECOLI_CODON_TABLE.items():\n    for codon in codons:\n        CODON_TO_AA[codon] = aa\n\ndef calculate_cai(dna_seq, codon_table=ECOLI_CODON_TABLE):\n    \"\"\"Calculate Codon Adaptation Index.\"\"\"\n    codons = [dna_seq[i:i+3] for i in range(0, len(dna_seq)-2, 3)]\n    weights = []\n\n    for codon in codons:\n        aa = CODON_TO_AA.get(codon)\n        if aa and aa != '*':\n            aa_codons = codon_table[aa]\n            max_freq = max(aa_codons.values())\n            w = aa_codons.get(codon, 0) \u002F max_freq if max_freq > 0 else 0\n            if w > 0:\n                weights.append(np.log(w))\n\n    cai = np.exp(np.mean(weights)) if weights else 0\n    return cai\n\ndef optimize_codons(protein_seq, codon_table=ECOLI_CODON_TABLE,\n                    gc_min=0.40, gc_max=0.60):\n    \"\"\"Optimize codons for target organism.\"\"\"\n    optimized = []\n\n    for aa in protein_seq:\n        if aa == '*':\n            break\n        if aa not in codon_table:\n            raise ValueError(f\"Unknown amino acid: {aa}\")\n\n        codons = codon_table[aa]\n        # Select highest-frequency codon\n        best_codon = max(codons, key=codons.get)\n        optimized.append(best_codon)\n\n    dna_seq = ''.join(optimized)\n\n    # Check GC content\n    gc = (dna_seq.count('G') + dna_seq.count('C')) \u002F len(dna_seq)\n    cai = calculate_cai(dna_seq, codon_table)\n\n    print(f\"Optimized sequence: {len(dna_seq)} bp\")\n    print(f\"GC content: {gc:.1%}\")\n    print(f\"CAI: {cai:.4f}\")\n\n    if gc \u003C gc_min or gc > gc_max:\n        print(f\"WARNING: GC content {gc:.1%} outside target range [{gc_min:.0%}-{gc_max:.0%}]\")\n\n    return dna_seq, cai, gc\n\n# Example\nprotein = \"MSKGEELFTGVVPILVELDGDVNGHKFSVSGEGEGDATYGKL\"  # GFP fragment\nopt_dna, cai, gc = optimize_codons(protein)\n```\n\n### 2. Gene Circuit Simulation\n\nODE models for common synthetic gene circuits.\n\n```python\nimport numpy as np\nfrom scipy.integrate import solve_ivp\n\ndef repressilator(t, y, alpha, n, beta, gamma):\n    \"\"\"Repressilator: 3-gene oscillator (Elowitz & Leibler).\n    gamma = growth dilution rate.\"\"\"\n    m1, p1, m2, p2, m3, p3 = y\n\n    dm1 = alpha \u002F (1 + p3**n) - (beta + gamma) * m1\n    dp1 = m1 - (beta + gamma) * p1\n    dm2 = alpha \u002F (1 + p1**n) - (beta + gamma) * m2\n    dp2 = m2 - (beta + gamma) * p2\n    dm3 = alpha \u002F (1 + p2**n) - (beta + gamma) * m3\n    dp3 = m3 - (beta + gamma) * p3\n\n    return [dm1, dp1, dm2, dp2, dm3, dp3]\n\ndef inducible_promoter(t, y, V_max, Km, n, beta, gamma, inducer_conc):\n    \"\"\"Inducible gene expression (Hill function).\"\"\"\n    mRNA, protein = y\n    induction = V_max * inducer_conc**n \u002F (Km**n + inducer_conc**n)\n    dmRNA = induction - (beta + gamma) * mRNA\n    dprotein = mRNA - (beta + gamma) * protein\n    return [dmRNA, dprotein]\n\n# Simulate repressilator\ny0 = [0.5, 1.0, 0.0, 0.0, 0.0, 0.0]\nsol = solve_ivp(repressilator, [0, 200], y0,\n                args=(5.0, 2.0, 0.5, 0.1),\n                t_eval=np.linspace(0, 200, 2000),\n                method='RK45')\n\n# Check for oscillation\nfrom scipy.signal import find_peaks\npeaks, _ = find_peaks(sol.y[1])\nif len(peaks) > 2:\n    period = np.mean(np.diff(sol.t[peaks]))\n    print(f\"Oscillation period: {period:.1f} time units\")\n    print(f\"Amplitude: {sol.y[1, peaks].mean() - sol.y[1].min():.3f}\")\nelse:\n    print(\"No sustained oscillations detected\")\n\n# Parameter sensitivity analysis\ndef sensitivity_analysis(param_name, param_values, base_params, y0, t_span):\n    \"\"\"Sweep one parameter and measure output.\"\"\"\n    results = []\n    for val in param_values:\n        params = base_params.copy()\n        params[param_name] = val\n        sol = solve_ivp(repressilator, t_span, y0,\n                        args=tuple(params.values()),\n                        t_eval=np.linspace(*t_span, 500))\n        # Measure amplitude\n        amplitude = sol.y[1].max() - sol.y[1].min()\n        results.append({'param_value': val, 'amplitude': amplitude})\n    return pd.DataFrame(results)\n```\n\n### 3. SBML Model Creation\n\nBuild standardized SBML models with python-libsbml.\n\n```python\nimport libsbml\n\ndef create_sbml_model(model_name, compartments, species_list, reactions):\n    \"\"\"Create SBML Level 3 model.\n\n    Args:\n        model_name: string name\n        compartments: list of (id, size) tuples\n        species_list: list of (id, compartment, initial_amount) tuples\n        reactions: list of dicts with 'id', 'reactants', 'products', 'kinetic_law'\n    \"\"\"\n    doc = libsbml.SBMLDocument(3, 2)\n    model = doc.createModel()\n    model.setId(model_name)\n\n    # Compartments\n    for comp_id, size in compartments:\n        c = model.createCompartment()\n        c.setId(comp_id)\n        c.setConstant(True)\n        c.setSize(size)\n        c.setSpatialDimensions(3)\n\n    # Species\n    for sp_id, comp_id, init_amount in species_list:\n        s = model.createSpecies()\n        s.setId(sp_id)\n        s.setCompartment(comp_id)\n        s.setInitialAmount(init_amount)\n        s.setConstant(False)\n        s.setBoundaryCondition(False)\n        s.setHasOnlySubstanceUnits(False)\n\n    # Reactions\n    for rxn in reactions:\n        r = model.createReaction()\n        r.setId(rxn['id'])\n        r.setReversible(rxn.get('reversible', False))\n\n        for reactant_id, stoich in rxn.get('reactants', []):\n            sr = r.createReactant()\n            sr.setSpecies(reactant_id)\n            sr.setStoichiometry(stoich)\n            sr.setConstant(True)\n\n        for product_id, stoich in rxn.get('products', []):\n            sp = r.createProduct()\n            sp.setSpecies(product_id)\n            sp.setStoichiometry(stoich)\n            sp.setConstant(True)\n\n        kl = r.createKineticLaw()\n        kl.setMath(libsbml.parseL3Formula(rxn['kinetic_law']))\n\n        # Add parameters\n        for param_id, value in rxn.get('parameters', []):\n            p = kl.createLocalParameter()\n            p.setId(param_id)\n            p.setValue(value)\n\n    # Validate\n    errors = doc.getNumErrors()\n    if errors > 0:\n        for i in range(errors):\n            print(f\"SBML Error: {doc.getError(i).getMessage()}\")\n\n    return doc\n\n# Example: simple enzymatic reaction\ndoc = create_sbml_model(\n    'enzyme_kinetics',\n    compartments=[('cell', 1.0)],\n    species_list=[('S', 'cell', 10.0), ('P', 'cell', 0.0), ('E', 'cell', 1.0)],\n    reactions=[{\n        'id': 'v1',\n        'reactants': [('S', 1)],\n        'products': [('P', 1)],\n        'kinetic_law': 'Vmax * S \u002F (Km + S)',\n        'parameters': [('Vmax', 1.0), ('Km', 0.5)]\n    }]\n)\n\n# Write to file\nlibsbml.writeSBMLToFile(doc, 'model.xml')\nprint(\"SBML model written to model.xml\")\n```\n\n### 4. Bifurcation Analysis\n\nIdentify bistability in gene circuits.\n\n```python\nimport numpy as np\nfrom scipy.optimize import fsolve\n\ndef toggle_steady_states(alpha1, alpha2, n, beta):\n    \"\"\"Find steady states of toggle switch by sweeping inducer.\"\"\"\n    def steady_state_eq(x, alpha1_eff, alpha2, n, beta):\n        u, v = x\n        eq1 = alpha1_eff \u002F (1 + v**n) - beta * u\n        eq2 = alpha2 \u002F (1 + u**n) - beta * v\n        return [eq1, eq2]\n\n    inducer_values = np.linspace(0, 10, 200)\n    stable_u = []\n    stable_v = []\n\n    for ind in inducer_values:\n        alpha1_eff = alpha1 * (1 + ind)  # Inducer enhances gene 1 expression\n        solutions = []\n\n        # Try multiple initial conditions to find all steady states\n        for u0 in [0.01, 1.0, 5.0, 10.0]:\n            for v0 in [0.01, 1.0, 5.0, 10.0]:\n                try:\n                    sol = fsolve(steady_state_eq, [u0, v0],\n                                args=(alpha1_eff, alpha2, n, beta),\n                                full_output=True)\n                    if sol[2] == 1:  # Converged\n                        u, v = sol[0]\n                        if u > 0 and v > 0:\n                            solutions.append((round(u, 4), round(v, 4)))\n                except Exception:\n                    pass\n\n        # Deduplicate\n        unique = list(set(solutions))\n        for u, v in unique:\n            stable_u.append({'inducer': ind, 'u': u, 'branch': 'high' if u > v else 'low'})\n\n    import pandas as pd\n    df = pd.DataFrame(stable_u)\n    n_branches = df.groupby('inducer')['branch'].nunique()\n    bistable_range = n_branches[n_branches > 1]\n\n    if len(bistable_range) > 0:\n        print(f\"Bistable region: inducer = [{bistable_range.index.min():.2f}, \"\n              f\"{bistable_range.index.max():.2f}]\")\n    else:\n        print(\"No bistability detected\")\n\n    return df\n\nresults = toggle_steady_states(alpha1=3.0, alpha2=3.0, n=2.5, beta=1.0)\n```\n\n### 5. Barcode Sequencing Analysis\n\nAnalyze fitness from barcode tracking experiments.\n\n```python\nimport pandas as pd\nimport numpy as np\nfrom scipy.cluster.hierarchy import linkage, fcluster\n\ndef analyze_barcode_fitness(count_table, reference_timepoint='T0', min_reads=10):\n    \"\"\"Calculate fitness from barcode count data.\n\n    Args:\n        count_table: DataFrame with barcodes as index, timepoints as columns\n        reference_timepoint: column name for initial counts\n    \"\"\"\n    # Filter low-abundance barcodes\n    mask = count_table[reference_timepoint] >= min_reads\n    filtered = count_table[mask].copy()\n    print(f\"Barcodes passing filter: {len(filtered)} \u002F {len(count_table)}\")\n\n    # Normalize to relative frequency\n    normalized = filtered.div(filtered.sum(axis=0), axis=1)\n\n    # Calculate log2 fold change vs reference\n    fitness = np.log2(normalized.div(normalized[reference_timepoint], axis=0) + 1e-10)\n    fitness = fitness.drop(columns=[reference_timepoint])\n\n    # Summary statistics\n    for col in fitness.columns:\n        positive = (fitness[col] > 0).sum()\n        negative = (fitness[col] \u003C 0).sum()\n        print(f\"{col}: {positive} positive, {negative} negative fitness barcodes\")\n\n    return fitness\n\ndef cluster_lineage_fitness(fitness_df, n_clusters=5):\n    \"\"\"Hierarchical clustering of barcode fitness profiles.\"\"\"\n    Z = linkage(fitness_df.values, method='ward')\n    clusters = fcluster(Z, n_clusters, criterion='maxclust')\n    fitness_df['cluster'] = clusters\n\n    # Cluster summary\n    for c in range(1, n_clusters+1):\n        cluster_data = fitness_df[fitness_df['cluster'] == c].drop(columns=['cluster'])\n        print(f\"Cluster {c} ({len(cluster_data)} barcodes): \"\n              f\"mean fitness = {cluster_data.values.mean():.3f}\")\n\n    return fitness_df\n```\n\n### 6. Genome Engineering\n\nDesign and annotate expression cassettes.\n\n```python\nfrom Bio.Seq import Seq\nfrom Bio.SeqRecord import SeqRecord\nfrom Bio.SeqFeature import SeqFeature, FeatureLocation\nfrom Bio import SeqIO\n\ndef insert_expression_cassette(genome_record, insert_seq, locus_position,\n                                promoter_name='Ptac', gene_name='gfp',\n                                terminator_name='T7_term'):\n    \"\"\"Insert expression cassette at specified genomic locus.\"\"\"\n    # Build cassette\n    cassette_features = []\n    pos = 0\n\n    # Promoter (assume 100bp)\n    promoter_seq = 'A' * 100  # Placeholder — use actual sequence\n    cassette_features.append(SeqFeature(\n        FeatureLocation(pos, pos + len(promoter_seq)),\n        type='promoter', qualifiers={'label': promoter_name}\n    ))\n    pos += len(promoter_seq)\n\n    # RBS (20bp)\n    rbs_seq = 'AAGGAGATATACAT'  # Consensus RBS\n    cassette_features.append(SeqFeature(\n        FeatureLocation(pos, pos + len(rbs_seq)),\n        type='RBS', qualifiers={'label': 'RBS'}\n    ))\n    pos += len(rbs_seq)\n\n    # CDS\n    cassette_features.append(SeqFeature(\n        FeatureLocation(pos, pos + len(insert_seq)),\n        type='CDS', qualifiers={'label': gene_name, 'translation': str(Seq(insert_seq).translate())}\n    ))\n    pos += len(insert_seq)\n\n    # Terminator (50bp)\n    term_seq = 'T' * 50\n    cassette_features.append(SeqFeature(\n        FeatureLocation(pos, pos + len(term_seq)),\n        type='terminator', qualifiers={'label': terminator_name}\n    ))\n\n    full_cassette = promoter_seq + rbs_seq + insert_seq + term_seq\n\n    # Insert into genome\n    new_seq = str(genome_record.seq[:locus_position]) + full_cassette + \\\n              str(genome_record.seq[locus_position:])\n\n    # Adjust feature positions\n    offset = len(full_cassette)\n    new_features = []\n    for f in genome_record.features:\n        if f.location.start >= locus_position:\n            new_loc = FeatureLocation(f.location.start + offset,\n                                       f.location.end + offset, f.location.strand)\n            new_features.append(SeqFeature(new_loc, type=f.type, qualifiers=f.qualifiers))\n        else:\n            new_features.append(f)\n\n    # Add cassette features\n    for f in cassette_features:\n        adjusted = SeqFeature(\n            FeatureLocation(f.location.start + locus_position,\n                           f.location.end + locus_position),\n            type=f.type, qualifiers=f.qualifiers\n        )\n        new_features.append(adjusted)\n\n    new_record = SeqRecord(Seq(new_seq), id=genome_record.id,\n                           name=genome_record.name,\n                           description=f\"{genome_record.description} + {gene_name} cassette\",\n                           features=new_features)\n    return new_record\n```\n\n## Typical Workflows\n\n### Workflow 1: Optimize Gene for E. coli Expression and Calculate CAI\n\n```python\nprotein_seq = \"MVSKGEELFTGVVPILVELDGDVNGHKFSVSGEGEGDATYGKLTLKFICTTGKLPVPWPTLVTTLTYGVQCFSRYPDHMKQHDFFKSAMPEGYVQERTIFFKDDGNYKTRAEVKFEGDTLVNRIELKGIDFKEDGNILGHKLEYNYNSHNVYIMADKQKNGIKVNFKIRHNIEDGSVQLADHYQQNTPIGDGPVLLPDNHYLSTQSALSKDPNEKRDHMVLLEFVTAAGITLGMDELYK\"\nopt_dna, cai, gc = optimize_codons(protein_seq)\nprint(f\"Original CAI: {calculate_cai(opt_dna):.4f}\")\n```\n\n### Workflow 2: Simulate Toggle Switch with Growth Dilution\n\n```python\nimport numpy as np\nfrom scipy.integrate import solve_ivp\n\nsol = solve_ivp(toggle_switch, [0, 100], [0.1, 3.0],\n                args=(5.0, 5.0, 0.5, 2.0, 0.1),\n                t_eval=np.linspace(0, 100, 1000))\nprint(f\"Final: u={sol.y[0,-1]:.3f}, v={sol.y[1,-1]:.3f}\")\nprint(f\"State: {'Gene 1 ON' if sol.y[0,-1] > sol.y[1,-1] else 'Gene 2 ON'}\")\n```\n\n### Workflow 3: Create SBML Model of a Metabolic Pathway\n\n```python\ndoc = create_sbml_model(\n    'glycolysis_simplified',\n    compartments=[('cytoplasm', 1.0)],\n    species_list=[\n        ('glucose', 'cytoplasm', 5.0),\n        ('G6P', 'cytoplasm', 0.0),\n        ('pyruvate', 'cytoplasm', 0.0),\n        ('ATP', 'cytoplasm', 2.0),\n    ],\n    reactions=[\n        {'id': 'hexokinase', 'reactants': [('glucose', 1), ('ATP', 1)],\n         'products': [('G6P', 1)], 'kinetic_law': 'Vmax * glucose * ATP \u002F ((Km_g + glucose) * (Km_a + ATP))',\n         'parameters': [('Vmax', 1.0), ('Km_g', 0.1), ('Km_a', 0.5)]},\n        {'id': 'glycolysis', 'reactants': [('G6P', 1)],\n         'products': [('pyruvate', 2), ('ATP', 2)], 'kinetic_law': 'k * G6P',\n         'parameters': [('k', 0.5)]},\n    ]\n)\nlibsbml.writeSBMLToFile(doc, 'glycolysis.xml')\n```\n\n## Best Practices\n\n1. **Codon optimization** — always check GC content after optimization; extreme GC can cause expression problems\n2. **Circuit simulation** — include growth dilution term (gamma * x) in all ODE models; cells divide, diluting intracellular molecules\n3. **SBML validation** — always call `doc.getNumErrors()` after model creation; common errors are missing units and unbalanced reactions\n4. **Bifurcation analysis** — use multiple initial conditions to find all steady states; bistable systems have hysteresis\n5. **Barcode fitness** — require minimum read count (>10) to filter PCR\u002Fsequencing noise; use log2 fold change for fitness\n6. **Stiffness** — gene circuits with fast mRNA and slow protein dynamics are stiff; use `method='BDF'` in `solve_ivp`\n\n## Troubleshooting\n\n**Problem:** ODE solver fails with \"excess work\"\n**Solution:** Increase `max_step` or switch to stiff solver (`BDF`, `Radau`). Check parameter values for unreasonably large rates.\n\n**Problem:** python-libsbml not found after installation\n**Solution:** Use `pip install python-libsbml` (not `libsbml`). On some systems: `pip install python-libsbml-experimental`.\n\n**Problem:** Codon optimization produces sequence with internal stop codons\n**Solution:** Verify protein sequence uses standard single-letter amino acid codes. Check for ambiguous residues (B, X, Z).\n\n**Problem:** Bifurcation analysis misses steady states\n**Solution:** Use more initial conditions for `fsolve`. Add parameter continuation methods for systematic sweeps.\n\n## Resources\n\n- [python-libsbml Documentation](https:\u002F\u002Fsbml.org\u002Fsoftware\u002Flibsbml\u002F)\n- [Repressilator Paper (Elowitz & Leibler, 2000)](https:\u002F\u002Fdoi.org\u002F10.1038\u002F35002125)\n- [Toggle Switch Paper (Gardner et al., 2000)](https:\u002F\u002Fdoi.org\u002F10.1038\u002F35002131)\n- [iGEM Parts Registry](http:\u002F\u002Fparts.igem.org\u002F)\n- [Codon Usage Database](https:\u002F\u002Fwww.kazusa.or.jp\u002Fcodon\u002F)\n","# Synthetic Biology: Design & Simulation\n\n## Overview\n\nSynthetic Biology provides computational tools for designing and simulating engineered biological systems. This skill covers codon optimization with species-specific usage tables, gene circuit ODE modeling (repressilator, toggle switch, inducible promoters) with growth dilution coupling, SBML model creation and validation using python-libsbml, bifurcation analysis for bistable circuits, barcode sequencing fitness analysis, and genome engineering with expression cassette insertion. All simulations produce quantitative outputs suitable for guiding experimental design.\n\n## When to Use This Skill\n\n- Optimizing gene sequences for heterologous expression (codon adaptation)\n- Simulating gene circuit dynamics (toggle switches, repressilators, inducible systems)\n- Creating standardized SBML models of biological networks\n- Analyzing bistability and bifurcation behavior in synthetic circuits\n- Processing barcode sequencing data for fitness landscape analysis\n- Designing expression cassettes and generating annotated plasmid maps\n- Sensitivity analysis of circuit parameters for robust design\n\n**Related Skills:** For constraint-based metabolic modeling use `cobrapy`. For sequence manipulation and file parsing use `biopython`. For molecular cloning simulation use `molecular-cloning`.\n\n## Installation\n\n```bash\nuv pip install python-libsbml scipy biopython numpy pandas matplotlib\n```\n\n## Quick Start\n\n```python\nimport numpy as np\nfrom scipy.integrate import solve_ivp\n\n# Toggle switch: two mutually repressing genes\ndef toggle_switch(t, y, alpha1, alpha2, beta, n, gamma):\n    u, v = y  # Protein concentrations\n    du = alpha1 \u002F (1 + v**n) - (beta + gamma) * u  # gamma = growth dilution\n    dv = alpha2 \u002F (1 + u**n) - (beta + gamma) * v\n    return [du, dv]\n\nsol = solve_ivp(toggle_switch, [0, 50], [0.1, 3.0],\n                args=(5.0, 5.0, 0.5, 2.0, 0.1),\n                t_eval=np.linspace(0, 50, 500))\n\nprint(f\"Final state: u={sol.y[0,-1]:.3f}, v={sol.y[1,-1]:.3f}\")\nprint(f\"Bistable: {'Yes' if abs(sol.y[0,-1] - sol.y[1,-1]) > 0.5 else 'No'}\")\n```\n\n## Core Capabilities\n\n### 1. Codon Optimization\n\nOptimize gene sequences for expression in target organisms.\n\n```python\nimport numpy as np\nfrom collections import Counter\n\n# E. coli codon usage table (fraction per amino acid)\nECOLI_CODON_TABLE = {\n    'F': {'TTT': 0.58, 'TTC': 0.42},\n    'L': {'TTA': 0.11, 'TTG': 0.11, 'CTT': 0.10, 'CTC': 0.10, 'CTA': 0.04, 'CTG': 0.54},\n    'I': {'ATT': 0.49, 'ATC': 0.39, 'ATA': 0.07},\n    'M': {'ATG': 1.0},\n    'V': {'GTT': 0.28, 'GTC': 0.20, 'GTA': 0.17, 'GTG': 0.35},\n    'S': {'TCT': 0.17, 'TCC': 0.15, 'TCA': 0.14, 'TCG': 0.14, 'AGT': 0.16, 'AGC': 0.25},\n    'P': {'CCT': 0.18, 'CCC': 0.13, 'CCA': 0.20, 'CCG': 0.49},\n    'T': {'ACT': 0.19, 'ACC': 0.40, 'ACA': 0.17, 'ACG': 0.25},\n    'A': {'GCT': 0.18, 'GCC': 0.26, 'GCA': 0.23, 'GCG': 0.33},\n    'Y': {'TAT': 0.59, 'TAC': 0.41},\n    '*': {'TAA': 0.61, 'TAG': 0.09, 'TGA': 0.30},\n    'H': {'CAT': 0.57, 'CAC': 0.43},\n    'Q': {'CAA': 0.34, 'CAG': 0.66},\n    'N': {'AAT': 0.49, 'AAC': 0.51},\n    'K': {'AAA': 0.74, 'AAG': 0.26},\n    'D': {'GAT': 0.63, 'GAC': 0.37},\n    'E': {'GAA': 0.68, 'GAG': 0.32},\n    'C': {'TGT': 0.46, 'TGC': 0.54},\n    'W': {'TGG': 1.0},\n    'R': {'CGT': 0.36, 'CGC': 0.36, 'CGA': 0.07, 'CGG': 0.11, 'AGA': 0.07, 'AGG': 0.04},\n    'G': {'GGT': 0.35, 'GGC': 0.37, 'GGA': 0.13, 'GGG': 0.15},\n}\n\nCODON_TO_AA = {}\nfor aa, codons in ECOLI_CODON_TABLE.items():\n    for codon in codons:\n        CODON_TO_AA[codon] = aa\n\ndef calculate_cai(dna_seq, codon_table=ECOLI_CODON_TABLE):\n    \"\"\"Calculate Codon Adaptation Index.\"\"\"\n    codons = [dna_seq[i:i+3] for i in range(0, len(dna_seq)-2, 3)]\n    weights = []\n\n    for codon in codons:\n        aa = CODON_TO_AA.get(codon)\n        if aa and aa != '*':\n            aa_codons = codon_table[aa]\n            max_freq = max(aa_codons.values())\n            w = aa_codons.get(codon, 0) \u002F max_freq if max_freq > 0 else 0\n            if w > 0:\n                weights.append(np.log(w))\n\n    cai = np.exp(np.mean(weights)) if weights else 0\n    return cai\n\ndef optimize_codons(protein_seq, codon_table=ECOLI_CODON_TABLE,\n                    gc_min=0.40, gc_max=0.60):\n    \"\"\"Optimize codons for target organism.\"\"\"\n    optimized = []\n\n    for aa in protein_seq:\n        if aa == '*':\n            break\n        if aa not in codon_table:\n            raise ValueError(f\"Unknown amino acid: {aa}\")\n\n        codons = codon_table[aa]\n        # Select highest-frequency codon\n        best_codon = max(codons, key=codons.get)\n        optimized.append(best_codon)\n\n    dna_seq = ''.join(optimized)\n\n    # Check GC content\n    gc = (dna_seq.count('G') + dna_seq.count('C')) \u002F len(dna_seq)\n    cai = calculate_cai(dna_seq, codon_table)\n\n    print(f\"Optimized sequence: {len(dna_seq)} bp\")\n    print(f\"GC content: {gc:.1%}\")\n    print(f\"CAI: {cai:.4f}\")\n\n    if gc \u003C gc_min or gc > gc_max:\n        print(f\"WARNING: GC content {gc:.1%} outside target range [{gc_min:.0%}-{gc_max:.0%}]\")\n\n    return dna_seq, cai, gc\n\n# Example\nprotein = \"MSKGEELFTGVVPILVELDGDVNGHKFSVSGEGEGDATYGKL\"  # GFP fragment\nopt_dna, cai, gc = optimize_codons(protein)\n```\n\n### 2. Gene Circuit Simulation\n\nODE models for common synthetic gene circuits.\n\n```python\nimport numpy as np\nfrom scipy.integrate import solve_ivp\n\ndef repressilator(t, y, alpha, n, beta, gamma):\n    \"\"\"Repressilator: 3-gene oscillator (Elowitz & Leibler).\n    gamma = growth dilution rate.\"\"\"\n    m1, p1, m2, p2, m3, p3 = y\n\n    dm1 = alpha \u002F (1 + p3**n) - (beta + gamma) * m1\n    dp1 = m1 - (beta + gamma) * p1\n    dm2 = alpha \u002F (1 + p1**n) - (beta + gamma) * m2\n    dp2 = m2 - (beta + gamma) * p2\n    dm3 = alpha \u002F (1 + p2**n) - (beta + gamma) * m3\n    dp3 = m3 - (beta + gamma) * p3\n\n    return [dm1, dp1, dm2, dp2, dm3, dp3]\n\ndef inducible_promoter(t, y, V_max, Km, n, beta, gamma, inducer_conc):\n    \"\"\"Inducible gene expression (Hill function).\"\"\"\n    mRNA, protein = y\n    induction = V_max * inducer_conc**n \u002F (Km**n + inducer_conc**n)\n    dmRNA = induction - (beta + gamma) * mRNA\n    dprotein = mRNA - (beta + gamma) * protein\n    return [dmRNA, dprotein]\n\n# Simulate repressilator\ny0 = [0.5, 1.0, 0.0, 0.0, 0.0, 0.0]\nsol = solve_ivp(repressilator, [0, 200], y0,\n                args=(5.0, 2.0, 0.5, 0.1),\n                t_eval=np.linspace(0, 200, 2000),\n                method='RK45')\n\n# Check for oscillation\nfrom scipy.signal import find_peaks\npeaks, _ = find_peaks(sol.y[1])\nif len(peaks) > 2:\n    period = np.mean(np.diff(sol.t[peaks]))\n    print(f\"Oscillation period: {period:.1f} time units\")\n    print(f\"Amplitude: {sol.y[1, peaks].mean() - sol.y[1].min():.3f}\")\nelse:\n    print(\"No sustained oscillations detected\")\n\n# Parameter sensitivity analysis\ndef sensitivity_analysis(param_name, param_values, base_params, y0, t_span):\n    \"\"\"Sweep one parameter and measure output.\"\"\"\n    results = []\n    for val in param_values:\n        params = base_params.copy()\n        params[param_name] = val\n        sol = solve_ivp(repressilator, t_span, y0,\n                        args=tuple(params.values()),\n                        t_eval=np.linspace(*t_span, 500))\n        # Measure amplitude\n        amplitude = sol.y[1].max() - sol.y[1].min()\n        results.append({'param_value': val, 'amplitude': amplitude})\n    return pd.DataFrame(results)\n```\n\n### 3. SBML Model Creation\n\nBuild standardized SBML models with python-libsbml.\n\n```python\nimport libsbml\n\ndef create_sbml_model(model_name, compartments, species_list, reactions):\n    \"\"\"Create SBML Level 3 model.\n\n    Args:\n        model_name: string name\n        compartments: list of (id, size) tuples\n        species_list: list of (id, compartment, initial_amount) tuples\n        reactions: list of dicts with 'id', 'reactants', 'products', 'kinetic_law'\n    \"\"\"\n    doc = libsbml.SBMLDocument(3, 2)\n    model = doc.createModel()\n    model.setId(model_name)\n\n    # Compartments\n    for comp_id, size in compartments:\n        c = model.createCompartment()\n        c.setId(comp_id)\n        c.setConstant(True)\n        c.setSize(size)\n        c.setSpatialDimensions(3)\n\n    # Species\n    for sp_id, comp_id, init_amount in species_list:\n        s = model.createSpecies()\n        s.setId(sp_id)\n        s.setCompartment(comp_id)\n        s.setInitialAmount(init_amount)\n        s.setConstant(False)\n        s.setBoundaryCondition(False)\n        s.setHasOnlySubstanceUnits(False)\n\n    # Reactions\n    for rxn in reactions:\n        r = model.createReaction()\n        r.setId(rxn['id'])\n        r.setReversible(rxn.get('reversible', False))\n\n        for reactant_id, stoich in rxn.get('reactants', []):\n            sr = r.createReactant()\n            sr.setSpecies(reactant_id)\n            sr.setStoichiometry(stoich)\n            sr.setConstant(True)\n\n        for product_id, stoich in rxn.get('products', []):\n            sp = r.createProduct()\n            sp.setSpecies(product_id)\n            sp.setStoichiometry(stoich)\n            sp.setConstant(True)\n\n        kl = r.createKineticLaw()\n        kl.setMath(libsbml.parseL3Formula(rxn['kinetic_law']))\n\n        # Add parameters\n        for param_id, value in rxn.get('parameters', []):\n            p = kl.createLocalParameter()\n            p.setId(param_id)\n            p.setValue(value)\n\n    # Validate\n    errors = doc.getNumErrors()\n    if errors > 0:\n        for i in range(errors):\n            print(f\"SBML Error: {doc.getError(i).getMessage()}\")\n\n    return doc\n\n# Example: simple enzymatic reaction\ndoc = create_sbml_model(\n    'enzyme_kinetics',\n    compartments=[('cell', 1.0)],\n    species_list=[('S', 'cell', 10.0), ('P', 'cell', 0.0), ('E', 'cell', 1.0)],\n    reactions=[{\n        'id': 'v1',\n        'reactants': [('S', 1)],\n        'products': [('P', 1)],\n        'kinetic_law': 'Vmax * S \u002F (Km + S)',\n        'parameters': [('Vmax', 1.0), ('Km', 0.5)]\n    }]\n)\n\n# Write to file\nlibsbml.writeSBMLToFile(doc, 'model.xml')\nprint(\"SBML model written to model.xml\")\n```\n\n### 4. Bifurcation Analysis\n\nIdentify bistability in gene circuits.\n\n```python\nimport numpy as np\nfrom scipy.optimize import fsolve\n\ndef toggle_steady_states(alpha1, alpha2, n, beta):\n    \"\"\"Find steady states of toggle switch by sweeping inducer.\"\"\"\n    def steady_state_eq(x, alpha1_eff, alpha2, n, beta):\n        u, v = x\n        eq1 = alpha1_eff \u002F (1 + v**n) - beta * u\n        eq2 = alpha2 \u002F (1 + u**n) - beta * v\n        return [eq1, eq2]\n\n    inducer_values = np.linspace(0, 10, 200)\n    stable_u = []\n    stable_v = []\n\n    for ind in inducer_values:\n        alpha1_eff = alpha1 * (1 + ind)  # Inducer enhances gene 1 expression\n        solutions = []\n\n        # Try multiple initial conditions to find all steady states\n        for u0 in [0.01, 1.0, 5.0, 10.0]:\n            for v0 in [0.01, 1.0, 5.0, 10.0]:\n                try:\n                    sol = fsolve(steady_state_eq, [u0, v0],\n                                args=(alpha1_eff, alpha2, n, beta),\n                                full_output=True)\n                    if sol[2] == 1:  # Converged\n                        u, v = sol[0]\n                        if u > 0 and v > 0:\n                            solutions.append((round(u, 4), round(v, 4)))\n                except Exception:\n                    pass\n\n        # Deduplicate\n        unique = list(set(solutions))\n        for u, v in unique:\n            stable_u.append({'inducer': ind, 'u': u, 'branch': 'high' if u > v else 'low'})\n\n    import pandas as pd\n    df = pd.DataFrame(stable_u)\n    n_branches = df.groupby('inducer')['branch'].nunique()\n    bistable_range = n_branches[n_branches > 1]\n\n    if len(bistable_range) > 0:\n        print(f\"Bistable region: inducer = [{bistable_range.index.min():.2f}, \"\n              f\"{bistable_range.index.max():.2f}]\")\n    else:\n        print(\"No bistability detected\")\n\n    return df\n\nresults = toggle_steady_states(alpha1=3.0, alpha2=3.0, n=2.5, beta=1.0)\n```\n\n### 5. Barcode Sequencing Analysis\n\nAnalyze fitness from barcode tracking experiments.\n\n```python\nimport pandas as pd\nimport numpy as np\nfrom scipy.cluster.hierarchy import linkage, fcluster\n\ndef analyze_barcode_fitness(count_table, reference_timepoint='T0', min_reads=10):\n    \"\"\"Calculate fitness from barcode count data.\n\n    Args:\n        count_table: DataFrame with barcodes as index, timepoints as columns\n        reference_timepoint: column name for initial counts\n    \"\"\"\n    # Filter low-abundance barcodes\n    mask = count_table[reference_timepoint] >= min_reads\n    filtered = count_table[mask].copy()\n    print(f\"Barcodes passing filter: {len(filtered)} \u002F {len(count_table)}\")\n\n    # Normalize to relative frequency\n    normalized = filtered.div(filtered.sum(axis=0), axis=1)\n\n    # Calculate log2 fold change vs reference\n    fitness = np.log2(normalized.div(normalized[reference_timepoint], axis=0) + 1e-10)\n    fitness = fitness.drop(columns=[reference_timepoint])\n\n    # Summary statistics\n    for col in fitness.columns:\n        positive = (fitness[col] > 0).sum()\n        negative = (fitness[col] \u003C 0).sum()\n        print(f\"{col}: {positive} positive, {negative} negative fitness barcodes\")\n\n    return fitness\n\ndef cluster_lineage_fitness(fitness_df, n_clusters=5):\n    \"\"\"Hierarchical clustering of barcode fitness profiles.\"\"\"\n    Z = linkage(fitness_df.values, method='ward')\n    clusters = fcluster(Z, n_clusters, criterion='maxclust')\n    fitness_df['cluster'] = clusters\n\n    # Cluster summary\n    for c in range(1, n_clusters+1):\n        cluster_data = fitness_df[fitness_df['cluster'] == c].drop(columns=['cluster'])\n        print(f\"Cluster {c} ({len(cluster_data)} barcodes): \"\n              f\"mean fitness = {cluster_data.values.mean():.3f}\")\n\n    return fitness_df\n```\n\n### 6. Genome Engineering\n\nDesign and annotate expression cassettes.\n\n```python\nfrom Bio.Seq import Seq\nfrom Bio.SeqRecord import SeqRecord\nfrom Bio.SeqFeature import SeqFeature, FeatureLocation\nfrom Bio import SeqIO\n\ndef insert_expression_cassette(genome_record, insert_seq, locus_position,\n                                promoter_name='Ptac', gene_name='gfp',\n                                terminator_name='T7_term'):\n    \"\"\"Insert expression cassette at specified genomic locus.\"\"\"\n    # Build cassette\n    cassette_features = []\n    pos = 0\n\n    # Promoter (assume 100bp)\n    promoter_seq = 'A' * 100  # Placeholder — use actual sequence\n    cassette_features.append(SeqFeature(\n        FeatureLocation(pos, pos + len(promoter_seq)),\n        type='promoter', qualifiers={'label': promoter_name}\n    ))\n    pos += len(promoter_seq)\n\n    # RBS (20bp)\n    rbs_seq = 'AAGGAGATATACAT'  # Consensus RBS\n    cassette_features.append(SeqFeature(\n        FeatureLocation(pos, pos + len(rbs_seq)),\n        type='RBS', qualifiers={'label': 'RBS'}\n    ))\n    pos += len(rbs_seq)\n\n    # CDS\n    cassette_features.append(SeqFeature(\n        FeatureLocation(pos, pos + len(insert_seq)),\n        type='CDS', qualifiers={'label': gene_name, 'translation': str(Seq(insert_seq).translate())}\n    ))\n    pos += len(insert_seq)\n\n    # Terminator (50bp)\n    term_seq = 'T' * 50\n    cassette_features.append(SeqFeature(\n        FeatureLocation(pos, pos + len(term_seq)),\n        type='terminator', qualifiers={'label': terminator_name}\n    ))\n\n    full_cassette = promoter_seq + rbs_seq + insert_seq + term_seq\n\n    # Insert into genome\n    new_seq = str(genome_record.seq[:locus_position]) + full_cassette + \\\n              str(genome_record.seq[locus_position:])\n\n    # Adjust feature positions\n    offset = len(full_cassette)\n    new_features = []\n    for f in genome_record.features:\n        if f.location.start >= locus_position:\n            new_loc = FeatureLocation(f.location.start + offset,\n                                       f.location.end + offset, f.location.strand)\n            new_features.append(SeqFeature(new_loc, type=f.type, qualifiers=f.qualifiers))\n        else:\n            new_features.append(f)\n\n    # Add cassette features\n    for f in cassette_features:\n        adjusted = SeqFeature(\n            FeatureLocation(f.location.start + locus_position,\n                           f.location.end + locus_position),\n            type=f.type, qualifiers=f.qualifiers\n        )\n        new_features.append(adjusted)\n\n    new_record = SeqRecord(Seq(new_seq), id=genome_record.id,\n                           name=genome_record.name,\n                           description=f\"{genome_record.description} + {gene_name} cassette\",\n                           features=new_features)\n    return new_record\n```\n\n## Typical Workflows\n\n### Workflow 1: Optimize Gene for E. coli Expression and Calculate CAI\n\n```python\nprotein_seq = \"MVSKGEELFTGVVPILVELDGDVNGHKFSVSGEGEGDATYGKLTLKFICTTGKLPVPWPTLVTTLTYGVQCFSRYPDHMKQHDFFKSAMPEGYVQERTIFFKDDGNYKTRAEVKFEGDTLVNRIELKGIDFKEDGNILGHKLEYNYNSHNVYIMADKQKNGIKVNFKIRHNIEDGSVQLADHYQQNTPIGDGPVLLPDNHYLSTQSALSKDPNEKRDHMVLLEFVTAAGITLGMDELYK\"\nopt_dna, cai, gc = optimize_codons(protein_seq)\nprint(f\"Original CAI: {calculate_cai(opt_dna):.4f}\")\n```\n\n### Workflow 2: Simulate Toggle Switch with Growth Dilution\n\n```python\nimport numpy as np\nfrom scipy.integrate import solve_ivp\n\nsol = solve_ivp(toggle_switch, [0, 100], [0.1, 3.0],\n                args=(5.0, 5.0, 0.5, 2.0, 0.1),\n                t_eval=np.linspace(0, 100, 1000))\nprint(f\"Final: u={sol.y[0,-1]:.3f}, v={sol.y[1,-1]:.3f}\")\nprint(f\"State: {'Gene 1 ON' if sol.y[0,-1] > sol.y[1,-1] else 'Gene 2 ON'}\")\n```\n\n### Workflow 3: Create SBML Model of a Metabolic Pathway\n\n```python\ndoc = create_sbml_model(\n    'glycolysis_simplified',\n    compartments=[('cytoplasm', 1.0)],\n    species_list=[\n        ('glucose', 'cytoplasm', 5.0),\n        ('G6P', 'cytoplasm', 0.0),\n        ('pyruvate', 'cytoplasm', 0.0),\n        ('ATP', 'cytoplasm', 2.0),\n    ],\n    reactions=[\n        {'id': 'hexokinase', 'reactants': [('glucose', 1), ('ATP', 1)],\n         'products': [('G6P', 1)], 'kinetic_law': 'Vmax * glucose * ATP \u002F ((Km_g + glucose) * (Km_a + ATP))',\n         'parameters': [('Vmax', 1.0), ('Km_g', 0.1), ('Km_a', 0.5)]},\n        {'id': 'glycolysis', 'reactants': [('G6P', 1)],\n         'products': [('pyruvate', 2), ('ATP', 2)], 'kinetic_law': 'k * G6P',\n         'parameters': [('k', 0.5)]},\n    ]\n)\nlibsbml.writeSBMLToFile(doc, 'glycolysis.xml')\n```\n\n## Best Practices\n\n1. **Codon optimization** — always check GC content after optimization; extreme GC can cause expression problems\n2. **Circuit simulation** — include growth dilution term (gamma * x) in all ODE models; cells divide, diluting intracellular molecules\n3. **SBML validation** — always call `doc.getNumErrors()` after model creation; common errors are missing units and unbalanced reactions\n4. **Bifurcation analysis** — use multiple initial conditions to find all steady states; bistable systems have hysteresis\n5. **Barcode fitness** — require minimum read count (>10) to filter PCR\u002Fsequencing noise; use log2 fold change for fitness\n6. **Stiffness** — gene circuits with fast mRNA and slow protein dynamics are stiff; use `method='BDF'` in `solve_ivp`\n\n## Troubleshooting\n\n**Problem:** ODE solver fails with \"excess work\"\n**Solution:** Increase `max_step` or switch to stiff solver (`BDF`, `Radau`). Check parameter values for unreasonably large rates.\n\n**Problem:** python-libsbml not found after installation\n**Solution:** Use `pip install python-libsbml` (not `libsbml`). On some systems: `pip install python-libsbml-experimental`.\n\n**Problem:** Codon optimization produces sequence with internal stop codons\n**Solution:** Verify protein sequence uses standard single-letter amino acid codes. Check for ambiguous residues (B, X, Z).\n\n**Problem:** Bifurcation analysis misses steady states\n**Solution:** Use more initial conditions for `fsolve`. Add parameter continuation methods for systematic sweeps.\n\n## Resources\n\n- [python-libsbml Documentation](https:\u002F\u002Fsbml.org\u002Fsoftware\u002Flibsbml\u002F)\n- [Repressilator Paper (Elowitz & Leibler, 2000)](https:\u002F\u002Fdoi.org\u002F10.1038\u002F35002125)\n- [Toggle Switch Paper (Gardner et al., 2000)](https:\u002F\u002Fdoi.org\u002F10.1038\u002F35002131)\n- [iGEM Parts Registry](http:\u002F\u002Fparts.igem.org\u002F)\n- [Codon Usage Database](https:\u002F\u002Fwww.kazusa.or.jp\u002Fcodon\u002F)\n",{"name":5,"license":50,"category":25,"metadata":51,"description":7},"MIT license",{"skill-author":52},"InkVell Inc.","main","4aa39efd1cdab0b4657ecee16c92a92011a5b10f","openscience\u002Fbackend\u002Fcli\u002Fskills\u002Fbiology\u002Fsynthetic-biology","https:\u002F\u002Fgithub.com\u002Ffadrienne\u002FMyGitHub","https:\u002F\u002Fgithub.com\u002Ffadrienne","2026-10-28 00:43:09",{"source":8,"skillName":5,"commands":60,"prompt":70,"zipAvailable":71},[61,64,67],{"tool":62,"command":63},"npx","npx skills add fadrienne\u002FMyGitHub --skill synthetic-biology",{"tool":65,"command":66},"bunx","bunx skills add fadrienne\u002FMyGitHub --skill synthetic-biology",{"tool":68,"command":69},"pnpm","pnpm dlx skills add fadrienne\u002FMyGitHub --skill synthetic-biology","安装技能，技能地址：https:\u002F\u002Fgithub.com\u002Ffadrienne\u002FMyGitHub\u002Fblob\u002Fmain\u002Fopenscience\u002Fbackend\u002Fcli\u002Fskills\u002Fbiology\u002Fsynthetic-biology\u002FSKILL.md",true,[73,79,83,87],{"path":74,"resourceType":75,"resourceTypeDesc":76,"sizeBytes":77,"sourceHtmlUrl":78},"scripts\u002Fbifurcation.py","SCRIPT","脚本",20870,"https:\u002F\u002Fgithub.com\u002Ffadrienne\u002FMyGitHub\u002Fblob\u002Fmain\u002Fopenscience\u002Fbackend\u002Fcli\u002Fskills\u002Fbiology\u002Fsynthetic-biology\u002Fscripts\u002Fbifurcation.py",{"path":80,"resourceType":75,"resourceTypeDesc":76,"sizeBytes":81,"sourceHtmlUrl":82},"scripts\u002Fcodon_optimize.py",22377,"https:\u002F\u002Fgithub.com\u002Ffadrienne\u002FMyGitHub\u002Fblob\u002Fmain\u002Fopenscience\u002Fbackend\u002Fcli\u002Fskills\u002Fbiology\u002Fsynthetic-biology\u002Fscripts\u002Fcodon_optimize.py",{"path":84,"resourceType":75,"resourceTypeDesc":76,"sizeBytes":85,"sourceHtmlUrl":86},"scripts\u002Fgene_circuit.py",17358,"https:\u002F\u002Fgithub.com\u002Ffadrienne\u002FMyGitHub\u002Fblob\u002Fmain\u002Fopenscience\u002Fbackend\u002Fcli\u002Fskills\u002Fbiology\u002Fsynthetic-biology\u002Fscripts\u002Fgene_circuit.py",{"path":88,"resourceType":75,"resourceTypeDesc":76,"sizeBytes":89,"sourceHtmlUrl":90},"scripts\u002Fsbml_model.py",17373,"https:\u002F\u002Fgithub.com\u002Ffadrienne\u002FMyGitHub\u002Fblob\u002Fmain\u002Fopenscience\u002Fbackend\u002Fcli\u002Fskills\u002Fbiology\u002Fsynthetic-biology\u002Fscripts\u002Fsbml_model.py",[92,119,146,180,207,234],{"skillNo":93,"name":94,"nameZh":6,"description":95,"descriptionZh":6,"repositoryFullName":8,"ownerLogin":9,"ownerAvatarUrl":10,"ownerAccountNo":11,"ownerDisplayName":12,"repositoryNo":13,"starsCount":14,"licenseSpdxId":15,"licenseFileUrl":6,"sourceHtmlUrl":96,"categories":97,"keywords":101,"publishedAt":45},"01M7167B28PK20HP7R7ZED2DY0","statistical-power","Sample size calculation, power analysis, and effect size conversion for scientific studies. Use BEFORE data collection (a priori) to determine required N, or after (post-hoc) to compute achieved power. Covers parametric tests (t-test, ANOVA, chi-square, proportions, correlation, regression), simulation-based power for complex\u002Fclustered\u002Fnested designs, and power curves. Use this skill when someone asks 'how many samples do I need', 'what is my power', 'what effect size can I detect', or any variant. Pairs with \u002Fexperimental-design (choose design first, then compute power) and \u002Fstatistical-analysis (analyze data after collection).","https:\u002F\u002Fgithub.com\u002Ffadrienne\u002FMyGitHub\u002Fblob\u002Fmain\u002Fscientific-agent-skills\u002Fskills\u002Fstatistical-power\u002FSKILL.md",[98],{"categoryNo":99,"categoryName":100,"taxonomyType":21,"taxonomyTypeDesc":22},"01JBSEEDCAT000000000000023","Skill与智能体开发",[102,103,104,105,106,107,36,108,109,110,111,41,112,113,114,115,116,117,40,118],"power","statistical power","effect","scipy","regression","choose","uv","when","Bash","collection","calculation","ANOVA","conversion","analyze","t-test","chi-square","sample",{"skillNo":120,"name":121,"nameZh":6,"description":122,"descriptionZh":6,"repositoryFullName":8,"ownerLogin":9,"ownerAvatarUrl":10,"ownerAccountNo":11,"ownerDisplayName":12,"repositoryNo":13,"starsCount":14,"licenseSpdxId":15,"licenseFileUrl":6,"sourceHtmlUrl":123,"categories":124,"keywords":128,"publishedAt":45},"01M71677EBCM8EPCE9BZCK8505","statistical-analysis","Guided statistical analysis with test selection and reporting. Use when you need help choosing appropriate tests for your data, assumption checking, power analysis, and APA-formatted results. Best for academic research reporting, test selection guidance. For implementing specific models programmatically use statsmodels.","https:\u002F\u002Fgithub.com\u002Ffadrienne\u002FMyGitHub\u002Fblob\u002Fmain\u002Fscientific-agent-skills\u002Fskills\u002Fstatistical-analysis\u002FSKILL.md",[125],{"categoryNo":126,"categoryName":127,"taxonomyType":21,"taxonomyTypeDesc":22},"01JBSEEDCAT000000000000008","测试与质量",[41,129,102,130,131,132,109,133,134,135,136,137,138,139,140,141,142,143,144,145],"statistical analysis","academic research","implementing","selection","you","reporting","data","for","tests","use","with","test","research","results","statsmodels","models","help",{"skillNo":147,"name":148,"nameZh":6,"description":149,"descriptionZh":6,"repositoryFullName":8,"ownerLogin":9,"ownerAvatarUrl":10,"ownerAccountNo":11,"ownerDisplayName":12,"repositoryNo":13,"starsCount":14,"licenseSpdxId":15,"licenseFileUrl":6,"sourceHtmlUrl":150,"categories":151,"keywords":161,"publishedAt":45},"01M71673R93XAHFH81DBNVNG7H","scientific-writing","Core skill for the deep research and writing tool. Write scientific manuscripts in full paragraphs (never bullet points). Use two-stage process with (1) section outlines with key points using research-lookup then (2) convert to flowing prose. IMRAD structure, citations (APA\u002FAMA\u002FVancouver), figures\u002Ftables, reporting guidelines (CONSORT\u002FSTROBE\u002FPRISMA), for research papers and journal submissions.","https:\u002F\u002Fgithub.com\u002Ffadrienne\u002FMyGitHub\u002Fblob\u002Fmain\u002Fscientific-agent-skills\u002Fskills\u002Fscientific-writing\u002FSKILL.md",[152,155,156],{"categoryNo":153,"categoryName":154,"taxonomyType":21,"taxonomyTypeDesc":22},"01JBSEEDCAT000000000000018","写作与文案",{"categoryNo":99,"categoryName":100,"taxonomyType":21,"taxonomyTypeDesc":22},{"categoryNo":157,"categoryName":158,"taxonomyType":159,"taxonomyTypeDesc":160},"01JBSEEDCAT000000000000036","内容创作者","PROFESSION","适用职业",[162,163,164,165,166,167,168,169,170,171,110,172,173,174,175,176,177,178,134,179],"writing","scientific","scientific writing","Citations","deep","deep research","never","papers","journal","false","api","prisma","structure","openrouter","Outlines","core skill","read","features",{"skillNo":181,"name":182,"nameZh":6,"description":183,"descriptionZh":6,"repositoryFullName":8,"ownerLogin":9,"ownerAvatarUrl":10,"ownerAccountNo":11,"ownerDisplayName":12,"repositoryNo":13,"starsCount":14,"licenseSpdxId":15,"licenseFileUrl":6,"sourceHtmlUrl":184,"categories":185,"keywords":190,"publishedAt":45},"01M7166ZPKXBF4EBPHVTJPQBB1","scientific-visualization","Meta-skill for publication-ready figures. Use when creating journal submission figures requiring multi-panel layouts, significance annotations, error bars, colorblind-safe palettes, and specific journal formatting (Nature, Science, Cell). Orchestrates matplotlib\u002Fseaborn\u002Fplotly with publication styles. For quick exploration use seaborn or plotly directly.","https:\u002F\u002Fgithub.com\u002Ffadrienne\u002FMyGitHub\u002Fblob\u002Fmain\u002Fscientific-agent-skills\u002Fskills\u002Fscientific-visualization\u002FSKILL.md",[186,189],{"categoryNo":187,"categoryName":188,"taxonomyType":21,"taxonomyTypeDesc":22},"01JBSEEDCAT000000000000013","分析与可视化",{"categoryNo":99,"categoryName":100,"taxonomyType":21,"taxonomyTypeDesc":22},[191,163,192,193,194,195,196,197,198,170,109,199,200,201,202,203,204,205,136,206],"visualization","scientific visualization","error","ready","quick","exploration","meta-skill","Meta","safe","plotly","annotations","formatting","Publication","figures","panel","submission",{"skillNo":208,"name":209,"nameZh":6,"description":210,"descriptionZh":6,"repositoryFullName":8,"ownerLogin":9,"ownerAvatarUrl":10,"ownerAccountNo":11,"ownerDisplayName":12,"repositoryNo":13,"starsCount":14,"licenseSpdxId":15,"licenseFileUrl":6,"sourceHtmlUrl":211,"categories":212,"keywords":219,"publishedAt":45},"01M7166VXJWQSSC3RQZP60WBGR","research-code","Debug, profile, review, and restructure Python research and analysis code. Use when analysis scripts crash, produce wrong results, run too slowly, or need a correctness review. Covers: reading tracebacks and diagnosing root causes, hypothesis-driven debugging, reviewing code for common statistical\u002Fnumerical errors, profiling data pipelines, improving reproducibility (seeds, environments, determinism), and structuring analysis scripts for sharing. Distinct from \u002Fexploratory-data-analysis (which understands data) and \u002Fstatistical-analysis (which chooses and runs tests) — this skill focuses on the code itself.","https:\u002F\u002Fgithub.com\u002Ffadrienne\u002FMyGitHub\u002Fblob\u002Fmain\u002Fscientific-agent-skills\u002Fskills\u002Fresearch-code\u002FSKILL.md",[213,216],{"categoryNo":214,"categoryName":215,"taxonomyType":21,"taxonomyTypeDesc":22},"01JBSEEDCAT000000000000021","资料检索与研究",{"categoryNo":217,"categoryName":218,"taxonomyType":159,"taxonomyTypeDesc":160},"01JBSEEDCAT000000000000030","开发工程师",[220,221,141,222,223,224,225,108,226,109,110,41,227,228,229,230,231,232,178,233],"code","research code","which","memory","data-analysis","errors","debugging","common","review","data pipelines","run","scripts","line","write",{"skillNo":235,"name":236,"nameZh":6,"description":237,"descriptionZh":6,"repositoryFullName":8,"ownerLogin":9,"ownerAvatarUrl":10,"ownerAccountNo":11,"ownerDisplayName":12,"repositoryNo":13,"starsCount":14,"licenseSpdxId":238,"licenseFileUrl":6,"sourceHtmlUrl":239,"categories":240,"keywords":247,"publishedAt":45},"01M7166CF5HSR7SVZYZFWTDX55","markdown-mermaid-writing","Comprehensive markdown and Mermaid diagram writing skill. Use when creating any scientific document, report, analysis, or visualization. Establishes text-based diagrams as the default documentation standard with full style guides (markdown + mermaid), 24 diagram type references, and 9 document templates.","Apache-2.0","https:\u002F\u002Fgithub.com\u002Ffadrienne\u002FMyGitHub\u002Fblob\u002Fmain\u002Fscientific-agent-skills\u002Fskills\u002Fmarkdown-mermaid-writing\u002FSKILL.md",[241,244,245,246],{"categoryNo":242,"categoryName":243,"taxonomyType":21,"taxonomyTypeDesc":22},"01JBSEEDCAT000000000000002","文档处理",{"categoryNo":153,"categoryName":154,"taxonomyType":21,"taxonomyTypeDesc":22},{"categoryNo":99,"categoryName":100,"taxonomyType":21,"taxonomyTypeDesc":22},{"categoryNo":157,"categoryName":158,"taxonomyType":159,"taxonomyTypeDesc":160},[162,248,249,250,251,252,191,253,254,109,110,41,255,256,257,258,259,260,163,178],"markdown mermaid writing","mermaid","markdown","community","diagrams","project","default","team","guides","text","documentation","references","diagram"]