├── .github └── workflows │ ├── python-package.yml │ ├── python-pypi-publish-on-release.yml │ └── python-testpypi-publish-on-tag.yml ├── .gitignore ├── CITATION.cff ├── LICENSE ├── README.md ├── case_studies ├── Condensation.ipynb ├── Kotani2017.ipynb ├── Many_systems.ipynb ├── Qian2011.ipynb ├── README.md ├── Reactionrates.ipynb ├── Yin2008.ipynb ├── dabby2013_rates.py ├── figure_analysis.py ├── genot2011.py ├── kotani2017.py ├── qian2011.py ├── qian2011sqrt.py ├── yin2008.py ├── zhang2007.py ├── zhang2009.py ├── zhang2009_rates.py ├── zhang2010.py └── zhang2011.py ├── peppercornenumerator ├── __init__.py ├── condense.py ├── enumerator.py ├── input.py ├── objects.py ├── output.py ├── peppercorn.py ├── pilsimulator.py ├── ratemodel.py ├── reactions.py └── utils.py ├── pyproject.toml └── tests ├── __init__.py ├── examples ├── README.md ├── literature │ ├── badelt2019_F5.pil │ ├── kotani2017_F2.pil │ ├── thachuk2015_fig5.pil │ ├── thachuk2015_fig9.pil │ ├── wang2018_DLD.pil │ ├── wang2018_SLD.pil │ └── wang2018_TLD.pil └── oldfileformats │ ├── 3-arm-junction.enum │ ├── DLD_simple_AND.pil │ ├── DLD_translator_displacement.pil │ ├── DLD_translator_leak.pil │ ├── DLD_translator_leak_reporter.pil │ ├── DLD_translator_leak_reporter_fuel1.pil │ ├── DLD_translator_leak_reporter_fuel2.pil │ ├── DLD_translator_leak_simple.pil │ ├── DLD_translator_leak_simple_reporter.pil │ ├── SLC_standard_input.enum │ ├── SLD_translator_leak.pil │ ├── SLD_translator_simpler_leak.pil │ ├── TMSD_domain_helix.pil │ ├── bounded-dendrimer.enum │ ├── catalytic-circuit.enum │ ├── delayedchoice1.enum │ ├── fate-example.pil │ ├── genot2011fig3.pil │ ├── genot2011fig4b.pil │ ├── genot2013figS3.pil │ ├── grun2014fig3.pil │ ├── grun2014fig3_alt.pil │ ├── grun2014fig3_irrev.pil │ ├── multiplicities.pil │ ├── muscat2011fig1.pil │ ├── qian2011science_fig2_detailed.pil │ ├── qian_andor.pil │ ├── qian_reporter4way.pil │ ├── rarerates.pil │ ├── sadowski-tetrahedron.enum │ ├── sarma2010_biggate.in │ ├── sarma2010_fig1.in │ ├── sarma2010_fig2.in │ ├── sarma2010_fig3.in │ ├── sarma2010_fig4.in │ ├── sarma2010_gate.in │ ├── sarma2010_hybridize.in │ ├── sarma2010_hybridizelong.in │ ├── sarma2010_mediumgate.in │ ├── sarma2010_polymer.in │ ├── sarma2010_smallgate.in │ ├── sarma2010_transient.in │ ├── seelig2006_fig2c.enum │ ├── seelig2006_fig2c_error.enum │ ├── seesaw.enum │ ├── seesaw2.enum │ ├── srinivas_P_CApAq.pil │ ├── venkataraman2007.pil │ ├── xichen2012fig2.pil │ ├── zhang2007fig1.pil │ └── zhang2011fig1.pil ├── test_condense.py ├── test_enumerator.py ├── test_input.py ├── test_objects.py ├── test_output.py ├── test_ratemodel.py ├── test_reactions.py └── test_utils.py /.github/workflows/python-package.yml: -------------------------------------------------------------------------------- 1 | # This workflow will install Python dependencies, run tests and lint with a variety of Python versions 2 | # For more information see: https://docs.github.com/en/actions/automating-builds-and-tests/building-and-testing-python 3 | 4 | name: Python package 5 | 6 | on: 7 | push: 8 | branches: [ "master" ] 9 | pull_request: 10 | branches: [ "master" ] 11 | 12 | jobs: 13 | build: 14 | 15 | runs-on: ubuntu-latest 16 | strategy: 17 | fail-fast: false 18 | matrix: 19 | python-version: ["3.8", "3.9", "3.10", "3.11"] 20 | 21 | steps: 22 | - uses: actions/checkout@v3 23 | - name: Set up Python ${{ matrix.python-version }} 24 | uses: actions/setup-python@v3 25 | with: 26 | python-version: ${{ matrix.python-version }} 27 | - name: Install dependencies 28 | run: | 29 | python -m pip install --upgrade pip 30 | python -m pip install flake8 pytest pytest-cov flit 31 | python -m pip install libroadrunner 32 | python -m pip install . 33 | - name: Lint with flake8 34 | run: | 35 | # stop the build if there are Python syntax errors or undefined names 36 | flake8 . --count --select=E9,F63,F7,F82 --show-source --statistics 37 | # exit-zero treats all errors as warnings. The GitHub editor is 127 chars wide 38 | # Wow, so much to do! Looks like a round of pep8 code cleanup is overdue. 39 | # flake8 . --count --exit-zero --max-complexity=10 --max-line-length=127 --statistics 40 | - name: Test with pytest 41 | run: | 42 | pytest --cov=peppercornenumerator --cov-report xml 43 | - name: Upload coverage 44 | uses: codecov/codecov-action@v3 45 | if: ${{ success() }} 46 | -------------------------------------------------------------------------------- /.github/workflows/python-pypi-publish-on-release.yml: -------------------------------------------------------------------------------- 1 | # This workflow will upload a Python Package using Twine when a release is created 2 | # For more information see: https://docs.github.com/en/actions/automating-builds-and-tests/building-and-testing-python#publishing-to-package-registries 3 | 4 | # This workflow uses actions that are not certified by GitHub. 5 | # They are provided by a third-party and are governed by 6 | # separate terms of service, privacy policy, and support 7 | # documentation. 8 | 9 | name: Upload Python Package 10 | 11 | on: 12 | release: 13 | types: [published] 14 | 15 | permissions: 16 | contents: read 17 | 18 | jobs: 19 | deploy: 20 | 21 | runs-on: ubuntu-latest 22 | 23 | steps: 24 | - uses: actions/checkout@v3 25 | - name: Set up Python 26 | uses: actions/setup-python@v3 27 | with: 28 | python-version: '3.10' 29 | - name: Install dependencies 30 | run: | 31 | python -m pip install --upgrade pip 32 | pip install build 33 | - name: Build package 34 | run: python -m build 35 | - name: Publish package 36 | uses: pypa/gh-action-pypi-publish@27b31702a0e7fc50959f5ad993c78deac1bdfc29 37 | with: 38 | user: __token__ 39 | password: ${{ secrets.PYPI_API_TOKEN }} 40 | 41 | -------------------------------------------------------------------------------- /.github/workflows/python-testpypi-publish-on-tag.yml: -------------------------------------------------------------------------------- 1 | name: Publish tagged Python 🐍 distributions to TestPyPI 2 | 3 | on: push 4 | 5 | permissions: 6 | contents: read 7 | 8 | jobs: 9 | build-n-publish: 10 | name: Build and publish Python 🐍 distributions 📦 to TestPyPI 11 | runs-on: ubuntu-latest 12 | 13 | steps: 14 | - uses: actions/checkout@v3 15 | - name: Set up Python 16 | uses: actions/setup-python@v3 17 | with: 18 | python-version: '3.10' 19 | - name: Install dependencies 20 | run: | 21 | python -m pip install --upgrade pip 22 | pip install build 23 | - name: Build package 24 | run: python -m build 25 | - name: Publish distribution 📦 to Test PyPI 26 | if: startsWith(github.ref, 'refs/tags') 27 | uses: pypa/gh-action-pypi-publish@release/v1 28 | with: 29 | password: ${{ secrets.TEST_PYPI_API_TOKEN }} 30 | repository_url: https://test.pypi.org/legacy/ 31 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | *pyc 2 | *~ 3 | *.swp 4 | *.tex 5 | .coverage 6 | .ipynb_checkpoints/ 7 | -------------------------------------------------------------------------------- /CITATION.cff: -------------------------------------------------------------------------------- 1 | cff-version: 1.2.0 2 | message: "If you use this software, please cite it as below." 3 | preferred-citation: 4 | type: article 5 | authors: 6 | - family-names: "Badelt" 7 | given-names: "Stefan" 8 | orcid: "https://orcid.org/0000-0003-2636-5801" 9 | - family-names: "Grun" 10 | given-names: "Casey" 11 | orcid: "https://orcid.org/0000-0002-4563-6358" 12 | - family-names: "Sarma" 13 | given-names: "Karthik V." 14 | - family-names: "Wolfe" 15 | given-names: "Brian" 16 | - family-names: "Shin" 17 | given-names: "Seung Woo" 18 | - family-names: "Winfree" 19 | given-names: "Erik" 20 | orcid: "http://orcid.org/0000-0002-5899-7523" 21 | doi: "10.1098/rsif.2019.0866" 22 | journal: "Journal of the Royal Society Interface" 23 | month: June 24 | title: "A domain-level DNA strand displacement reaction enumerator allowing arbitrary non-pseudoknotted secondary structures" 25 | issue: 167 26 | volume: 17 27 | year: 2020 28 | url: "https://doi.org/10.1098/rsif.2019.0866" 29 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | The MIT License (MIT) 2 | 3 | Copyright (c) 2014-2020 Stefan Badelt, Casey Grun, Karthik Sarma, Brian Wolfe, Seung Woo Shin and Erik Winfree 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy of 6 | this software and associated documentation files (the "Software"), to deal in 7 | the Software without restriction, including without limitation the rights to 8 | use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies 9 | of the Software, and to permit persons to whom the Software is furnished to do 10 | so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # peppercornenumerator 2 | 3 | [![GitHub tag (latest by date)](https://img.shields.io/github/v/tag/dna-and-natural-algorithms-group/peppercornenumerator)](https://github.com/dna-and-natural-algorithms-group/peppercornenumerator/tags) 4 | [![GitHub release (latest by date including pre-releases)](https://img.shields.io/github/v/release/dna-and-natural-algorithms-group/peppercornenumerator?include_prereleases)](https://github.com/dna-and-natural-algorithms-group/peppercornenumerator/releases) 5 | [![PyPI version](https://badge.fury.io/py/peppercornenumerator.svg)](https://badge.fury.io/py/peppercornenumerator) 6 | [![PyPI - License](https://img.shields.io/pypi/l/peppercornenumerator)](https://opensource.org/licenses/MIT) 7 | ![build](https://github.com/DNA-and-Natural-Algorithms-Group/peppercornenumerator/actions/workflows/python-package.yml/badge.svg) 8 | [![Codecov](https://img.shields.io/codecov/c/github/dna-and-natural-algorithms-group/peppercornenumerator)](https://codecov.io/gh/dna-and-natural-algorithms-group/peppercornenumerator) 9 | 10 | 11 | This is a package for domain-level strand displacement (DSD) system analysis. 12 | After installation, you should be able to execute the scripts **peppercorn** 13 | and **pilsimulator**. 14 | 15 | The reaction enumerator Peppercorn reads a file with initially present 16 | domain-level complexes, and returns all possible reactions and products. 17 | Peppercorn supports arbitrary non-pseudoknotted structures and the following 18 | domain-level reactions: bind, open, proximal 3-way and 4-way branch migration, 19 | remote 3-way and 4-way branch migration. For more background on reaction 20 | semantics we refer to [Badelt et al. (2020)]. 21 | 22 | Given a specification of initial species concentrations, the simulation 23 | software Pilsimulator can read Peppercorn's output and simulate expected 24 | species concentrations over time. Alternatively, you can export the results 25 | into **SBML** format for analysis in your favorite simulator. 26 | Note that the reaction rates assume DNA 27 | molecules! 28 | 29 | For a quick overview of the software, you can also have a look at [this talk] 30 | held at the 26th International Conference on DNA Computing and Molecular 31 | Programming ([DNA 26]). 32 | 33 | ## Installation 34 | ```sh 35 | ~$ pip install peppercornenumerator 36 | ``` 37 | 38 | If you are installing from the git repository, use: 39 | ```bash 40 | $ pip install . 41 | ``` 42 | If you are planning to contribute to the repository, please install the 43 | development version and make sure all tests pass: 44 | ``` 45 | $ pip install .[dev] 46 | $ pytest 47 | ``` 48 | 49 | ## Quickstart using executable scripts 50 | 51 | ### General workflow 52 | After installation of **peppercornenumerator**, you must have 53 | two excutable scripts, try if they work and look at the options: 54 | ```sh 55 | $ peppercorn --help 56 | $ pilsimulator --help 57 | ``` 58 | 59 | Use the executable **peppercorn** to load the file [example.pil] and write results to example_enum.pil: 60 | 61 | ```sh 62 | # either using commandline flags 63 | $ peppercorn -o example_enum.pil example.pil 64 | # or read from STDIN and write to STDOUT: 65 | $ cat example.pil | peppercorn > example_enum.pil 66 | ``` 67 | Your can simulate the enumerated system using the **pilsimulator** executable. 68 | ```sh 69 | $ cat example_enum.pil | pilsimulator --t8 1800 --p0 S1=100 S2=100 C1=0.1 70 | ``` 71 | Note that default concentration unit changed to 'nM' in version 1.1 (previously 72 | 'M'). Check commandline options of peppercorn to change units, e.g. to 'M', as 73 | well as to provide initial concentrations directly in the input file. 74 | 75 | ### Input/Output format 76 | 77 | The following input format is recommended. The lengths of all domains are 78 | defined first, then all initial complexes are defined in terms of their 79 | sequence and secondary structure. For more details on the **kernel notation** 80 | of complexes, see Figure 1 or Section 2 of [Badelt et al. (2020)]. 81 | 82 | ``` 83 | # <- this is a comment 84 | # 85 | # Shohei Kotani and William L. Hughes (2017) 86 | # Multi-Arm Junctions for Dynamic DNA Nanotechnology 87 | # 88 | # Figure 2A: Single-layer catalytic system with three-arm junction substrates. 89 | # 90 | 91 | # 92 | # Initialize domains (and their complements) and specify their lengths: 93 | # 94 | length a = 22 # Domains a and a* with length = 22 95 | length b = 22 96 | length c = 22 97 | length t1 = 6 # name = 1 in Figure 98 | length t2 = 6 # name = 2 in Figure 99 | length t3 = 10 # name = 3 in Figure 100 | length T2 = 2 101 | 102 | length d1s = 16 103 | length d2 = 6 104 | 105 | # 106 | # Initialize all initial complexes using kernel notation, 107 | # which combines name, sequence and structure into a single line! 108 | # Always use 5' to 3' direction of sequences. 109 | # 110 | 111 | # The following complex is called C1, has a single strand with 3 unpaired domains: 112 | C1 = t1 c a 113 | 114 | # The complex S1 has multiple strands and is connected via paired domains! 115 | # Sequence of S1: d1s T2 b a t2 + t2* a* c* t1* + c b* 116 | # Structure of S1: . . ( ( ( + ) ) ( . + ) ) 117 | S1 = d1s T2 b( a( t2( + ) ) c*( t1* + ) ) 118 | 119 | S2 = t1( c( a( + t2* ) b*( d2 t3 + ) ) ) 120 | 121 | P1 = t2* a*( c*( t1*( + ) ) ) 122 | I1 = d1s T2 b( a t2 + c ) 123 | I2 = d1s T2 b( a( t2( + ) ) b*( d2 t3 + ) c*( t1* + ) ) 124 | 125 | P2 = d1s T2 b( a( t2( + ) ) ) d2 t3 126 | P3 = b( c*( t1* + ) ) 127 | 128 | R = d1s( d2( + t3* ) ) 129 | 130 | D = d1s d2 131 | RW = d1s( T2 b( a( t2( + ) ) ) d2( t3( + ) ) ) 132 | ``` 133 | 134 | Let's use reaction condensation for a more compact representation of the 135 | reaction network and increase the default maximum complex size to avoid 136 | (warnings about) incomplete enumeration. 137 | ``` 138 | $ peppercorn -o system-enum.pil --max-complex-size 10 --condensed < system.pil 139 | ``` 140 | 141 | And then the output file should look something like this. The layout may vary 142 | between different Peppercorn versions. 143 | ``` 144 | # File generated by peppercorn-v0.9 145 | 146 | # Domains (17) 147 | length a = 22 148 | length b = 22 149 | length c = 22 150 | length d1s = 16 151 | length d2 = 6 152 | length t1 = 6 153 | length T2 = 2 154 | length t2 = 6 155 | length t3 = 10 156 | 157 | # Resting complexes (12) 158 | C1 = t1 c a 159 | D = d1s d2 160 | e52 = t3*( d2*( d1s*( + ) ) + b( c*( t1*( + ) ) a( + t2* ) ) d2 ) 161 | e60 = t3*( d2*( d1s*( + ) d2 + b( c*( t1*( + ) ) a( + t2* ) ) ) ) 162 | I1 = d1s T2 b( a t2 + c ) 163 | P1 = t2* a*( c*( t1*( + ) ) ) 164 | P2 = d1s T2 b( a( t2( + ) ) ) d2 t3 165 | P3 = b( c*( t1* + ) ) 166 | R = d1s( d2( + t3* ) ) 167 | RW = d1s( T2 b( a( t2( + ) ) ) d2( t3( + ) ) ) 168 | S1 = d1s T2 b( a( t2( + ) ) c*( t1* + ) ) 169 | S2 = t1( c( a( + t2* ) b*( d2 t3 + ) ) ) 170 | 171 | # Resting macrostates (11) 172 | macrostate C1 = [C1] 173 | macrostate D = [D] 174 | macrostate e60 = [e60, e52] 175 | macrostate I1 = [I1] 176 | macrostate P1 = [P1] 177 | macrostate P2 = [P2] 178 | macrostate P3 = [P3] 179 | macrostate R = [R] 180 | macrostate RW = [RW] 181 | macrostate S1 = [S1] 182 | macrostate S2 = [S2] 183 | 184 | # Condensed reactions (6) 185 | reaction [condensed = 466694 /M/s ] e60 + I1 -> P3 + RW + D + C1 186 | reaction [condensed = 3082.99 /M/s ] I1 + P1 -> S1 + C1 187 | reaction [condensed = 3e+06 /M/s ] P2 + R -> RW + D 188 | reaction [condensed = 1.63659e+06 /M/s ] S1 + C1 -> I1 + P1 189 | reaction [condensed = 466694 /M/s ] S2 + I1 -> P3 + P2 + C1 190 | reaction [condensed = 3e+06 /M/s ] S2 + R -> e60 191 | ``` 192 | 193 | ### Tips & Tricks 194 | * You can specify concentrations of complexes in the input file, e.g.: 195 | 196 | C1 = t1 c a @initial 10 nM 197 | 198 | The benefit of hard-coding initial concentrations in the input file, is 199 | that they do not have to be specified again when simulating the output 200 | using the Pilsimulator software. 201 | 202 | * You can name complexes, even though you do not want them initially present. To do that, give them explicitly 0 initial concentration: 203 | 204 | I1 = d1s T2 b( a t2 + c ) @initial 0 nM 205 | 206 | * Every file produced by Peppercorn, can be used as an input to Peppercorn, 207 | although some types of input (e.g. macrostate assignments, condensed 208 | reactions) may be ignored with a warning. You can use that to specify 209 | a reaction with a specific type and rate constant and that reaction will 210 | then be part of the enumerated and condensed output of peppercorn. If 211 | Peppercorn enumerates an already specified reaction (same type, same 212 | complexes), the rate will not be updated. 213 | 214 | reaction [branch-4way = 1e-10 /s ] I2 -> P3 + P2 215 | 216 | Of course, all reactants and products must be previously defined complexes. 217 | You can use the supported reaction types: 218 | open, bind21, bind11, branch-3way, branch-4way ... but not condensed! 219 | 220 | * You can use a short-hand notation for a *super sequence* that is composed 221 | of multiple domains. For example, if a domain *k* is sometimes split into 222 | *k1*, *k2*, and *k3*, e.g. when they are not all bound at the same time, 223 | you can define 224 | 225 | sup-sequence k = k1 k2 k3 226 | 227 | and use the domain *k* as a shorthand for *k1 k2 k3* when applicable. 228 | Note, that the output will always use the extended format, explicitly 229 | listing the most detailed domain composition. 230 | 231 | * You can specify the nucleotide sequence of a domain, and it will remain 232 | present in the ouput file. Hower, note that rates (at the moment) only 233 | depend on domain length, and not on the nucleotide sequence. Use the keyword 234 | `sequence` to initialize a domain with the nucleotide sequence: 235 | 236 | sequence a = ACGTUGCA : 8 237 | 238 | The digit at the end denotes the length of the domain, it can be omitted, 239 | but must not be wrong. 240 | 241 | * Peppercorn supports a range of different input file formats, e.g. the 242 | specification language of the [Seesaw Compiler]. You can use the option 243 | `--dry-run` to translate every valid input into kernel format without 244 | enumeration. 245 | 246 | $ cat seesaw_ciruit.ssw | peppercorn --dry-run 247 | 248 | * Consider taking a look at the [case studies] directory for more examples. 249 | 250 | ## Version 251 | 1.1.1 -- Removed deprecated setup.py, bumping to Python>=3.8. 252 | 253 | 1.1 -- Mayor Python>=3.7 code cleanup and speedups for some core functions. 254 | * rewrite of all objects to use dsdobjects>=0.8 (an attempt to fix rare segfaults). 255 | * moved ratemodel related functions to peppercornenumerator/ratemodel.py. 256 | * renamed open to open1N in order to avoid name conflicts. 257 | * default concentration unit for output is now 'nM' throughout the library. 258 | * updating and extending unittests. 259 | * some pythonification of old code. 260 | * removing deprecated code and undocumented experimental features. 261 | * updated files in case_study directory for compatibility with changes. 262 | 263 | 1.0.1 -- bugfix for pilsimulator --labels option. 264 | 265 | 1.0 -- stable release, requires python >= 3.7. 266 | 267 | ## Authors 268 | Stefan Badelt, Casey Grun, Karthik V. Sarma, Brian Wolfe, Seung Woo Shin and Erik Winfree. 269 | 270 | ## Cite 271 | If you are using this package, plese cite: 272 | - Stefan Badelt, Casey Grun, Karthik V. Sarma, Seung Woo Shin, Brian Wolfe, and Erik Winfree (2020) 273 | "Enumeration, condensation and simulation of pseudoknot-free domain-level DNA strand displacement systems" 274 | [[Badelt et al. (2020)]]. 275 | 276 | 277 | [Badelt et al. (2020)]: 278 | [example.pil]: 279 | [Seesaw Compiler]: 280 | [case studies]: 281 | [DNA 26]: 282 | [this talk]: 283 | 284 | -------------------------------------------------------------------------------- /case_studies/Many_systems.ipynb: -------------------------------------------------------------------------------- 1 | { 2 | "cells": [ 3 | { 4 | "cell_type": "markdown", 5 | "metadata": {}, 6 | "source": [ 7 | "### IMPORTANT: matplotlib.pyplot conflicts with garbage collection of peppercorns' objects. \n", 8 | "Whenever you enumerate multiple systems that use same-named domains, complexes, etc., make sure to import plotting libraries only after all your data has been generated. (You have to restart the kernel in order to modify your data once a plotting library has been importet, even if it is e.g. a shell script in the background importing that library. Yes, it's terrible.) " 9 | ] 10 | }, 11 | { 12 | "cell_type": "markdown", 13 | "metadata": { 14 | "slideshow": { 15 | "slide_type": "slide" 16 | } 17 | }, 18 | "source": [ 19 | "# System Analysis" 20 | ] 21 | }, 22 | { 23 | "cell_type": "markdown", 24 | "metadata": { 25 | "slideshow": { 26 | "slide_type": "skip" 27 | } 28 | }, 29 | "source": [ 30 | "# Initialization" 31 | ] 32 | }, 33 | { 34 | "cell_type": "code", 35 | "execution_count": null, 36 | "metadata": { 37 | "slideshow": { 38 | "slide_type": "skip" 39 | } 40 | }, 41 | "outputs": [], 42 | "source": [ 43 | "import pandas as pd\n", 44 | "from numpy import log10, sqrt" 45 | ] 46 | }, 47 | { 48 | "cell_type": "code", 49 | "execution_count": null, 50 | "metadata": {}, 51 | "outputs": [], 52 | "source": [ 53 | "def sema(vect, fig):\n", 54 | " \"\"\"Rewrite the semantics column into a more compact, human readable version.\n", 55 | " \"\"\"\n", 56 | " nv = []\n", 57 | " for line in vect:\n", 58 | " v = []\n", 59 | " for (x,y) in fig.pepperargs[line].items():\n", 60 | " if x == 'enumconc': continue\n", 61 | " if x == 'max_complex_size': continue\n", 62 | " if x == 'max_complex_count': continue\n", 63 | " if x == 'max_reaction_count': continue\n", 64 | " if x == 'condensed': \n", 65 | " z = x if y is True else 'detailed'\n", 66 | " else:\n", 67 | " z = '{}={}'.format(x,y)\n", 68 | " v.append(z)\n", 69 | " nv.append(', '.join(v))\n", 70 | " return nv" 71 | ] 72 | }, 73 | { 74 | "cell_type": "code", 75 | "execution_count": null, 76 | "metadata": {}, 77 | "outputs": [], 78 | "source": [ 79 | "from zhang2007 import data; z07 = data()\n", 80 | "from yin2008 import data; y08 = data()\n", 81 | "from zhang2009 import data; z09 = data()\n", 82 | "from zhang2010 import data; z10 = data()\n", 83 | "from zhang2011 import data; z11 = data()\n", 84 | "from kotani2017 import data; k17 = data()\n", 85 | "\n", 86 | "%who list" 87 | ] 88 | }, 89 | { 90 | "cell_type": "code", 91 | "execution_count": null, 92 | "metadata": {}, 93 | "outputs": [], 94 | "source": [ 95 | "def fill_table_prf(data, verb = 0):\n", 96 | " for fig in data:\n", 97 | " #print(fig.name)\n", 98 | " fig.eval(verbose = verb, enumprofile = True)\n", 99 | "\n", 100 | "def fill_table(data, verb = 0):\n", 101 | " for fig in data:\n", 102 | " print(fig.name)\n", 103 | " display(fig.pepperargs['default'])\n", 104 | " assert fig.pepperargs['default']['condensed'] == True\n", 105 | " fig.eval('default', verbose = verb)\n", 106 | " for df in fig.get_dataframes():\n", 107 | " df['Name'] = fig.name\n", 108 | " df['Semantics'] = sema(df['Semantics'], fig)\n", 109 | " yield df" 110 | ] 111 | }, 112 | { 113 | "cell_type": "markdown", 114 | "metadata": { 115 | "slideshow": { 116 | "slide_type": "slide" 117 | } 118 | }, 119 | "source": [ 120 | "# Peppercorn estimates" 121 | ] 122 | }, 123 | { 124 | "cell_type": "code", 125 | "execution_count": null, 126 | "metadata": { 127 | "slideshow": { 128 | "slide_type": "slide" 129 | } 130 | }, 131 | "outputs": [], 132 | "source": [ 133 | "Table1 = pd.DataFrame()\n", 134 | "for x in fill_table(z07 + y08 + z09 + z10 + z11 + k17, verb = 0):\n", 135 | " display(x)\n", 136 | " Table1 = Table1.append(x)" 137 | ] 138 | }, 139 | { 140 | "cell_type": "code", 141 | "execution_count": null, 142 | "metadata": {}, 143 | "outputs": [], 144 | "source": [ 145 | "%%timeit\n", 146 | "fill_table_prf(z07 + y08 + z09 + z10 + z11 + k17)" 147 | ] 148 | }, 149 | { 150 | "cell_type": "markdown", 151 | "metadata": {}, 152 | "source": [ 153 | "# Everything" 154 | ] 155 | }, 156 | { 157 | "cell_type": "code", 158 | "execution_count": null, 159 | "metadata": {}, 160 | "outputs": [], 161 | "source": [ 162 | "import matplotlib.pyplot as plt\n", 163 | "import seaborn as sns\n", 164 | "sns.set(style=\"darkgrid\")" 165 | ] 166 | }, 167 | { 168 | "cell_type": "code", 169 | "execution_count": null, 170 | "metadata": {}, 171 | "outputs": [], 172 | "source": [ 173 | "Table1.to_latex('ManySystems.tex', index=False, float_format='{:.3g}'.format)\n", 174 | "tmpfig = Table1\n", 175 | "#tmpfig.reset_index(inplace=True, drop=True)\n", 176 | "#tmpfig = tmpfig.iloc[0:-1]\n", 177 | "#tmpfig = tmpfig.iloc[[4,5,6,7,28,29,30,31], :]\n", 178 | "#display(tmpfig)\n", 179 | "\n", 180 | "if False: # Just look at them individually\n", 181 | " #tmpfig = tmpfig.loc[tmpfig['Name'].isin([fig.name for fig in z07+z10])]\n", 182 | " m = 'o'\n", 183 | "else:\n", 184 | " m = ['+'] * 3\n", 185 | " m += ['.']\n", 186 | " m += ['^'] * 3\n", 187 | " m += ['*'] * 4\n", 188 | " m += ['v']\n", 189 | " m += ['o'] * 3\n", 190 | "\n", 191 | "colors = sns.color_palette(\"Set1\", n_colors=8, desat=.5).as_hex()\n", 192 | " \n", 193 | "g = sns.lmplot(x = \"Time (experiment)\", y = \"Time (simulation)\", \n", 194 | " col = 'Metric', hue = 'Name', sharey = True, \n", 195 | " col_order = ['completion-time', 'diagonal-crossing-time'],\n", 196 | " data = tmpfig, markers = m, palette = colors,\n", 197 | " fit_reg = False, legend = False)\n", 198 | "\n", 199 | "plt.xscale('log')\n", 200 | "plt.yscale('log')\n", 201 | "plt.legend(bbox_to_anchor=(1, -0.2), loc=1, borderaxespad=0.)#, fontsize = 10)\n", 202 | "\n", 203 | "mi, ma = 1e1, 1e5\n", 204 | "for ax in g.axes[0]:\n", 205 | " ax.plot([mi, ma], [mi, ma], linewidth=3, color='white', zorder=0)\n", 206 | "\n", 207 | "g.axes[0][0].set_title('50%-completion time')\n", 208 | "g.axes[0][1].set_title('Diagonal-crossing time')\n", 209 | "\n", 210 | "g.set(xlabel='Experimental timepoint [s]') \n", 211 | "g.axes[0][0].set(ylabel='Peppercorn timepoint [s]')\n", 212 | "\n", 213 | "plt.savefig('all_systems.pdf', bbox_inches='tight')\n", 214 | "plt.savefig('all_systems.svg', bbox_inches='tight')" 215 | ] 216 | } 217 | ], 218 | "metadata": { 219 | "kernelspec": { 220 | "display_name": "py38", 221 | "language": "python", 222 | "name": "py38" 223 | }, 224 | "language_info": { 225 | "codemirror_mode": { 226 | "name": "ipython", 227 | "version": 3 228 | }, 229 | "file_extension": ".py", 230 | "mimetype": "text/x-python", 231 | "name": "python", 232 | "nbconvert_exporter": "python", 233 | "pygments_lexer": "ipython3", 234 | "version": "3.8.5" 235 | } 236 | }, 237 | "nbformat": 4, 238 | "nbformat_minor": 4 239 | } 240 | -------------------------------------------------------------------------------- /case_studies/README.md: -------------------------------------------------------------------------------- 1 | # Case study data 2 | This directory contains the data used for the publication [Badelt et al. (2020)]: 3 | 4 | Badelt, Grun, Sarma, Wolfe, Shin, Winfree: 5 | *A domain-level DNA strand displacement reaction enumerator allowing arbitrary non-pseudoknotted secondary structures* 6 | 7 | Note: The notebooks have been produced with peppercorn version 1.0. 8 | If you are experiencing problems at later versions of this software, 9 | please install peppercornenumerator==1.0. 10 | 11 | You must make a directory called **tmp/** where temporary files are stored. Be 12 | aware that the temporary files remain in this directory for further analysis. 13 | 14 | # Jupyter notebooks 15 | If you are interested in particular figures, the following notebook files have 16 | been used to produce Figures 6 - 11. 17 | 18 | * Condensation.ipynb ([Badelt et al. (2020)], [Figure 6]) 19 | * Reactionrates.ipynb ([Badelt et al. (2020)], [Figure 7]) 20 | * Kotani2017.ipynb ([Badelt et al. (2020)], [Figure 8]) 21 | * Yin2008.ipynb ([Badelt et al. (2020)], [Figure 9]) 22 | * Qian2011.ipynb ([Badelt et al. (2020)], [Figure 10]) 23 | * Many_systems.ipynb ([Badelt et al. (2020)], [Figure 11]) 24 | 25 | # Commandline verison 26 | Then execute the python script: 27 | 28 | $ ./figure_analysis.py 29 | 30 | The script reads the experimental data from library files, where each of those 31 | library files corresponds to a particular publictation, currently: 32 | 33 | * zhang2007.py 34 | * yin2008.py 35 | * zhang2009.py 36 | * zhang2010.py 37 | * zhang2011.py 38 | * genot2011.py 39 | * qian2011.py 40 | * qian2011_sqrt.py 41 | * kotani2017.py 42 | * zhang2009_rates.py 43 | * dabby2013_rates.py 44 | 45 | You might want to adapt settings in those files. 46 | 47 | [Badelt et al. (2020)]: 48 | [Figure 6]: 49 | [Figure 7]: 50 | [Figure 8]: 51 | [Figure 9]: 52 | [Figure 10]: 53 | [Figure 11]: 54 | -------------------------------------------------------------------------------- /case_studies/Yin2008.ipynb: -------------------------------------------------------------------------------- 1 | { 2 | "cells": [ 3 | { 4 | "cell_type": "markdown", 5 | "metadata": {}, 6 | "source": [ 7 | "### IMPORTANT: matplotlib.pyplot conflicts with garbage collection of peppercorns' objects. \n", 8 | "Whenever you enumerate multiple systems that use same-named domains, complexes, etc., make sure to import plotting libraries only after all your data has been generated. (You have to restart the kernel in order to modify your data once a plotting library has been importet, even if it is e.g. a shell script in the background importing that library. Yes, it's terrible.)" 9 | ] 10 | }, 11 | { 12 | "cell_type": "code", 13 | "execution_count": null, 14 | "metadata": {}, 15 | "outputs": [], 16 | "source": [ 17 | "import numpy as np\n", 18 | "from pandas import DataFrame\n", 19 | "from yin2008 import data; y08 = data()" 20 | ] 21 | }, 22 | { 23 | "cell_type": "markdown", 24 | "metadata": {}, 25 | "source": [ 26 | "# Generate the data" 27 | ] 28 | }, 29 | { 30 | "cell_type": "code", 31 | "execution_count": null, 32 | "metadata": {}, 33 | "outputs": [], 34 | "source": [ 35 | "%%timeit\n", 36 | "y08 = data()\n", 37 | "for fig in y08:\n", 38 | " fig.eval(verbose = 0, enumprofile = True)" 39 | ] 40 | }, 41 | { 42 | "cell_type": "code", 43 | "execution_count": null, 44 | "metadata": {}, 45 | "outputs": [], 46 | "source": [ 47 | "Table1 = DataFrame()\n", 48 | "for fig in y08:\n", 49 | " display(fig.pepperargs['default'])\n", 50 | " fig.eval('default', verbose = 0, cmpfig=True)\n", 51 | " for df in fig.get_dataframes():\n", 52 | " df['name'] = fig.name\n", 53 | " #display(df)\n", 54 | " Table1 = Table1.append(df)" 55 | ] 56 | }, 57 | { 58 | "cell_type": "code", 59 | "execution_count": null, 60 | "metadata": {}, 61 | "outputs": [], 62 | "source": [ 63 | "import matplotlib.pyplot as plt\n", 64 | "from numpy import log10\n", 65 | "import seaborn as sns\n", 66 | "sns.set(style=\"darkgrid\")\n", 67 | "\n", 68 | "tmpfig = Table1.copy()\n", 69 | "tmpfig['Time (experiment)'] = log10(tmpfig['Time (experiment)'])\n", 70 | "tmpfig['Time (simulation)'] = log10(tmpfig['Time (simulation)'])\n", 71 | "tmpfig = tmpfig.loc[tmpfig['Semantics'].isin(['default'])]\n", 72 | "#display(tmpfig)\n", 73 | "\n", 74 | "sns.lmplot(x = \"Time (experiment)\", \n", 75 | " y = \"Time (simulation)\", \n", 76 | " hue = \"Metric\", \n", 77 | " fit_reg = False,\n", 78 | " data = tmpfig)\n", 79 | "\n", 80 | "(mi, ma)=(1, 4)\n", 81 | "plt.plot([mi, ma], [mi, ma], linewidth=1, color='white',zorder=0)\n", 82 | "#plt.gcf().set_size_inches(3.5,2.5)\n" 83 | ] 84 | }, 85 | { 86 | "cell_type": "code", 87 | "execution_count": null, 88 | "metadata": {}, 89 | "outputs": [], 90 | "source": [ 91 | "# Get Data from File\n", 92 | "F3 = y08[0]\n", 93 | "nxy = np.loadtxt(F3.cmpfig['default'], skiprows=1)\n", 94 | "\n", 95 | "print(F3.cmpfig['default'])\n", 96 | "\n", 97 | "time = nxy[:,0] / 60\n", 98 | "ys = nxy[:,1:]\n", 99 | "legend = ['20 nM', '6 nM', '2 nM', '1 nM', '0.6 nM', '0.4 nM', '0.2 nM', '0.1 nM', '0.06 nM', '0.02 nM', '0.01 nM']#, '0 nM']\n", 100 | "legend = list(map(lambda x: '{}{}'.format('I = ', x), legend))\n", 101 | "\n", 102 | "assert ys.shape[1] == len(legend)\n", 103 | "\n", 104 | "# Customize plot using Yin 2008 color scheme, etc.\n", 105 | "mycolors = ['#882486', \n", 106 | " '#ffbb11', \n", 107 | " '#ea0081', \n", 108 | " '#eb1c22',\n", 109 | " '#f68a1d',\n", 110 | " '#0faa44', \n", 111 | " '#87398e', \n", 112 | " '#2b2d89',\n", 113 | " '#016667',\n", 114 | " '#027ac5',\n", 115 | " '#eb125b']\n", 116 | " #'#211e1f']\n", 117 | "\n", 118 | "plt.figure(figsize=(3.5,2.5))\n", 119 | "plt.gca().set_prop_cycle(color=mycolors)\n", 120 | "#sns.set(rc={'figure.figsize':(3.5,2.5)})\n", 121 | "\n", 122 | "#plt.gca().invert_yaxis()\n", 123 | "\n", 124 | "# Plot the data\n", 125 | "plt.plot(time, ys)\n", 126 | "\n", 127 | "plt.xlim(-0.5,20.5)\n", 128 | "plt.xticks(np.arange(0, 21, step=5))\n", 129 | "\n", 130 | "plt.ylim(21,-1)\n", 131 | "plt.yticks(np.arange(0, 21, step=5))\n", 132 | "\n", 133 | "plt.legend(legend, ncol=1, loc='center right', fontsize=7);\n", 134 | "plt.gca().set_xlabel('Time [min]', fontsize=10)\n", 135 | "plt.gca().set_ylabel('Concentration A [nM]', fontsize=10)\n", 136 | "plt.gca().axhline(y=10, linewidth=1, color='black', linestyle='--')\n", 137 | "\n", 138 | "#plt.savefig('yinF3.pdf', bbox_inches='tight')\n", 139 | "#plt.savefig('yinF3.svg', bbox_inches='tight')\n" 140 | ] 141 | }, 142 | { 143 | "cell_type": "code", 144 | "execution_count": null, 145 | "metadata": {}, 146 | "outputs": [], 147 | "source": [] 148 | } 149 | ], 150 | "metadata": { 151 | "kernelspec": { 152 | "display_name": "py38", 153 | "language": "python", 154 | "name": "py38" 155 | }, 156 | "language_info": { 157 | "codemirror_mode": { 158 | "name": "ipython", 159 | "version": 3 160 | }, 161 | "file_extension": ".py", 162 | "mimetype": "text/x-python", 163 | "name": "python", 164 | "nbconvert_exporter": "python", 165 | "pygments_lexer": "ipython3", 166 | "version": "3.8.5" 167 | } 168 | }, 169 | "nbformat": 4, 170 | "nbformat_minor": 4 171 | } 172 | -------------------------------------------------------------------------------- /case_studies/dabby2013_rates.py: -------------------------------------------------------------------------------- 1 | 2 | def dabby2013_4way_displacement(nm): 3 | (n,m) = nm 4 | assert n<7 and (m<7 or m==16) 5 | M = 0 if (m==6 or m==16) else 6-m 6 | N = 6-n 7 | return """# Nadine Dabby experiments 8 | # (n,m,k1_fit) from and Nadine Dabby, 9 | # Caltech PhD Thesis, Table 5.2 10 | # (note m,n have consistent meaning, but order in table is swapped.) 11 | 12 | length x = 21 13 | {}length m = {} # m 14 | {}length M = {} # M 15 | {}length n = {} # n 16 | {}length N = {} # N 17 | 18 | # starting states 19 | 20 | # x*( m* M* + N* n* ) 21 | rep = x*( {} {} + {} {} ) 22 | 23 | # m x( + ) n 24 | clx = {} x( + ) {} 25 | 26 | # x*( m*( M* + ) ) 27 | pr1 = x*( {} {} + {} ) 28 | 29 | # x*( n( + N* ) ) 30 | pr2 = x*( {} + {} {} ) 31 | 32 | """.format( 33 | '#' if m==0 else '', m, 34 | '#' if M==0 else '', M, 35 | '#' if n==0 else '', n, 36 | '#' if N==0 else '', N, 37 | '' if m==0 else 'm*', 38 | '' if M==0 else 'M*', 39 | '' if N==0 else 'N*', 40 | '' if n==0 else 'n*', 41 | '' if m==0 else 'm', 42 | '' if n==0 else 'n', 43 | '' if m==0 else 'm*(', 44 | '' if M==0 else 'M*', 45 | '' if m==0 else ')', 46 | '' if n==0 else 'n(', 47 | '' if N==0 else 'N*', 48 | '' if n==0 else ')') 49 | 50 | def data(evaluate=False, verbose = 0): 51 | from figure_analysis import FigureData 52 | 53 | d13 = FigureData('Dabby (2013)\n4-way strand displacement') 54 | d13.fname = 'Dabby2013-4way' 55 | current = d13 56 | 57 | pilp = [(0, 2), (2, 2), (2, 0), 58 | (4, 2), (4, 0), (0, 4), 59 | (2, 4), (6, 2), (0, 6), 60 | (4, 4), (6, 0), (2, 6), 61 | (4, 6), (6, 4), (6, 6)] 62 | litr = [(0.047), (0.10), (0.033), 63 | (0.93), (0.039), (0.97), 64 | (56), (490), (58), 65 | (770), (5.0), (9.4e3), 66 | (7.0e4), (2.8e5), (6.9e5)] 67 | 68 | for (pil, rate) in zip(pilp, litr): 69 | pilstring = dabby2013_4way_displacement(pil) 70 | exp_result = 'rep + clx -> pr1 + pr2 [k={}]'.format(rate) 71 | current.add_reaction_rate_setup(pilstring, exp_result, pil) 72 | 73 | current.pepperargs['default'] = current.pepperargs['condensed'].copy() 74 | if evaluate: 75 | current.eval() 76 | 77 | if verbose: 78 | for df in current.get_dataframes(): 79 | print(df) 80 | 81 | return [d13] 82 | 83 | if __name__ == '__main__': 84 | data() 85 | 86 | -------------------------------------------------------------------------------- /case_studies/genot2011.py: -------------------------------------------------------------------------------- 1 | 2 | def genot2011_F3_pil(mn) : 3 | (m,n) = mn 4 | return """ 5 | length d1 = 15 6 | length d2 = 22 7 | length d3 = 14 8 | 9 | length d05 = {} 10 | length d04 = {} 11 | 12 | S = d1 d2( + d3* d05* ) 13 | I = d2 d04 d3 14 | 15 | T = d2( d04 d3( + ) d05* ) 16 | W = d1 d2 17 | """.format(m, n) 18 | 19 | def genot2011_F4A_pil(_) : 20 | return """ 21 | length d1 = 15 22 | length d2 = 22 23 | length d3 = {} 24 | 25 | S = d1 d2( + d3* ) 26 | I = d2 d3 27 | 28 | T = d2( d3( + ) ) 29 | W = d1 d2 30 | """.format(_) 31 | 32 | def genot2011_F4B_pil(_) : 33 | return """ 34 | length d1 = 15 35 | length d2 = 22 36 | length d8 = 1 37 | length d3 = {} 38 | 39 | S = d1 d2( + d3* d8 ) 40 | I = d2 d3 41 | 42 | T = d2( d3( + ) d8 ) 43 | W = d1 d2 44 | """.format(_) 45 | 46 | def genot2011_F4C_pil(_) : 47 | return """ 48 | length d1 = 15 49 | length d2 = 22 50 | length d3 = 6 # original 51 | #length d3 = 4 # try-to-fit 52 | 53 | S = d1 d2( + d3* ) 54 | I = d2 d3 55 | 56 | T = d2( d3( + ) ) 57 | W = d1 d2 58 | """ 59 | 60 | def genot2011_F4D_pil(_) : 61 | return """ 62 | length d1 = 15 63 | length d2 = 22 64 | length d3 = 14 # original 65 | #length d3 = 7 # try-to-fit 66 | length d4 = 17 67 | length d5 = 17 68 | 69 | S = d1 d2( + d3* d5 ) # d3: 14 70 | I = d2 d4 d3 71 | 72 | T = d2( d4 d3( + ) d5 ) 73 | W = d1 d2 74 | """ 75 | 76 | def genot2011_SF4A_pil(dl) : 77 | return """ 78 | \rlength d1 = 15 79 | \rlength d2a = 5 80 | \rlength d2b = 7 81 | \rlength d2c = 10 82 | \rlength d3 = 14 # n 83 | \rlength d4 = {} # m 84 | \rlength d5 = {} # m 85 | 86 | \rsup-sequence d2 = d2a d2b d2c 87 | \r 88 | \rS = d1 d2( + d3* d5 ) 89 | \rX = d2 d4 d3 90 | 91 | \rW = d2( d4 d3( + ) d5 ) 92 | \rP = d1 d2 93 | 94 | \rR = d1( d2a( + d2b* ) ) 95 | 96 | \rF = d1 d2a 97 | \rFW = d1( d2a( d2b( d2c + ) ) ) 98 | """.format(dl, dl) 99 | 100 | def genot2011_SF5_pil(dl) : 101 | return """ 102 | \rlength d1 = 15 103 | \rlength d2a = 5 104 | \rlength d2b = 7 105 | \rlength d2c = 10 106 | \rlength d3 = {} # n 107 | \rlength d4 = 20 # m 108 | \rlength d5 = 20 # m 109 | 110 | \rsup-sequence d2 = d2a d2b d2c 111 | \r 112 | \rS = d1 d2( + d3* d5 ) 113 | \rX = d2 d4 d3 114 | 115 | \rW = d2( d4 d3( + ) d5 ) 116 | \rP = d1 d2 117 | 118 | \rR = d1( d2a( + d2b* ) ) 119 | 120 | \rF = d1 d2a 121 | \rFW = d1( d2a( d2b( d2c + ) ) ) 122 | """.format(dl) 123 | 124 | 125 | def data(evaluate=False, verbose = 0): 126 | from figure_analysis import FigureData 127 | psim = "pilsimulator --no-jacobian --header --nxy --atol 1e-13 --rtol 1e-13 --mxstep 10000 " 128 | psim += "--t-lin 10000 --t8 1000" 129 | rates = {'k_slow': 1e-10, 'k_fast': 0.01} 130 | 131 | G11_F3 = FigureData('Fig. 3: |a|=14, |b|=22, varying: |n|, |m|') 132 | G11_F3.fname = 'Genot2011-F3' 133 | current = G11_F3 134 | template = genot2011_F3_pil 135 | 136 | pilp = [(8,7), (17,17), (20,20), (23,23)] # original 137 | # After 30% of the reaction has gone to completion, the signal dropped to 70%. 138 | litr = [(42, 1.98), (48, 1.98), (100, 1.98), (91, 1.98)] # seconds 139 | 140 | for (pil, res) in zip(pilp, litr): 141 | pilstring = template(pil) 142 | simulation = psim + " --pyplot-labels S I T W --p0 S=6.6 I=660" 143 | reporter = 'T' 144 | metric = 'completion-time' 145 | current.add_system_simulation_setup(pilstring, simulation, reporter, metric, '1.98', res)#, simargs='pilname') 146 | 147 | current.pepperargs['default'] = current.pepperargs['condensed'].copy() 148 | current.pepperargs['default'].update(rates) 149 | 150 | if evaluate: 151 | current.eval() 152 | 153 | if verbose: 154 | for df in current.get_dataframes(): 155 | print(df) 156 | 157 | 158 | G11_F4A = FigureData('Fig. 4A: |n|=|m|=0, either |a|=11 or |a|=9') 159 | G11_F4A.fname = 'Genot2011-F4A' 160 | current = G11_F4A 161 | template = genot2011_F4A_pil 162 | 163 | pilp = [11, 9] 164 | #litr = [(32, 0.58*6.6), (38, 0.58*6.6)] 165 | litr = [(2, 1.98), (3, 1.98)] 166 | 167 | for (pil, res) in zip(pilp, litr): 168 | pilstring = template(pil) 169 | simulation = psim + " --pyplot-labels S I T W --p0 S=6.6 I=22" 170 | reporter = 'T' 171 | metric = 'completion-time' 172 | current.add_system_simulation_setup(pilstring, simulation, reporter, metric, '1.98', res)#, simargs='pilname') 173 | 174 | current.pepperargs['default'] = current.pepperargs['condensed'].copy() 175 | current.pepperargs['default'].update(rates) 176 | 177 | if evaluate: 178 | current.eval() 179 | 180 | if verbose: 181 | for df in current.get_dataframes(): 182 | print(df) 183 | 184 | 185 | G11_F4B = FigureData('Fig. 4B: |n|=|m|=1, either |a|=11 or |a|=9') 186 | G11_F4B.fname = 'Genot2011-F4B' 187 | current = G11_F4B 188 | template = genot2011_F4B_pil 189 | 190 | pilp = [11, 9] 191 | #litr = [(44, 3.3), (182, 3.3)] 192 | litr = [(15, 1.98), (75, 1.98)] 193 | 194 | for (pil, res) in zip(pilp, litr): 195 | pilstring = template(pil) 196 | simulation = psim + " --pyplot-labels S I T W --p0 S=6.6 I=22" 197 | reporter = 'T' 198 | metric = 'completion-time' 199 | current.add_system_simulation_setup(pilstring, simulation, reporter, metric, '1.98', res)#, simargs='pilname') 200 | 201 | current.pepperargs['default'] = current.pepperargs['condensed'].copy() 202 | current.pepperargs['default'].update(rates) 203 | 204 | if evaluate: 205 | current.eval() 206 | 207 | if verbose: 208 | for df in current.get_dataframes(): 209 | print(df) 210 | 211 | G11_F4C = FigureData('Fig. 4C: |n|=|m|=0, |a|=6, varying: [invader]$_0$') 212 | G11_F4C.fname = 'Genot2011-F4C' 213 | current = G11_F4C 214 | template = genot2011_F4C_pil 215 | 216 | sims = [psim + " --pyplot-labels S I T W --p0 S=6.6 I=330", 217 | psim + " --pyplot-labels S I T W --p0 S=6.6 I=145", 218 | psim + " --pyplot-labels S I T W --p0 S=6.6 I=66"] 219 | #litr = [(69, 3.3), (177, 3.3), (347, 3.3)] 220 | litr = [(25, 1.98), (75, 1.98), (150, 1.98)] 221 | 222 | for (sim, res) in zip(sims, litr): 223 | pilstring = template(None) 224 | simulation = sim 225 | reporter = 'T' 226 | metric = 'completion-time' 227 | current.add_system_simulation_setup(pilstring, simulation, reporter, metric, '1.98', res)#, simargs=sim[sim.find('I='):]) 228 | 229 | current.pepperargs['default'] = current.pepperargs['condensed'].copy() 230 | current.pepperargs['default'].update(rates) 231 | 232 | if evaluate: 233 | current.eval() 234 | 235 | if verbose: 236 | for df in current.get_dataframes(): 237 | print(df) 238 | 239 | G11_F4D = FigureData('Fig. 4D: |n|=|m|=17, |a|=14, varying: [invader]$_0$') 240 | G11_F4D.fname = 'Genot2011-F4D' 241 | current = G11_F4D 242 | template = genot2011_F4D_pil 243 | sims = [psim + " --pyplot-labels S I T W --p0 S=6.6 I=330", 244 | psim + " --pyplot-labels S I T W --p0 S=6.6 I=145", 245 | psim + " --pyplot-labels S I T W --p0 S=6.6 I=66"] 246 | #litr = [(176, 3.3), (213, 3.3), (248, 3.3)] 247 | litr = [(51, 1.98), (55, 1.98), (60, 1.98)] 248 | 249 | for (sim, res) in zip(sims, litr): 250 | pilstring = template(None) 251 | simulation = sim 252 | reporter = 'T' 253 | metric = 'completion-time' 254 | current.add_system_simulation_setup(pilstring, simulation, reporter, metric, '1.98', res)#, simargs=sim[sim.find('I='):]) 255 | 256 | current.pepperargs['default'] = current.pepperargs['condensed'].copy() 257 | current.pepperargs['default'].update(rates) 258 | 259 | if evaluate: 260 | current.eval() 261 | 262 | if verbose: 263 | for df in current.get_dataframes(): 264 | print(df) 265 | 266 | G11_SF4A = FigureData('Sup. Fig. 4A: |a|=14, |b|=22 varying: |n|,|m|') 267 | G11_SF4A.fname = 'Genot2011-SF4A' 268 | current = G11_SF4A 269 | template = genot2011_SF4A_pil 270 | 271 | pilp = [17, 20, 23] 272 | #litr = [(9088, 5), (13927, 5), (28681, 5)] 273 | litr = [(4249, 3), (6492, 3), (12157,3)] 274 | 275 | psim = "pilsimulator --nxy --header --atol 1e-12 --rtol 1e-12 --mxstep 10000 --t-lin 100000 --t8 1e5" 276 | for (pil, res) in zip(pilp, litr): 277 | pilstring = template(pil) 278 | simulation = psim + " --pyplot-labels S X R F --p0 R=30 X=40 S=10" 279 | reporter = 'F' 280 | metric = 'completion-time' 281 | current.add_system_simulation_setup(pilstring, simulation, reporter, metric, '3', res) 282 | 283 | current.pepperargs['default'] = current.pepperargs['condensed'].copy() 284 | current.pepperargs['default'].update(rates) 285 | if evaluate: 286 | current.eval() 287 | 288 | if verbose: 289 | for df in current.get_dataframes(): 290 | print(df) 291 | 292 | G11_SF5 = FigureData('Sup. Fig. 5: |m|=|n|=20, varying: |a|') 293 | G11_SF5.fname = 'Genot2011-SF5' 294 | current = G11_SF5 295 | template = genot2011_SF5_pil 296 | 297 | pilp = [14, 10, 8, 6, 4, 2] 298 | litr = [(25382, 6.94), 299 | (35273, 5.76), 300 | (68655, 1.87), 301 | (77018, 0.91), 302 | (76218, 0.99), 303 | (77818, 0.79)] 304 | 305 | psim = "pilsimulator --nxy --header --atol 1e-12 --rtol 1e-12 --mxstep 10000 --t-lin 100000 --t8 1e5" 306 | for (pil, res) in zip(pilp, litr): 307 | pilstring = template(pil) 308 | simulation = psim + " --pyplot-labels S X R F --p0 R=30 X=40 S=10" 309 | reporter = 'F' 310 | metric = 'diagonal-crossing-time' 311 | tmax = '86400' 312 | cmax = '10' 313 | current.add_system_simulation_setup(pilstring, simulation, reporter, metric, 314 | ':'.join([tmax, cmax]), res) 315 | 316 | current.pepperargs['default'] = current.pepperargs['detailed'].copy() 317 | current.pepperargs['default'].update({'k_slow': 1e-10, 'k_fast': 1e-5}) 318 | if evaluate: 319 | current.eval() 320 | 321 | if verbose: 322 | for df in current.get_dataframes(): 323 | print(df) 324 | 325 | 326 | return [G11_F3, G11_F4A, G11_F4B, G11_F4C, G11_F4D, G11_SF4A]#, G11_SF5] 327 | 328 | if __name__ == '__main__': 329 | data(evaluate=True, verbose=1) 330 | 331 | -------------------------------------------------------------------------------- /case_studies/kotani2017.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python 2 | 3 | def kotani2017_F2_pil(x): 4 | return """ 5 | length a = 22 6 | length b = 22 7 | length c = 22 8 | length t1 = 6 9 | length t2 = 6 10 | length t3 = 10 11 | length T2 = 2 12 | 13 | length d1s = 16 14 | length d2 = 6 15 | 16 | S1 = d1s T2 b( a( t2( + ) ) c*( t1* + ) ) 17 | S2 = t1( c( a( + t2* ) b*( d2 t3 + ) ) ) 18 | C1 = t1 c a 19 | 20 | P1 = t2* a*( c*( t1*( + ) ) ) 21 | I1 = d1s T2 b( a t2 + c ) 22 | I2 = d1s T2 b( a( t2( + ) ) b*( d2 t3 + ) c*( t1* + ) ) 23 | 24 | P2 = d1s T2 b( a( t2( + ) ) ) d2 t3 25 | P3 = b( c*( t1* + ) ) 26 | 27 | R = d1s( d2( + t3* ) ) 28 | 29 | D = d1s d2 30 | RW = d1s( T2 b( a( t2( + ) ) ) d2( t3( + ) ) ) 31 | 32 | """.format(x) 33 | 34 | def kotani2017_F3_pil(x): 35 | return """ 36 | length a = 22 37 | length b = 22 38 | length c1 = 11 39 | length c2 = 11 40 | length e = 22 41 | length f = 22 42 | length g = 22 43 | length t1 = 6 44 | length t2 = 6 45 | length t3 = 10 46 | length t4 = 6 47 | length t5 = 6 48 | length T2 = 2 49 | 50 | length d1s = 16 51 | length d2 = 6 52 | 53 | S3 = t1 c1 c2( f( e( t5( + ) ) g*( t4* + ) ) ) 54 | S4 = t4( g( e( + t5* ) f*( T2 a + c2 ) ) ) 55 | C2 = t4 g e 56 | P4 = t5* e*( g*( t4*( + ) ) ) 57 | P5 = t1 c1 c2 f( e( t5( + ) ) ) T2 a 58 | P6 = c2( f( g*( t4* + ) ) ) 59 | 60 | 61 | S1 = d1s T2 b( a( t2( + ) ) c2*( c1*( t1* + ) ) ) 62 | S2 = t1( c1( c2( a( + t2* ) b*( d2 t3 + ) ) ) ) 63 | 64 | P1 = t2* a*( c2*( c1*( t1*( + ) ) ) ) 65 | P2 = d1s T2 b( a( t2( + ) ) ) d2 t3 66 | P3 = b( c2*( c1*( t1* + ) ) ) 67 | 68 | R = d1s( d2( + t3* ) ) 69 | 70 | C1 = t1 c1 c2 a 71 | 72 | D = d1s d2 73 | RW = d1s( T2 b( a( t2( + ) ) ) d2( t3( + ) ) ) 74 | """.format(x) 75 | 76 | def kotani2017_F4_pil(x): 77 | return """ 78 | \tlength a = 22 79 | \tlength b = 22 80 | \tlength o = 22 81 | \tlength c1 = 11 82 | \tlength c2 = 11 83 | \tlength t1 = 6 84 | \tlength t2 = 6 85 | \tlength t3 = 10 86 | \tlength T2 = 2 87 | \tlength x = 2 88 | \tlength y = 2 89 | 90 | \tlength d1s = 16 91 | \tlength d1r = 2 92 | \tlength d2 = 6 93 | 94 | \tS5 = o( b*( T2 a + c2 ) a( t2( y + ) ) c2*( c1*( t1* x* + ) ) ) d2 t3 95 | \tS6 = y* t2* a*( b*( c2*( + x t1 c1 ) ) o*( + d1s T2 ) c2*( c1*( t1*( + x ) ) ) ) 96 | \t 97 | \tC1 = x t1 c1 c2 a 98 | 99 | \tP1 = t2* a*( c2*( c1*( t1*( x*( + ) ) ) ) ) @i 0 M 100 | \tP2 = c2( b( a( t2( y( + ) ) ) ) ) @i 0 M 101 | 102 | \tI5 = c1 c2 o*( d2 t3 + ) b*( T2 a + c2 ) a t2 y @i 0 M 103 | \tI6 = c1( c2( o*( d2 t3 + ) b*( T2 a + c2 ) a( t2( y( + ) ) ) b*( c2*( + x t1 c1 ) ) o*( + d1s T2 ) ) ) t1* @i 0 M 104 | \tP10 = x( t1( c1( c2( b( o*( + ) ) T2 a( + t2* ) ) ) ) ) @i 0 M 105 | 106 | \tP8 = x t1 c1 c2 b( o*( + ) ) T2 a @i 0 M 107 | \tP9 = d1s T2 o( c2*( c1*( t1* + ) ) ) d2 t3 @i 0 M 108 | 109 | \tR = d1r( d1s( d2( + t3* ) ) ) 110 | \tD = d1r d1s d2 @i 0 M 111 | \tRW = d1s( T2 o( c2*( c1*( t1* + ) ) ) d2( t3( + ) ) ) d1r* @i 0 M 112 | """.format(x) 113 | 114 | def kotani2017_F4_pil_simple(x): 115 | return """Splits the reporter reaction into a shorter domain (t3 -> t3a t3b) to reduce large intermediates. 116 | \tlength a = 22 117 | \tlength b = 22 118 | \tlength o = 22 119 | \tlength c1 = 11 120 | \tlength c2 = 11 121 | \tlength t1 = 6 122 | \tlength t2 = 6 123 | \tlength t3a = 6 124 | \tlength t3b = 4 125 | \tlength T2 = 2 126 | \tlength x = 2 127 | \tlength y = 2 128 | 129 | \tlength d1s = 16 130 | \tlength d2 = 6 131 | 132 | \tS5 = o( b*( T2 a + c2 ) a( t2( y + ) ) c2*( c1*( t1* x* + ) ) ) d2 t3a t3b 133 | \tS6 = y* t2* a*( b*( c2*( + x t1 c1 ) ) o*( + d1s T2 ) c2*( c1*( t1*( + x ) ) ) ) 134 | \t 135 | \tC1 = x t1 c1 c2 a 136 | 137 | \tP1 = t2* a*( c2*( c1*( t1*( x*( + ) ) ) ) ) @i 0 M 138 | \tP2 = c2( b( a( t2( y( + ) ) ) ) ) @i 0 M 139 | 140 | \tI5 = c1 c2 o*( d2 t3a t3b + ) b*( T2 a + c2 ) a t2 y @i 0 M 141 | \tI6 = c1( c2( o*( d2 t3a t3b + ) b*( T2 a + c2 ) a( t2( y( + ) ) ) b*( c2*( + x t1 c1 ) ) o*( + d1s T2 ) ) ) t1* @i 0 M 142 | \tP10 = x( t1( c1( c2( b( o*( + ) ) T2 a( + t2* ) ) ) ) ) @i 0 M 143 | 144 | \tP8 = x t1 c1 c2 b( o*( + ) ) T2 a @i 0 M 145 | \tP9 = d1s T2 o( c2*( c1*( t1* + ) ) ) d2 t3a t3b @i 0 M 146 | 147 | \tR = d1s( d2( + t3a* ) ) 148 | \tD = d1s d2 @i 0 M 149 | \tRW = d1s( T2 o( c2*( c1*( t1* + ) ) ) d2( t3a( t3b + ) ) ) @i 0 M 150 | """.format(x) 151 | 152 | def data(evaluate=False, verbose = 0): 153 | from figure_analysis import FigureData 154 | 155 | # Default pilsimulator call 156 | psim = "pilsimulator --no-jacobian --nxy --header --atol 1e-12 --rtol 1e-12 --mxstep 1000" 157 | h10l = " --t0 0 --t8 36000 --t-lin 18000" 158 | h20l = " --t0 0 --t8 72000 --t-lin 18000" 159 | h30log = " --t0 0.1 --t8 108000 --t-log 18000" 160 | 161 | # Setup 162 | k17_F2 = FigureData('Kotani & Hughes (2017) Fig. 2 - Single-layer catalytic DSD with 4-way branch migration (varying catalyst)') 163 | k17_F2.fname = 'Kotani2017-F2' 164 | current = k17_F2 165 | template = kotani2017_F2_pil 166 | sims = [psim + h10l + " --pyplot-labels D S1 S2 R C1 --p0 S1=10 S2=10 R=20 C1=1", 167 | psim + h10l + " --pyplot-labels D S1 S2 R C1 --p0 S1=10 S2=10 R=20 C1=0.5", 168 | psim + h10l + " --pyplot-labels D S1 S2 R C1 --p0 S1=10 S2=10 R=20 C1=0.05"] 169 | #litr = [(7733, 7.42), (11333, 6.18), (25533, 1.40)] 170 | 171 | diagX = [(4893.97, 7.49), (9388.93, 6.29), (27435.62, 1.35)] 172 | for (sim, res) in zip(sims, diagX): 173 | pilstring = template(None) 174 | simulation = sim 175 | reporter = 'D' 176 | metric = 'diagonal-crossing-time' 177 | cmax = '10' 178 | tmax = '32400' 179 | current.add_system_simulation_setup(pilstring, simulation, reporter, metric, ':'.join([tmax, cmax]), res, simargs=sim[sim.find('C1='):]) 180 | 181 | halfC = [(555.34, 5.00), (4514.48, 5.00)] 182 | for (sim, res) in zip(sims, halfC): 183 | pilstring = template(None) 184 | simulation = sim 185 | reporter = 'D' 186 | metric = 'completion-time' 187 | current.add_system_simulation_setup(pilstring, simulation, reporter, metric, '5', res, simargs=sim[sim.find('C1='):]) 188 | 189 | current.pepperargs['default'] = current.pepperargs['condensed'].copy() 190 | current.pepperargs['default']['release_cutoff'] = 7 191 | current.pepperargs['default']['max_complex_size'] = 8 192 | 193 | if evaluate: 194 | current.eval(cmpfig=True) 195 | 196 | if verbose: 197 | for df in current.get_dataframes(): 198 | print(df) 199 | 200 | # Setup 201 | k17_F3 = FigureData('Kotani & Hughes (2017) Fig. 3 - Two-layer feedforward DSD system with 4-way branch migration (varying catalyst)') 202 | k17_F3.fname = 'Kotani2017-F3' 203 | current = k17_F3 204 | template = kotani2017_F3_pil 205 | sims = [psim + h30log + " --pyplot-labels D S1 S2 S3 S4 R C1 --p0 S1=10 S2=10 S3=10 S4=10 R=20 C1=0.1", 206 | psim + h30log + " --pyplot-labels D S1 S2 S3 S4 R C1 --p0 S1=10 S2=10 S3=10 S4=10 R=20 C1=0.01", 207 | psim + h30log + " --pyplot-labels D S1 S2 S3 S4 R C1 --p0 S1=10 S2=10 S3=10 S4=10 R=20 C1=0.001"] 208 | #litr = [(21220, 7.72), (64203, 3.12), (86996, 0.69)] 209 | 210 | diagX = [(21370.60, 7.78), (66095.66, 3.17), (90663.66, 0.74)] 211 | for (sim, res) in zip(sims, diagX): 212 | pilstring = template(None) 213 | simulation = sim 214 | reporter = 'D' 215 | metric = 'diagonal-crossing-time' 216 | cmax = '10' 217 | tmax = '97200' 218 | current.add_system_simulation_setup(pilstring, simulation, reporter, metric, ':'.join([tmax, cmax]), res, simargs=sim[sim.find('C1='):]) 219 | 220 | halfC = [(12994.28, 5)] 221 | for (sim, res) in zip(sims, halfC): 222 | pilstring = template(None) 223 | simulation = sim 224 | reporter = 'D' 225 | metric = 'completion-time' 226 | current.add_system_simulation_setup(pilstring, simulation, reporter, metric, '5', res, simargs=sim[sim.find('C1='):]) 227 | 228 | current.pepperargs['default'] = current.pepperargs['condensed'].copy() 229 | current.pepperargs['default']['release_cutoff'] = 7 230 | current.pepperargs['default']['max_complex_size'] = 8 231 | 232 | if evaluate: 233 | current.eval(cmpfig=True) 234 | 235 | if verbose: 236 | for df in current.get_dataframes(): 237 | print(df) 238 | 239 | # Setup 240 | k17_F4 = FigureData('Kotani & Hughes (2017) Fig. 4 - Autocatalytic DSD system with 4-way branch migration (varying autocatalyst)') 241 | k17_F4.fname = 'Kotani2017-F4' 242 | current = k17_F4 243 | template = kotani2017_F4_pil 244 | sims = [psim + h20l + " --pyplot-labels D S5 S6 R C1 --p0 S5=10 S6=10 R=20 C1=0.1", 245 | psim + h20l + " --pyplot-labels D S5 S6 R C1 --p0 S5=10 S6=10 R=20 C1=0.01", 246 | psim + h20l + " --pyplot-labels D S5 S6 R C1 --p0 S5=10 S6=10 R=20 C1=0.001", 247 | psim + h20l + " --pyplot-labels D S5 S6 R C1 --p0 S5=10 S6=10 R=20 C1=0"] 248 | 249 | diagX = [(6800.87, 6.11), (9054.78, 4.88), (10322.61, 4.21), (10921.30, 3.85)] 250 | for (sim, res) in zip(sims, diagX): 251 | pilstring = template(None) 252 | simulation = sim 253 | reporter = 'D' 254 | metric = 'diagonal-crossing-time' 255 | cmax = '10' 256 | tmax = '18000' 257 | current.add_system_simulation_setup(pilstring, simulation, reporter, metric, ':'.join([tmax, cmax]), res, simargs=sim[sim.find('C1='):]) 258 | 259 | halfC = [(6131.74, 5), (9125.22, 5), (10780.43, 5), (11520.00, 5)] 260 | for (sim, res) in zip(sims, halfC): 261 | pilstring = template(None) 262 | simulation = sim 263 | reporter = 'D' 264 | metric = 'completion-time' 265 | current.add_system_simulation_setup(pilstring, simulation, reporter, metric, '5', res, simargs=sim[sim.find('C1='):]) 266 | 267 | current.pepperargs['default'] = current.pepperargs['CONDENSED'].copy() 268 | current.pepperargs['default']['max_complex_size'] = 24 269 | current.pepperargs['default']['k_slow'] = 1e-4 270 | current.pepperargs['default']['k_fast'] = 1e-3 271 | 272 | if evaluate: 273 | current.eval(cmpfig=True) 274 | 275 | if verbose: 276 | for df in current.get_dataframes(): 277 | print(df) 278 | 279 | return [k17_F2, k17_F3, k17_F4] 280 | 281 | if __name__ == '__main__': 282 | print(kotani2017_F2_pil(None)) 283 | print(kotani2017_F3_pil(None)) 284 | print(kotani2017_F4_pil(None)) 285 | data(evaluate=True, verbose=1) 286 | 287 | -------------------------------------------------------------------------------- /case_studies/qian2011sqrt.py: -------------------------------------------------------------------------------- 1 | 2 | def qian2011_SF31(x): 3 | return """ 4 | INPUT(x1_0) = w[45,42] 5 | INPUT(x1_1) = w[46,41] 6 | INPUT(x2_0) = w[47,42] 7 | INPUT(x2_1) = w[48,41] 8 | INPUT(x3_0) = w[49,33] 9 | INPUT(x3_1) = w[50,35] 10 | INPUT(x4_0) = w[51,37] 11 | INPUT(x4_1) = w[52,38] 12 | 13 | OUTPUT(y1_0) = Fluor[6] 14 | OUTPUT(y1_1) = Fluor[23] 15 | OUTPUT(y2_0) = Fluor[24] 16 | OUTPUT(y2_1) = Fluor[25] 17 | 18 | seesawOR[10, 1, {21, 27}, {23}] 19 | seesawAND[53, 5, {18, 22}, {6}] 20 | seesawOR[34, 18, {28, 33, 37}, {53}] 21 | seesawAND[36, 21, {29, 35, 38}, {10}] 22 | seesawOR[39, 22, {29, 31}, {53}] 23 | seesawAND[40, 27, {30, 28}, {10}] 24 | 25 | seesawOR[41, 28, {46, 48}, {34, 40}] 26 | seesawAND[42, 29, {45, 47}, {36, 39}] 27 | seesawOR[43, 30, {33, 38}, {40}] 28 | seesawAND[44, 31, {35, 37}, {39}] 29 | seesawOR[20, 8, {35, 38}, {25}] 30 | seesawAND[26, 13, {33, 37}, {24}] 31 | 32 | inputfanout[33, 49, {34, 43, 26}] 33 | inputfanout[35, 50, {36, 44, 20}] 34 | inputfanout[37, 51, {34, 44, 26}] 35 | inputfanout[38, 52, {36, 43, 20}] 36 | 37 | reporter[6, 5] 38 | reporter[23, 1] 39 | reporter[24, 13] 40 | reporter[25, 8] 41 | """ 42 | 43 | def data(evaluate=False, verbose = 0): 44 | from figure_analysis import FigureData 45 | 46 | rates = {'k_slow': 0.01, 'k_fast': 1} 47 | seesaw_on = {'ssw_rxns': 'seesaw-T25-utbr-leak-reduced', 48 | 'ssw_expl': False, 49 | 'ssw_conc': 50e-9, 50 | 'dry_run': True} 51 | seesaw_off = {'ssw_rxns': None, 52 | 'ssw_expl': False, 53 | 'ssw_conc': 50e-9, 54 | 'dry_run': False} 55 | 56 | # Default pilsimulator call 57 | psim = "pilsimulator --no-jacobian --nxy --header --atol 1e-13 --rtol 1e-13 --mxstep 1000 --t8 36000 --t-lin 18000" 58 | 59 | # Setup 60 | SF31 = FigureData('Sup. Fig. 31: Integer 4-bit square-root circuit') 61 | SF31.fname = 'Qian2011-SF31' 62 | current = SF31 63 | template = qian2011_SF31 64 | sims = [psim + ' --pyplot-labels y1_0 y1_1 y2_0 y2_1 --p0 x4_0=45 x4_1=5 x3_0=45 x3_1=5 x2_0=45 x2_1=5 x1_0=45 x1_1=5', # 0000 65 | psim + ' --pyplot-labels y1_0 y1_1 y2_0 y2_1 --p0 x4_0=45 x4_1=5 x3_0=45 x3_1=5 x2_0=45 x2_1=5 x1_0=5 x1_1=45', # 0001 66 | psim + ' --pyplot-labels y1_0 y1_1 y2_0 y2_1 --p0 x4_0=45 x4_1=5 x3_0=45 x3_1=5 x2_0=5 x2_1=45 x1_0=45 x1_1=5', # 0010 67 | psim + ' --pyplot-labels y1_0 y1_1 y2_0 y2_1 --p0 x4_0=45 x4_1=5 x3_0=45 x3_1=5 x2_0=5 x2_1=45 x1_0=5 x1_1=45', # 0011 68 | psim + ' --pyplot-labels y1_0 y1_1 y2_0 y2_1 --p0 x4_0=45 x4_1=5 x3_0=5 x3_1=45 x2_0=45 x2_1=5 x1_0=45 x1_1=5', 69 | psim + ' --pyplot-labels y1_0 y1_1 y2_0 y2_1 --p0 x4_0=45 x4_1=5 x3_0=5 x3_1=45 x2_0=45 x2_1=5 x1_0=5 x1_1=45', 70 | psim + ' --pyplot-labels y1_0 y1_1 y2_0 y2_1 --p0 x4_0=45 x4_1=5 x3_0=5 x3_1=45 x2_0=5 x2_1=45 x1_0=45 x1_1=5', 71 | psim + ' --pyplot-labels y1_0 y1_1 y2_0 y2_1 --p0 x4_0=45 x4_1=5 x3_0=5 x3_1=45 x2_0=5 x2_1=45 x1_0=5 x1_1=45', 72 | psim + ' --pyplot-labels y1_0 y1_1 y2_0 y2_1 --p0 x4_0=5 x4_1=45 x3_0=45 x3_1=5 x2_0=45 x2_1=5 x1_0=45 x1_1=5', 73 | psim + ' --pyplot-labels y1_0 y1_1 y2_0 y2_1 --p0 x4_0=5 x4_1=45 x3_0=45 x3_1=5 x2_0=45 x2_1=5 x1_0=5 x1_1=45', 74 | psim + ' --pyplot-labels y1_0 y1_1 y2_0 y2_1 --p0 x4_0=5 x4_1=45 x3_0=45 x3_1=5 x2_0=5 x2_1=45 x1_0=45 x1_1=5', 75 | psim + ' --pyplot-labels y1_0 y1_1 y2_0 y2_1 --p0 x4_0=5 x4_1=45 x3_0=45 x3_1=5 x2_0=5 x2_1=45 x1_0=5 x1_1=45', 76 | psim + ' --pyplot-labels y1_0 y1_1 y2_0 y2_1 --p0 x4_0=5 x4_1=45 x3_0=5 x3_1=45 x2_0=45 x2_1=5 x1_0=45 x1_1=5', 77 | psim + ' --pyplot-labels y1_0 y1_1 y2_0 y2_1 --p0 x4_0=5 x4_1=45 x3_0=5 x3_1=45 x2_0=45 x2_1=5 x1_0=5 x1_1=45', 78 | psim + ' --pyplot-labels y1_0 y1_1 y2_0 y2_1 --p0 x4_0=5 x4_1=45 x3_0=5 x3_1=45 x2_0=5 x2_1=45 x1_0=45 x1_1=5', 79 | psim + ' --pyplot-labels y1_0 y1_1 y2_0 y2_1 --p0 x4_0=5 x4_1=45 x3_0=5 x3_1=45 x2_0=5 x2_1=45 x1_0=5 x1_1=45'] 80 | 81 | simargs = ['0000', 82 | '0001', 83 | '0010', 84 | '0011', 85 | '0100', 86 | '0101', 87 | '0110', 88 | '0111', 89 | '1000', 90 | '1001', 91 | '1010', 92 | '1011', 93 | '1100', 94 | '1101', 95 | '1110', 96 | '1111'] 97 | 98 | litr = [('y1_0', [(4.2*3600, 50*0.42), 99 | (7.1*3600, 50*0.1), 100 | (7.1*3600, 50*0.1), 101 | (7.1*3600, 50*0.1), 102 | (3.9*3600, 50*0.55), 103 | (4.1*3600, 50*0.45), 104 | (4.1*3600, 50*0.45), 105 | (4.1*3600, 50*0.45), 106 | (4.5*3600, 50*0.42), 107 | (7.3*3600, 50*0.1), 108 | (7.3*3600, 50*0.1), 109 | (7.3*3600, 50*0.1), 110 | (7.3*3600, 50*0.1), 111 | (7.3*3600, 50*0.1), 112 | (7.3*3600, 50*0.1), 113 | (7.3*3600, 50*0.1)]), 114 | ('y1_1', [(7.1*3600, 50*0.1), 115 | (5.0*3600, 50*0.4), 116 | (5.0*3600, 50*0.4), 117 | (4.2*3600, 50*0.42), 118 | (7.3*3600, 50*0.08), 119 | (7.3*3600, 50*0.08), 120 | (7.3*3600, 50*0.08), 121 | (7.3*3600, 50*0.08), 122 | (6.9*3600, 50*0.1), 123 | (4.0*3600, 50*0.5), 124 | (4.0*3600, 50*0.5), 125 | (3.8*3600, 50*0.6), 126 | (6.0*3600, 50*0.25), 127 | (4.0*3600, 50*0.51), 128 | (4.0*3600, 50*0.51), 129 | (3.5*3600, 50*0.6)]), 130 | ('y2_0', [(3.1*3600, 50*0.55), 131 | (3.0*3600, 50*0.6), 132 | (3.0*3600, 50*0.6), 133 | (3.0*3600, 50*0.6), 134 | (6.8*3600, 50*0.1), 135 | (6.8*3600, 50*0.1), 136 | (6.8*3600, 50*0.1), 137 | (6.8*3600, 50*0.1), 138 | (7.0*3600, 50*0.11), 139 | (7.0*3600, 50*0.11), 140 | (7.0*3600, 50*0.11), 141 | (7.0*3600, 50*0.11), 142 | (7.2*3600, 50*0.08), 143 | (7.2*3600, 50*0.08), 144 | (7.2*3600, 50*0.08), 145 | (7.2*3600, 50*0.08)]), 146 | ('y2_1', [(7.0*3600, 50*0.10), 147 | (7.0*3600, 50*0.10), 148 | (7.0*3600, 50*0.10), 149 | (7.0*3600, 50*0.10), 150 | (2.0*3600, 50*0.75), 151 | (2.0*3600, 50*0.75), 152 | (2.0*3600, 50*0.75), 153 | (2.0*3600, 50*0.75), 154 | (1.8*3600, 50*0.8), 155 | (1.8*3600, 50*0.8), 156 | (1.8*3600, 50*0.8), 157 | (1.8*3600, 50*0.8), 158 | (2.0*3600, 50*0.8), 159 | (2.0*3600, 50*0.8), 160 | (2.0*3600, 50*0.8), 161 | (2.0*3600, 50*0.8), 162 | (1.5*3600, 50*0.85), 163 | (1.5*3600, 50*0.85), 164 | (1.5*3600, 50*0.85), 165 | (1.5*3600, 50*0.85)])] 166 | 167 | for (rep, results) in litr: 168 | for (sim, arg, res) in zip(sims, simargs, results): 169 | pilstring = template(None) 170 | simulation = sim 171 | reporter = rep 172 | metric = 'diagonal-crossing-time' 173 | tmax = '36000' 174 | cmax = '50' 175 | current.add_system_simulation_setup(pilstring, simulation, reporter, metric, ':'.join([tmax, cmax]), res, simargs=rep + '-' + arg) 176 | 177 | current.pepperargs['default'] = current.pepperargs['CONDENSED'].copy() 178 | #current.pepperargs['default'].update(rates) 179 | current.pepperargs['default'].update(seesaw_off) 180 | if evaluate: 181 | current.eval() 182 | 183 | if verbose: 184 | for df in current.get_dataframes(): 185 | print(df) 186 | 187 | return [SF31] 188 | 189 | if __name__ == '__main__': 190 | data(evaluate=True, verbose=1) 191 | 192 | 193 | -------------------------------------------------------------------------------- /case_studies/yin2008.py: -------------------------------------------------------------------------------- 1 | 2 | def yin2008_F3_pil(x): 3 | return """ 4 | length a = 6 5 | length b = 6 6 | length c = 6 7 | length d = 6 8 | length u = 6 9 | length v = 6 10 | length x = 6 11 | length y = 6 12 | 13 | # Initially present 14 | I = a* x* v* b* y* 15 | A = x*( v*( b*( y*( u* c* a* x* ) ) ) ) a 16 | B = v* d* y*( u*( c*( a*( x*( v* b* y* ) ) ) ) ) b 17 | C = c u( y( d( v( u* c* a* x* ) ) ) ) 18 | D = d v( x( a( c( u( v* d* y* ) ) ) ) ) b* y* 19 | 20 | # Not initially present 21 | IA = a*( x*( v*( b*( y*( + x* v* b* y* u* c* a* x* ) ) ) ) ) @i 0 M 22 | AB = v* d* y* u* c* a*( x*( v*( b*( y*( x( a( c( u( y( b( + x* v* ) ) ) ) ) ) ) ) ) ) ) @i 0 M 23 | ABC = c( u( y( d( v( u* c* a* x* v* d* y* u* + ) ) ) ) ) a*( x*( v*( b*( y*( x( a( c( u( y( b( + x* v* ) ) ) ) ) ) ) ) ) ) ) @i 0 M 24 | CDB = c( u( y( d( v( u*( c*( a*( x*( v*( d*( y* u* + ) ) ) ) ) ) ) ) ) ) ) a* x* v* b*( y*( + v* d* y* u*( c*( a*( x*( v* b* y* ) ) ) ) ) ) @i 0 M 25 | CD = c( u( y( d( v( u*( c*( a*( x*( v*( d*( y* u* + ) ) ) ) ) ) ) ) ) ) ) a* x* v* b* y* @i 0 M 26 | CDA = c( u( y( d( v( u*( c*( a*( x*( v*( d*( y* u* + ) ) ) ) ) ) ) ) ) ) ) a*( x*( v*( b*( y*( + x* v* b* y* u* c* a* x* ) ) ) ) ) @i 0 M 27 | 28 | """.format(x) 29 | 30 | def data(evaluate=False, verbose = 0): 31 | from figure_analysis import FigureData 32 | 33 | # Default pilsimulator call 34 | psim = "pilsimulator --no-jacobian --nxy --header --atol 1e-10 --rtol 1e-10 --mxstep 10000 --t8 18000 --t-lin 18000" 35 | rates = {'k_slow': 1e-5, 'k_fast': 0.1} 36 | 37 | # Setup 38 | F3 = FigureData('Yin et al. (2008) Fig. 3 - Autocatalytic hairpin system (varying initiator)') 39 | F3.fname = 'Yin2008-F3' 40 | current = F3 41 | template = yin2008_F3_pil 42 | sims = [psim + ' --pyplot-labels A B C D I --p0 A=20 B=20 C=20 D=20 I=20', 43 | psim + ' --pyplot-labels A B C D I --p0 A=20 B=20 C=20 D=20 I=6', 44 | psim + ' --pyplot-labels A B C D I --p0 A=20 B=20 C=20 D=20 I=2', 45 | psim + ' --pyplot-labels A B C D I --p0 A=20 B=20 C=20 D=20 I=1', 46 | psim + ' --pyplot-labels A B C D I --p0 A=20 B=20 C=20 D=20 I=0.6', 47 | psim + ' --pyplot-labels A B C D I --p0 A=20 B=20 C=20 D=20 I=0.4', 48 | psim + ' --pyplot-labels A B C D I --p0 A=20 B=20 C=20 D=20 I=0.2', 49 | psim + ' --pyplot-labels A B C D I --p0 A=20 B=20 C=20 D=20 I=0.1', 50 | psim + ' --pyplot-labels A B C D I --p0 A=20 B=20 C=20 D=20 I=0.06', 51 | psim + ' --pyplot-labels A B C D I --p0 A=20 B=20 C=20 D=20 I=0.02', 52 | psim + ' --pyplot-labels A B C D I --p0 A=20 B=20 C=20 D=20 I=0.01'] 53 | #psim + ' --pyplot-labels A B C D I --p0 A=20 B=20 C=20 D=20 I=0'] 54 | 55 | # Diagonal crossing 56 | diagX = [ 57 | (297.38, 3.30), 58 | (2256.56, 5.23), 59 | (4411.66, 7.37), 60 | (5811.08, 8.72), 61 | (6930.61, 9.83), 62 | (7546.36, 10.45), 63 | (8302.04, 11.17), 64 | (8973.76, 11.76), 65 | (9281.63, 12.11), 66 | (9561.52, 12.38), 67 | (9701.46, 12.52), 68 | (9841.40, 12.66)] 69 | 70 | for (sim, res) in zip(sims, diagX): 71 | pilstring = template(None) 72 | simulation = sim 73 | reporter = 'A' 74 | metric = 'diagonal-crossing-time' 75 | tmax = '18000' 76 | cmax = '2;-20' 77 | current.add_system_simulation_setup(pilstring, simulation, reporter, metric, ':'.join([tmax, cmax]), res, simargs=sim[sim.find('I='):]) 78 | 79 | 80 | # Half completion 81 | halfC = [ 82 | (45.48, -10.00), 83 | (1067.06, -10.00), 84 | (3488.05, -10.00), 85 | (5321.28, -10.00), 86 | (6874.64, -10.00), 87 | (7700.29, -10.00), 88 | (8847.81, -10.00), 89 | (9729.45, -10.00), 90 | (10247.23, -10.00), 91 | (10681.05, -10.00), 92 | (10876.97, -10.00), 93 | (11086.88, -10.00)] 94 | 95 | for (sim, res) in zip(sims, halfC): 96 | pilstring = template(None) 97 | simulation = sim 98 | reporter = 'A' 99 | metric = 'completion-time' 100 | current.add_system_simulation_setup(pilstring, simulation, reporter, metric, '-10', res, simargs=sim[sim.find('I='):]) 101 | 102 | current.pepperargs['default'] = current.pepperargs['condensed'].copy() 103 | current.pepperargs['default'].update(rates) 104 | 105 | if evaluate: 106 | current.eval() 107 | 108 | if verbose: 109 | for df in current.get_dataframes(): 110 | print(df) 111 | 112 | return [F3] 113 | 114 | if __name__ == '__main__': 115 | data(evaluate=True, verbose=1) 116 | 117 | 118 | 119 | -------------------------------------------------------------------------------- /case_studies/zhang2007.py: -------------------------------------------------------------------------------- 1 | 2 | def zhang2007_F1_pil(x): 3 | return """ 4 | # Domains 5 | length d1 = 10 6 | length d2a = 6 7 | length d2b = 6 8 | length d2c = 12 9 | length d3 = 4 10 | length d4 = 16 11 | length d5 = 6 12 | length d6 = 16 13 | 14 | # Species 15 | C = d4 d5 16 | OB = d1 d2a d2b d2c 17 | ROX = d1 d2a 18 | S = d1 d2a( d2b( d2c( + d6 d3( d4( + d5* ) ) ) ) ) 19 | F = d2a d2b d2c d3 d4 # fuel 20 | OR = d1( d2a( + d2b* ) ) 21 | SB = d6 d3 d4 22 | 23 | I1 = d1 d2a( d2b( d2c( + d6 d3( d4( + d4 d5( + ) ) ) ) ) ) 24 | I2 = d1 d2a( d2b( d2c( + d6 d3( d4 + d4( d5( + ) ) ) ) ) ) 25 | I3 = d1 d2a( d2b( d2c( + d4( d5( + ) ) d3* ) ) ) 26 | I4 = d1 d2a( d2b( d2c( + d2a d2b d2c d3( d4 + d4( d5( + ) ) ) ) ) ) 27 | I4a = d1 d2a( d2b( d2c( + d2a d2b d2c d3( d4( + d4 d5( + ) ) ) ) ) ) 28 | I5 = d2a( d2b( d2c( d3( d4 + d4( d5( + ) ) ) ) ) ) 29 | W = d2a( d2b( d2c( d3( d4( + d5* ) ) ) ) ) 30 | RQ = d1( d2a( d2b( d2c + ) ) ) 31 | """.format(x) 32 | 33 | def zhang2007_F3_pil(x): 34 | return """ 35 | # Domains 36 | length d1 = 10 37 | length d2a = 6 38 | length d2b = 6 39 | length d2c = 12 40 | length d3 = 4 41 | length d4a = 10 42 | length d4b = 6 # = 2a 43 | length d5 = 6 # = 2b 44 | length d6 = 16 45 | length d7 = 12 46 | length d8 = 4 47 | length d9 = 16 48 | length d10 = 6 # = 2b 49 | 50 | # Species 51 | F0 = d4b d5 d7 d8 d9 52 | S0 = d4a d4b( d5( d7( + d8( d9( + d10* ) ) ) ) ) 53 | OB0 = d4a d4b d5 d7 54 | C0 = d9 d10 55 | 56 | F1 = d2a d2b d2c d3 d4a d4b 57 | S1 = d1 d2a( d2b( d2c( + d6 d3( d4a( d4b( + d5* ) ) ) ) ) ) 58 | OB1 = d1 d2a d2b d2c 59 | 60 | OR = d1( d2a( + d2b* ) ) 61 | ROX = d1 d2a 62 | RQ = d1( d2a( d2b( d2c + ) ) ) 63 | """.format(x) 64 | 65 | def zhang2007_F4_pil(x): 66 | return """ 67 | # Domains 68 | length d2b = 6 69 | length d2c = 12 70 | length d3 = 4 71 | length d4t = 7 72 | length d4a = 3 73 | length d4b = 6 74 | length d6 = 16 75 | 76 | # Species 77 | A = d4t d4a d4b d2b d2c 78 | SB = d6 d3 d4t d4a d4b 79 | TET = d6 d3 80 | I = d4t d4a d4b( d2b( d2c( + d4t( d4a( d4b( d2b( d2c + ) ) ) ) d3* ) ) ) 81 | 82 | S = d4t d4a d4b( d2b( d2c( + d6 d3( d4t( d4a( d4b( + d2b* ) ) ) ) ) ) ) 83 | SR = d6( d3( + d4t* ) ) 84 | F = d4b d2b d2c d3 d4t d4a d4b 85 | 86 | W = d4b( d2b( d2c( d3( d4t( d4a( d4b( + d2b* ) ) ) ) ) ) ) 87 | 88 | FQ = d6( d3( d4t( d4a d4b + ) ) ) 89 | """.format(x) 90 | 91 | def data(evaluate=False, verbose = 0): 92 | from figure_analysis import FigureData 93 | 94 | # Default pilsimulator call 95 | psim = "pilsimulator --nxy --header --atol 1e-13 --rtol 1e-13 --mxstep 10000" 96 | psim += " --t8 18000 --t-lin 18000" 97 | 98 | # Setup 99 | F1E = FigureData('Zhang et al. (2007) Fig. 1 - Single-layer catalytic DSD system (varying catalyst)') 100 | F1E.fname = 'Zhang2007-F1' 101 | current = F1E 102 | template = zhang2007_F1_pil 103 | sims = [psim + ' --pyplot-labels ROX S F OR C --p0 S=10 F=13 OR=30 C=10', 104 | psim + ' --pyplot-labels ROX S F OR C --p0 S=10 F=13 OR=30 C=5', 105 | psim + ' --pyplot-labels ROX S F OR C --p0 S=10 F=13 OR=30 C=2', 106 | psim + ' --pyplot-labels ROX S F OR C --p0 S=10 F=13 OR=30 C=1', 107 | psim + ' --pyplot-labels ROX S F OR C --p0 S=10 F=13 OR=30 C=0.5', 108 | psim + ' --pyplot-labels ROX S F OR C --p0 S=10 F=13 OR=30 C=0.2', 109 | psim + ' --pyplot-labels ROX S F OR C --p0 S=10 F=13 OR=30 C=0.1', 110 | psim + ' --pyplot-labels ROX S F OR C --p0 S=10 F=13 OR=30 C=0.05', 111 | psim + ' --pyplot-labels ROX S F OR C --p0 S=10 F=13 OR=30 C=0.02'] 112 | 113 | # DIAGONAL CROSSING 114 | diagX = [ 115 | (1216.44, 7.44), 116 | (1660.27, 6.83), 117 | (2457.53, 5.78), 118 | (3435.62, 4.49), 119 | (4364.38, 3.26), 120 | (5424.66, 1.88), 121 | (6073.97, 1.03), 122 | (6386.30, 0.57), 123 | (6550.68, 0.32)] 124 | #(6715.07, 0.09) 0 input 125 | 126 | for (sim, res) in zip(sims, diagX): 127 | pilstring = template(None) 128 | simulation = sim 129 | reporter = 'ROX' 130 | metric = 'diagonal-crossing-time' 131 | tmax = '7200' 132 | cmax = '10' 133 | current.add_system_simulation_setup(pilstring, simulation, reporter, metric, ':'.join([tmax, cmax]), res, simargs=sim[sim.find('C='):]) 134 | 135 | # Half completion 136 | halfC = [ 137 | (550.68, 5.00), 138 | (953.42, 5.00), 139 | (1906.85, 5.00), 140 | (4076.71, 5.00)] 141 | 142 | for (sim, res) in zip(sims, halfC): 143 | pilstring = template(None) 144 | simulation = sim 145 | reporter = 'ROX' 146 | metric = 'completion-time' 147 | current.add_system_simulation_setup(pilstring, simulation, reporter, metric, '5', res, simargs=sim[sim.find('C='):]) 148 | 149 | current.pepperargs['default'] = current.pepperargs['Condensed'].copy() 150 | 151 | if evaluate: 152 | current.eval() 153 | 154 | if verbose: 155 | for df in current.get_dataframes(): 156 | print(df) 157 | 158 | # Setup 159 | F3 = FigureData('Zhang et al. (2007) Fig. 3 - Two-layer feedforward DSD system (varying catalyst)') 160 | F3.fname = 'Zhang2007-F3' 161 | current = F3 162 | template = zhang2007_F3_pil 163 | sims = [psim + ' --pyplot-labels ROX S0 S1 F0 F1 OR C0 --p0 S1=10 F1=13 S0=10 F0=13 OR=30 C0=10', 164 | psim + ' --pyplot-labels ROX S0 S1 F0 F1 OR C0 --p0 S1=10 F1=13 S0=10 F0=13 OR=30 C0=5', 165 | psim + ' --pyplot-labels ROX S0 S1 F0 F1 OR C0 --p0 S1=10 F1=13 S0=10 F0=13 OR=30 C0=2', 166 | psim + ' --pyplot-labels ROX S0 S1 F0 F1 OR C0 --p0 S1=10 F1=13 S0=10 F0=13 OR=30 C0=1', 167 | psim + ' --pyplot-labels ROX S0 S1 F0 F1 OR C0 --p0 S1=10 F1=13 S0=10 F0=13 OR=30 C0=0.5', 168 | psim + ' --pyplot-labels ROX S0 S1 F0 F1 OR C0 --p0 S1=10 F1=13 S0=10 F0=13 OR=30 C0=0.2', 169 | psim + ' --pyplot-labels ROX S0 S1 F0 F1 OR C0 --p0 S1=10 F1=13 S0=10 F0=13 OR=30 C0=0.1', 170 | psim + ' --pyplot-labels ROX S0 S1 F0 F1 OR C0 --p0 S1=10 F1=13 S0=10 F0=13 OR=30 C0=0.05', 171 | psim + ' --pyplot-labels ROX S0 S1 F0 F1 OR C0 --p0 S1=10 F1=13 S0=10 F0=13 OR=30 C0=0.02', 172 | psim + ' --pyplot-labels ROX S0 S1 F0 F1 OR C0 --p0 S1=10 F1=13 S0=10 F0=13 OR=30 C0=0.01'] 173 | 174 | #Diagonal Dataset 175 | diagX = [ 176 | (1860.53, 6.56), 177 | (2302.30, 5.98), 178 | (2744.07, 5.40), 179 | (3066.90, 4.98), 180 | (3856.99, 3.92), 181 | (4519.65, 3.07), 182 | (4910.44, 2.54), 183 | (5607.08, 1.63), 184 | (5904.42, 1.23), 185 | (6065.84, 1.02)] 186 | #(6320.71, 0.66), # 0x 187 | #(6720.00, 0.15)] # control 188 | 189 | for (sim, res) in zip(sims, diagX): 190 | pilstring = template(None) 191 | simulation = sim 192 | reporter = 'ROX' 193 | metric = 'diagonal-crossing-time' 194 | tmax = '7200' 195 | cmax = '10' 196 | current.add_system_simulation_setup(pilstring, simulation, reporter, metric, ':'.join([tmax, cmax]), res, simargs=sim[sim.find('C0='):]) 197 | 198 | 199 | # Half completion 200 | halfC = [ 201 | (1257.35, 5.00), 202 | (1852.04, 5.00), 203 | (2514.69, 5.00), 204 | (3066.90, 5.00), 205 | (4850.97, 5.00)] 206 | 207 | for (sim, res) in zip(sims, halfC): 208 | pilstring = template(None) 209 | simulation = sim 210 | reporter = 'ROX' 211 | metric = 'completion-time' 212 | current.add_system_simulation_setup(pilstring, simulation, reporter, metric, '5', res, simargs=sim[sim.find('C0='):]) 213 | 214 | current.pepperargs['default'] = current.pepperargs['Condensed'].copy() 215 | 216 | if evaluate: 217 | current.eval() 218 | 219 | if verbose: 220 | for df in current.get_dataframes(): 221 | print(df) 222 | 223 | # Setup 224 | F4 = FigureData('Zhang et al. (2007) Fig. 4 - Autocatalytic DSD system (varying autocatalyst)') 225 | F4.fname = 'Zhang2007-F4' 226 | current = F4 227 | template = zhang2007_F4_pil 228 | sims = [psim + ' --pyplot-labels TET S F SR A --p0 S=10 F=13 SR=20 A=10', 229 | psim + ' --pyplot-labels TET S F SR A --p0 S=10 F=13 SR=20 A=7', 230 | psim + ' --pyplot-labels TET S F SR A --p0 S=10 F=13 SR=20 A=5', 231 | psim + ' --pyplot-labels TET S F SR A --p0 S=10 F=13 SR=20 A=3', 232 | psim + ' --pyplot-labels TET S F SR A --p0 S=10 F=13 SR=20 A=2', 233 | psim + ' --pyplot-labels TET S F SR A --p0 S=10 F=13 SR=20 A=1', 234 | psim + ' --pyplot-labels TET S F SR A --p0 S=10 F=13 SR=20 A=0.7', 235 | psim + ' --pyplot-labels TET S F SR A --p0 S=10 F=13 SR=20 A=0.5', 236 | psim + ' --pyplot-labels TET S F SR A --p0 S=10 F=13 SR=20 A=0.3', 237 | psim + ' --pyplot-labels TET S F SR A --p0 S=10 F=13 SR=20 A=0.2', 238 | psim + ' --pyplot-labels TET S F SR A --p0 S=10 F=13 SR=20 A=0.1'] 239 | 240 | #Diagonal Dataset 241 | diagX = [ 242 | (496.08, 7.62), 243 | (600.76, 7.32), 244 | (655.37, 7.16), 245 | (855.63, 6.61), 246 | (910.24, 6.45), 247 | (1064.98, 6.04), 248 | (1206.07, 5.64), 249 | (1237.93, 5.54), 250 | (1333.50, 5.26), 251 | (1392.67, 5.10), 252 | (1465.49, 4.91)] 253 | #(1756.76, 4.10)] 254 | 255 | for (sim, res) in zip(sims, diagX): 256 | pilstring = template(None) 257 | simulation = sim 258 | reporter = 'TET' 259 | metric = 'diagonal-crossing-time' 260 | tmax = '3600' 261 | cmax = '10' 262 | current.add_system_simulation_setup(pilstring, simulation, reporter, metric, ':'.join([tmax, cmax]), res, simargs=sim[sim.find('A='):]) 263 | 264 | #Half completion 265 | halfC = [ 266 | (241.21, 5.0), 267 | (350.44, 5.0), 268 | (393.68, 5.0), 269 | (609.86, 5.0), 270 | (694.06, 5.0), 271 | (892.04, 5.0), 272 | (1087.74, 5.0), 273 | (1121.87, 5.0), 274 | (1276.61, 5.0), 275 | (1376.74, 5.0), 276 | (1470.04, 5.0)] 277 | #(1966.12, 5.0)] 278 | 279 | for (sim, res) in zip(sims, halfC): 280 | pilstring = template(None) 281 | simulation = sim 282 | reporter = 'TET' 283 | metric = 'completion-time' 284 | current.add_system_simulation_setup(pilstring, simulation, reporter, metric, '5', res, simargs=sim[sim.find('A='):]) 285 | 286 | current.pepperargs['default'] = current.pepperargs['Condensed'].copy() 287 | 288 | if evaluate: 289 | current.eval() 290 | 291 | if verbose: 292 | for df in current.get_dataframes(): 293 | print(df) 294 | 295 | 296 | return [F1E, F3, F4] 297 | 298 | if __name__ == '__main__': 299 | data(evaluate=True, verbose=1) 300 | 301 | 302 | -------------------------------------------------------------------------------- /case_studies/zhang2009.py: -------------------------------------------------------------------------------- 1 | def zhang2009_F1DF_exchange_pil(mandn) : 2 | (m,n) = mandn 3 | assert m != 0 4 | assert n != 0 5 | return """ 6 | # Experiments Zhang 2009, 3-way strand displacement toehold exchange 7 | 8 | # For the reporter, assuming that beta^6 is actually beta^m, and then there 9 | # is a 7nt reporter toehold section (br) after bt... not pretty, but 10 | # should work just fine... 11 | 12 | length a = 16 13 | length bt = {:d} # m 14 | length br = 7 # 7 15 | length b = {:d} # 13 - m 16 | length ct = {:d} # n 17 | length c = {:d} # 15 - n 18 | 19 | X = br b ct 20 | S = a bt( br( b( + c* ct* ) ) ) 21 | 22 | I = a bt( br( b( + br b ct( + c* ) ) ) ) 23 | J = a bt( br b + br( b( ct( + c* ) ) ) ) 24 | 25 | Y = a bt br b 26 | L = br( b( ct( + c* ) ) ) bt* 27 | 28 | 29 | R = a( bt( + br* ) ) 30 | V = a( bt( br( b + ) ) ) 31 | F = a bt 32 | """.format(m, 13-m, n, 15-n) 33 | 34 | def zhang2009_F1DF_displacement_pil(n) : 35 | (n) = n 36 | assert n != 0 37 | return """ 38 | # Toehold mediated strand displacement (no exchange) 39 | 40 | length a = 16 41 | length b6 = 6 42 | length br = 7 43 | length b = 7 44 | length ct = {:d} # n 45 | length c = {:d} # 15 - n 46 | 47 | X = b6 br b ct 48 | S = a b6( br( b( + c* ct* ) ) ) 49 | 50 | I = a b6( br( b( + br b ct( + c* ) ) ) ) 51 | J = a b6( br b + br( b( ct( + c* ) ) ) ) 52 | 53 | Y = a b6 br b 54 | L = b6( br( b( ct( + c* ) ) ) ) 55 | 56 | 57 | R = a( b6( + br* ) ) 58 | V = a( b6( br( b + ) ) ) 59 | F = a b6 60 | """.format(n, 15-n) 61 | 62 | def zhang2009_F5_pil(n): 63 | (n) = n 64 | return """ 65 | # Domains 66 | length a = 16 67 | length bm = 5 # m 68 | length br = 1 # m 69 | length bc = 7 70 | length bt = 7 71 | length n = {} # n 72 | length c = {} # 15-n 73 | 74 | # Species 75 | S = a bm( br( bc( bt( + c* n* ) ) ) ) 76 | X = br bc bt n 77 | L = br( bc( bt( n( + c* ) ) ) ) bm* 78 | Y = a bm br bc bt 79 | Z = bm br bc bt 80 | W = bm( br( bc( bt( + c* n* ) ) ) ) 81 | 82 | R = a( bm( br( + bc* ) ) ) 83 | YW = a( bm( br( bc( bt + ) ) ) ) 84 | F = a bm br 85 | """.format(n, 15-n) 86 | 87 | 88 | def data(evaluate=False, verbose = 0): 89 | from figure_analysis import FigureData 90 | 91 | # Default pilsimulator call 92 | psim = "pilsimulator --no-jacobian --nxy --header" 93 | psim += " --atol 1e-12 --rtol 1e-12 --mxstep 1000" 94 | psim += " --t8 18000 --t-lin 18000" 95 | 96 | rates = {'k_slow': 1e-5, 'k_fast': 0.1} 97 | rc = {'release_cutoff': 15} 98 | 99 | # Setup 100 | F3 = FigureData('Zhang & Winfree (2009) Fig. 3 - Single strand displacement reactions (varying toehold length)') 101 | F3.fname = 'Zhang2009-F3' 102 | current = F3 103 | template = zhang2009_F1DF_displacement_pil 104 | sims = [psim + ' --pyplot-labels F R S X --p0 R=3 S=1 X=0.6', 105 | psim + ' --pyplot-labels F R S X --p0 R=3 S=1 X=0.4', 106 | psim + ' --pyplot-labels F R S X --p0 R=3 S=1 X=0.2'] 107 | diagX = [(1260, 0.31), (1867, 0.27), (3498, 0.17)] 108 | 109 | for (sim, res) in zip(sims, diagX): 110 | pilstring = template(5) 111 | simulation = sim 112 | reporter = 'F' 113 | metric = 'diagonal-crossing-time' 114 | tmax = '7200' 115 | cmax = '0.4' 116 | current.add_system_simulation_setup(pilstring, simulation, reporter, metric, 117 | ':'.join([tmax, cmax]), res, simargs=sim[sim.find('X='):]) 118 | 119 | # Half completion 120 | halfC = [(1241.01, 0.30), (2430.95, 0.30)] 121 | 122 | for (sim, res) in zip(sims, halfC): 123 | pilstring = template(5) 124 | simulation = sim 125 | reporter = 'F' 126 | metric = 'completion-time' 127 | current.add_system_simulation_setup(pilstring, simulation, reporter, metric, '0.3', 128 | res, simargs=sim[sim.find('X='):]) 129 | 130 | current.pepperargs['default'] = current.pepperargs['condensed'].copy() 131 | 132 | if evaluate: 133 | current.eval() 134 | 135 | if verbose: 136 | for df in current.get_dataframes(): 137 | print(df) 138 | 139 | # Setup 140 | F4 = FigureData('Zhang & Winfree (2009) Fig. 4 - Single toehold exchange reactions (varying toehold lengths)') 141 | F4.fname = 'Zhang2009-F4' 142 | current = F4 143 | template = zhang2009_F1DF_exchange_pil 144 | pilp = [(4,7), (5,7), (6,7), (7,7)] 145 | 146 | halfC = [ 147 | (527.64, 0.20), 148 | (578.28, 0.20), 149 | (983.36, 0.20), 150 | (1877.93, 0.20)] 151 | 152 | for (pip, res) in zip(pilp, halfC): 153 | pilstring = template(pip) 154 | simulation = psim + ' --pyplot-labels F R S X --p0 R=3 S=1 X=0.4' 155 | reporter = 'F' 156 | metric = 'completion-time' 157 | current.add_system_simulation_setup(pilstring, simulation, reporter, metric, '0.2', 158 | res, simargs=sim[sim.find('X='):]) 159 | 160 | diagX = [(785, 0.28), (823, 0.27), (1192, 0.23), (1622, 0.18)] 161 | 162 | for (pip, res) in zip(pilp, diagX): 163 | pilstring = template(pip) 164 | simulation = psim + ' --pyplot-labels F R S X --p0 R=3 S=1 X=0.4' 165 | reporter = 'F' 166 | metric = 'diagonal-crossing-time' 167 | tmax = '3600' 168 | cmax = '0.4' 169 | current.add_system_simulation_setup(pilstring, simulation, reporter, metric, 170 | ':'.join([tmax, cmax]), res, simargs=sim[sim.find('X='):]) 171 | 172 | current.pepperargs['default'] = current.pepperargs['condensed'].copy() 173 | 174 | if evaluate: 175 | current.eval() 176 | 177 | if verbose: 178 | for df in current.get_dataframes(): 179 | print(df) 180 | 181 | # Setup 182 | F5 = FigureData('Zhang & Winfree (2009) Fig. 5 - Catalytic DSD system (varying toehold lengths)') 183 | F5.fname = 'Zhang2009-F5' 184 | current = F5 185 | template = zhang2009_F5_pil 186 | pilp = [6,7,5,8,4,9,3,2] 187 | 188 | diagX = [ 189 | (2825.85, 7.53), 190 | (3485.78, 7.09), 191 | (4737.96, 6.19), 192 | (9103.64, 3.20), 193 | (10728.08, 2.08), 194 | (11269.57, 1.71), 195 | (13300.12, 0.30), 196 | (13672.39, 0.08)] 197 | 198 | for (pip, res) in zip(pilp, diagX): 199 | pilstring = template(pip) 200 | simulation = psim + ' --pyplot-labels F R S Z X --p0 R=30 S=10 Z=100 X=1' 201 | reporter = 'F' 202 | metric = 'diagonal-crossing-time' 203 | tmax = '14400' 204 | cmax = '10' 205 | current.add_system_simulation_setup(pilstring, simulation, reporter, metric, 206 | ':'.join([tmax, cmax]), res, simargs=sim[sim.find('X='):]) 207 | 208 | 209 | halfC = [ (1066.04, 5.01), (1472.15, 5.01), (3096.59, 5.01)] 210 | 211 | for (pip, res) in zip(pilp, halfC): 212 | pilstring = template(pip) 213 | simulation = psim + ' --pyplot-labels F R S Z X --p0 R=30 S=10 Z=100 X=1' 214 | reporter = 'F' 215 | metric = 'completion-time' 216 | current.add_system_simulation_setup(pilstring, simulation, reporter, metric, '5.01', 217 | res, simargs=sim[sim.find('X='):]) 218 | 219 | 220 | current.pepperargs['default'] = current.pepperargs['condensed'].copy() 221 | 222 | if evaluate: 223 | current.eval() 224 | 225 | if verbose: 226 | for df in current.get_dataframes(): 227 | print(df) 228 | 229 | return [F3, F4, F5] 230 | #return [F5] 231 | 232 | if __name__ == '__main__': 233 | data(evaluate=True, verbose=1) 234 | 235 | 236 | 237 | -------------------------------------------------------------------------------- /case_studies/zhang2009_rates.py: -------------------------------------------------------------------------------- 1 | 2 | def zhang2009_3way_displacement(cd): 3 | (c,d) = cd 4 | if c == 0 : # special leak case 5 | raise NotImplementedError() 6 | return """# Experiments Zhang 2009, 3-way strand displacement 7 | \rlength a = 16 8 | \rlength b1 = 6 9 | \rlength b2 = 7 10 | \rlength b3 = 7 11 | \rlength c = {:d} # c 12 | \r{}length d = {:d} # d 13 | 14 | \r# Chopped sequence for reporter reaction. 15 | \rsup-sequence b = b1 b2 b3 16 | 17 | \r# Inputs 18 | \rX = b c 19 | \rS = a b( + {} c* ) 20 | \rR = a( b1( + b2* ) ) 21 | 22 | \r# Outputs 23 | \rL = b( c( + {} ) ) @initial 0 M 24 | \rY = a b @initial 0 M 25 | \rF = a b1 @initial 0 M 26 | \rW = a( b1( b2( b3 + ) ) ) @initial 0 M 27 | 28 | \r# Intermediates 29 | \ri1 = a b( + b c( + {} ) ) @initial 0 M 30 | 31 | \r# Expected detailed reactions: 32 | \r# X + S <=> i1 33 | \r# i1 -> L + Y 34 | \r# Target condensed reactions: 35 | \r# X + S -> L + Y 36 | \r# R + Y -> F + W 37 | \r""".format(c, 38 | '#' if d==0 else '', d, 39 | '' if d==0 else 'd*', 40 | '' if d==0 else 'd*', 41 | '' if d==0 else 'd*') 42 | 43 | def zhang2009_3way_exchange(nm): 44 | (n,m) = nm 45 | return """# Experiments Zhang 2009, 3-way strand displacement toehold exchange 46 | \rlength A = 16 47 | \rlength b = {:d} # m 48 | \rlength B = {:d} # 20 - m 49 | \rlength c = {:d} # n 50 | \rlength D = {:d} # 15 - n 51 | 52 | \rS = A b( B( + D* c* ) ) 53 | \rX = B c 54 | 55 | \ri1 = A b( B( + B c( + D* ) ) ) @initial 0 M 56 | \ri2 = A b( B + B( c( + D* ) ) ) @initial 0 M 57 | \rL = B( c( + D* ) ) b* @initial 0 M 58 | \rY = A b B @initial 0 M 59 | 60 | \r# potential reactions: 61 | \r# inv + clx -> i1 62 | \r# i1 -> inv + clx 63 | \r# i1 -> i2 64 | \r# i2 -> i1 65 | \r# i2 -> i3 + i4 66 | \r# i3 + i4 -> i2 67 | \r""".format(m, 20-m, n, 15-n) 68 | 69 | def data(evaluate=False, verbose = 0): 70 | from figure_analysis import FigureData 71 | 72 | # Setup Experiment 1 73 | z09_3way = FigureData('Zhang and Winfree (2009)\n3-way strand displacement') 74 | z09_3way.fname = 'Zhang2009-3way' 75 | current = z09_3way 76 | 77 | k3way_exp = [ 78 | #((n, m), k) 79 | #((0, 15), 1.40), 80 | ((1, 14), 8.17), 81 | ((2, 13), 144), 82 | ((3, 12), 1.08e3), 83 | ((4, 11), 5.05e4), 84 | ((5, 10), 9.64e5), 85 | ((6, 9), 2.36e6), 86 | ((7, 8), 3.22e6), 87 | ((8, 9), 3.15e6), 88 | ((9, 8), 2.77e6), 89 | ((10, 7), 2.83e6), 90 | ((15, 0), 4.78e6)] 91 | 92 | for (pil, rate) in k3way_exp: 93 | pilstring = zhang2009_3way_displacement(pil) 94 | exp_result = 'X + S -> Y + L [k={}]'.format(rate) 95 | current.add_reaction_rate_setup(pilstring, exp_result, pil) 96 | 97 | current.pepperargs['default'] = current.pepperargs['condensed'].copy() 98 | if evaluate: 99 | current.eval() 100 | 101 | if verbose: 102 | for df in current.get_dataframes(): 103 | print(df) 104 | 105 | # Setup Experiment 2 106 | z09_3wayX = FigureData('Zhang and Winfree (2009)\n3-way toehold exchange') 107 | z09_3wayX.fname = 'Zhang2009-3wayX' 108 | current = z09_3wayX 109 | 110 | k3wayX_exp = [ 111 | ((1, 4), 7.70), ((1, 3), 5.48), ((1, 2), 23.5), ((1, 1), 18.9), 112 | ((2, 5), 43.6), ((2, 4), 214.05), ((2, 3), 273.0), ((2, 2), 249.0), ((2, 1), 231.0), 113 | ((3, 6), 66.9), ((3, 5), 215.0), ((3, 4), 939.0), ((3, 3), 974.0), ((3, 2), 907.0), ((3, 1), 846.0), 114 | ((4, 7), 131.0), ((4, 6), 407.0), ((4, 5), 4.25e3), ((4, 4), 2.13e4), ((4, 3), 2.41e4), ((4, 2), 2.29e4), ((4, 1), 1.97e4), 115 | ((5, 7), 3.59e3), ((5, 6), 9.72e4), ((5, 5), 3.45e5), ((5, 4), 1.53e6), ((5, 3), 1.58e6), ((5, 2), 1.58e6), ((5, 1), 1.73e6), 116 | ((6, 7), 1.61e5), ((6, 6), 4.05e5), ((6, 5), 1.48e6), ((6, 4), 3.04e6), ((6, 3), 2.59e6), ((6, 2), 3.00e6), 117 | ((7, 7), 4.7e5), ((7, 6), 1.11e6), ((7, 5), 2.90e6), ((7, 4), 3.57e6), 118 | ((8, 7), 1.94e6), ((8, 6), 2.68e6), ((8, 5), 3.14e6), ((8, 4), 3.37e6)] 119 | 120 | for (pil, rate) in k3wayX_exp: 121 | pilstring = zhang2009_3way_exchange(pil) 122 | exp_result = 'X + S -> Y + L [k={}]'.format(rate) 123 | current.add_reaction_rate_setup(pilstring, exp_result, pil) 124 | 125 | current.pepperargs['default'] = current.pepperargs['condensed'].copy() 126 | if evaluate: 127 | current.eval() 128 | 129 | if verbose: 130 | for df in current.get_dataframes(): 131 | print(df) 132 | 133 | return [z09_3way, z09_3wayX] 134 | 135 | if __name__ == '__main__': 136 | data() 137 | 138 | -------------------------------------------------------------------------------- /case_studies/zhang2010.py: -------------------------------------------------------------------------------- 1 | 2 | def zhang2007_F1_pil(x): 3 | return """ 4 | # Domains 5 | length d1 = 10 6 | length d2a = 6 7 | length d2b = 6 8 | length d2c = 12 9 | length d3 = 4 10 | length d4 = 16 11 | length d5 = 6 12 | length d6 = 16 13 | 14 | # Species 15 | C = d4 d5 16 | OB = d1 d2a d2b d2c 17 | ROX = d1 d2a 18 | S = d1 d2a( d2b( d2c( + d6 d3( d4( + d5* ) ) ) ) ) 19 | F = d2a d2b d2c d3 d4 # fuel 20 | OR = d1( d2a( + d2b* ) ) 21 | SB = d6 d3 d4 22 | 23 | I1 = d1 d2a( d2b( d2c( + d6 d3( d4( + d4 d5( + ) ) ) ) ) ) 24 | I2 = d1 d2a( d2b( d2c( + d6 d3( d4 + d4( d5( + ) ) ) ) ) ) 25 | I3 = d1 d2a( d2b( d2c( + d4( d5( + ) ) d3* ) ) ) 26 | I4 = d1 d2a( d2b( d2c( + d2a d2b d2c d3( d4 + d4( d5( + ) ) ) ) ) ) 27 | I4a = d1 d2a( d2b( d2c( + d2a d2b d2c d3( d4( + d4 d5( + ) ) ) ) ) ) 28 | I5 = d2a( d2b( d2c( d3( d4 + d4( d5( + ) ) ) ) ) ) 29 | W = d2a( d2b( d2c( d3( d4( + d5* ) ) ) ) ) 30 | RQ = d1( d2a( d2b( d2c + ) ) ) 31 | """.format(x) 32 | 33 | def zhang2010_F10A_pil(x): 34 | return """ 35 | # Domains 36 | length d41 = 16 37 | length d42a = 4 38 | length d42b = 7 39 | length d42c = 9 40 | length d43 = 5 41 | length d44 = 15 42 | length d45 = 8 43 | length d46 = 15 44 | 45 | F4 = d42a d42b d42c d43 d44 46 | S4 = d41 d42a( d42b( d42c( + d46 d43( d44( + d45* ) ) ) ) ) 47 | C4 = d44 d45 48 | 49 | W4 = d42a( d42b( d42c( d43( d44( + d45* ) ) ) ) ) 50 | OP4 = d41 d42a d42b d42c 51 | SP4 = d46 d43 d44 52 | 53 | RQ = d41( d42a( d42b( d42c + ) ) ) 54 | ROX = d41 d42a 55 | OR4 = d41( d42a( + d42b* ) ) 56 | """.format(x) 57 | 58 | def zhang2010_F10D_pil(x): 59 | return """ 60 | # Domains 61 | length d51 = 15 62 | length d52a = 5 63 | length d52b = 7 64 | length d52c = 10 65 | length d63 = 5 66 | length d64 = 11 67 | length d65 = 8 68 | length d66 = 10 69 | 70 | F43 = d52a d52b d52c d63 d64 71 | S43 = d51 d52a( d52b( d52c( + d66 d63( d64( + d65* ) ) ) ) ) 72 | C43 = d64 d65 73 | W43 = d52a( d52b( d52c( d63( d64( + d65* ) ) ) ) ) 74 | OP43 = d51 d52a d52b d52c 75 | SP43 = d66 d63 d64 76 | RQ = d51( d52a( d52b( d52c + ) ) ) 77 | RG = d51 d52a 78 | OR43 = d51( d52a( + d52b* ) ) 79 | """.format(x) 80 | 81 | def data(evaluate=False, verbose = 0): 82 | from figure_analysis import FigureData 83 | 84 | # Default pilsimulator call 85 | psim = "pilsimulator --no-jacobian --nxy --header" 86 | psim += " --atol 1e-10 --rtol 1e-10 --mxstep 1000" 87 | psim += " --t8 86500 --t-lin 86500" 88 | 89 | rates = {'k_slow': 1e-5, 'k_fast': 0.1} 90 | 91 | # Setup 92 | F3A = FigureData('Zhang & Winfree (2010) Fig. 3A - Catalytic DSD system with 100 nM substrates (varying catalyst)') 93 | F3A.fname = 'Zhang2010-F3A' 94 | current = F3A 95 | template = zhang2007_F1_pil 96 | sims = [psim + ' --pyplot-labels S F OR C ROX --p0 S=100 F=200 OR=300 C=10', 97 | psim + ' --pyplot-labels S F OR C ROX --p0 S=100 F=200 OR=300 C=1'] 98 | 99 | diagX = [(2557.53, 88.07), (11842.47, 44.61)] 100 | for (sim, res) in zip(sims, diagX): 101 | pilstring = template(None) 102 | simulation = sim 103 | reporter = 'ROX' 104 | metric = 'diagonal-crossing-time' 105 | tmax = '21600' 106 | cmax = '100' 107 | current.add_system_simulation_setup(pilstring, simulation, reporter, metric, 108 | ':'.join([tmax, cmax]), res, simargs=sim[sim.find('C='):]) 109 | 110 | halfC = [(611.58, 50.00), (15956.76, 50.00)] 111 | for (sim, res) in zip(sims, halfC): 112 | pilstring = template(None) 113 | simulation = sim 114 | reporter = 'ROX' 115 | metric = 'completion-time' 116 | current.add_system_simulation_setup(pilstring, simulation, reporter, metric, '50', 117 | res, simargs=sim[sim.find('C='):]) 118 | 119 | current.pepperargs['default'] = current.pepperargs['Condensed'].copy() 120 | 121 | if evaluate: 122 | current.eval() 123 | 124 | if verbose: 125 | for df in current.get_dataframes(): 126 | print(df) 127 | 128 | # Setup 129 | F3B = FigureData('Zhang & Winfree (2010) Fig. 3B - Catalytic DSD system 30 nM substrates (varying catalyst)') 130 | F3B.fname = 'Zhang2010-F3B' 131 | current = F3B 132 | template = zhang2007_F1_pil 133 | sims = [psim + ' --pyplot-labels S F OR C ROX --p0 S=30 F=60 OR=90 C=3', 134 | psim + ' --pyplot-labels S F OR C ROX --p0 S=30 F=60 OR=90 C=0.9'] 135 | 136 | diagX = [(4200.75, 24.15), (9051.94, 17.45)] 137 | for (sim, res) in zip(sims, diagX): 138 | pilstring = template(None) 139 | simulation = sim 140 | reporter = 'ROX' 141 | metric = 'diagonal-crossing-time' 142 | tmax = '21600' 143 | cmax = '30' 144 | current.add_system_simulation_setup(pilstring, simulation, reporter, metric, 145 | ':'.join([tmax, cmax]), res, simargs=sim[sim.find('C='):]) 146 | 147 | halfC = [(1571.89, 15), (6938.02, 15)] 148 | for (sim, res) in zip(sims, halfC): 149 | pilstring = template(None) 150 | simulation = sim 151 | reporter = 'ROX' 152 | metric = 'completion-time' 153 | current.add_system_simulation_setup(pilstring, simulation, reporter, metric, '15', 154 | res, simargs=sim[sim.find('C='):]) 155 | 156 | current.pepperargs['default'] = current.pepperargs['Condensed'].copy() 157 | 158 | if evaluate: 159 | current.eval() 160 | 161 | if verbose: 162 | for df in current.get_dataframes(): 163 | print(df) 164 | 165 | # Setup 166 | F3C = FigureData('Zhang & Winfree (2010) Fig. 3C - Catalytic DSD system with 3 nM substrates (varying catalyst)') 167 | F3C.fname = 'Zhang2010-F3C' 168 | current = F3C 169 | template = zhang2007_F1_pil 170 | sims = [psim + ' --pyplot-labels S F OR C ROX --p0 S=3 F=6 OR=9 C=0.9', 171 | psim + ' --pyplot-labels S F OR C ROX --p0 S=3 F=6 OR=9 C=0.3'] 172 | diagX = [(10199.26, 2.30), (17034.36, 1.82)] 173 | for (sim, res) in zip(sims, diagX): 174 | pilstring = template(None) 175 | simulation = sim 176 | reporter = 'ROX' 177 | metric = 'diagonal-crossing-time' 178 | tmax = '43200' 179 | cmax = '3' 180 | current.add_system_simulation_setup(pilstring, simulation, reporter, metric, 181 | ':'.join([tmax, cmax]), res, simargs=sim[sim.find('C='):]) 182 | 183 | halfC = [(4485.54, 1.50), (12388.63, 1.50)] 184 | for (sim, res) in zip(sims, halfC): 185 | pilstring = template(None) 186 | simulation = sim 187 | reporter = 'ROX' 188 | metric = 'completion-time' 189 | current.add_system_simulation_setup(pilstring, simulation, reporter, metric, '1.5', 190 | res, simargs=sim[sim.find('C='):]) 191 | 192 | current.pepperargs['default'] = current.pepperargs['condensed'].copy() 193 | 194 | if evaluate: 195 | current.eval() 196 | 197 | if verbose: 198 | for df in current.get_dataframes(): 199 | print(df) 200 | 201 | # Setup 202 | F3D = FigureData('Zhang & Winfree (2010) Fig. 3D - Catalytic DSD system with 1 nM substrates (varying catalyst)') 203 | F3D.fname = 'Zhang2010-F3D' 204 | current = F3D 205 | template = zhang2007_F1_pil 206 | sims = [psim + ' --pyplot-labels S F OR C ROX --p0 S=1 F=2 OR=3 C=1', 207 | psim + ' --pyplot-labels S F OR C ROX --p0 S=1 F=2 OR=3 C=0.1'] 208 | 209 | diagX = [(14382.50, 0.83), (40417.98, 0.53)] 210 | for (sim, res) in zip(sims, diagX): 211 | pilstring = template(None) 212 | simulation = sim 213 | reporter = 'ROX' 214 | metric = 'diagonal-crossing-time' 215 | tmax = '86400' 216 | cmax = '1' 217 | current.add_system_simulation_setup(pilstring, simulation, reporter, metric, 218 | ':'.join([tmax, cmax]), res, simargs=sim[sim.find('C='):]) 219 | 220 | halfC = [(5354.07, 0.50), (36323.69, 0.50)] 221 | for (sim, res) in zip(sims, halfC): 222 | pilstring = template(None) 223 | simulation = sim 224 | reporter = 'ROX' 225 | metric = 'completion-time' 226 | current.add_system_simulation_setup(pilstring, simulation, reporter, metric, '0.5', 227 | res, simargs=sim[sim.find('C='):]) 228 | 229 | 230 | current.pepperargs['default'] = current.pepperargs['condensed'].copy() 231 | 232 | if evaluate: 233 | current.eval() 234 | 235 | if verbose: 236 | for df in current.get_dataframes(): 237 | print(df) 238 | 239 | # Setup 240 | F10C = FigureData('Zhang & Winfree (2010) Fig. 10C -- Catalytic DSD system with four-letter alphabet (varying catalyst)') 241 | F10C.fname = 'Zhang2010-F10C' 242 | current = F10C 243 | template = zhang2010_F10A_pil 244 | sims = [psim + ' --pyplot-labels S4 F4 OR4 C4 ROX --p0 S4=30 F4=60 OR4=90 C4=3', 245 | psim + ' --pyplot-labels S4 F4 OR4 C4 ROX --p0 S4=30 F4=60 OR4=90 C4=0.09', 246 | psim + ' --pyplot-labels S4 F4 OR4 C4 ROX --p0 S4=30 F4=60 OR4=90 C4=0.03'] 247 | 248 | diagX = [(14893.10, 11.70), (25416.48, 5.91), (31189.31, 2.72)] 249 | for (sim, res) in zip(sims, diagX): 250 | pilstring = template(None) 251 | simulation = sim 252 | reporter = 'ROX' 253 | metric = 'diagonal-crossing-time' 254 | tmax = '36000' 255 | cmax = '20' 256 | current.add_system_simulation_setup(pilstring, simulation, reporter, metric, 257 | ':'.join([tmax, cmax]), res, simargs=sim[sim.find('C4='):]) 258 | 259 | #NOTE: That doesn't make sense! 260 | #halfC = [(10663.70, 10.01)] 261 | #for (sim, res) in zip(sims, halfC): 262 | # pilstring = template(None) 263 | # simulation = sim 264 | # reporter = 'ROX' 265 | # metric = 'completion-time' 266 | # current.add_system_simulation_setup(pilstring, simulation, reporter, metric, '10', 267 | # res, simargs=sim[sim.find('C4='):]) 268 | 269 | current.pepperargs['default'] = current.pepperargs['condensed'].copy() 270 | 271 | if evaluate: 272 | current.eval() 273 | 274 | if verbose: 275 | for df in current.get_dataframes(): 276 | print(df) 277 | 278 | # Setup 279 | F10F = FigureData('Zhang & Winfree (2010) Fig. 10F -- Catalytic DSD system with three and four-letter alphabet (varying catalyst)') 280 | F10F.fname = 'Zhang2010-F10F' 281 | current = F10F 282 | template = zhang2010_F10D_pil 283 | sims = [psim + ' --pyplot-labels S43 F43 OR43 C43 RG --p0 S43=10 F43=20 OR43=30 C43=3', 284 | psim + ' --pyplot-labels S43 F43 OR43 C43 RG --p0 S43=10 F43=20 OR43=30 C43=0.09', 285 | psim + ' --pyplot-labels S43 F43 OR43 C43 RG --p0 S43=10 F43=20 OR43=30 C43=0.03'] 286 | 287 | diagX = [(3545.01, 4.06), (5321.74, 2.07), (6277.79, 1.01)] 288 | for (sim, res) in zip(sims, diagX): 289 | pilstring = template(None) 290 | simulation = sim 291 | reporter = 'RG' 292 | metric = 'diagonal-crossing-time' 293 | tmax = '7200' 294 | cmax = '8' 295 | current.add_system_simulation_setup(pilstring, simulation, reporter, metric, 296 | ':'.join([tmax, cmax]), res, simargs=sim[sim.find('C43='):]) 297 | 298 | #NOTE: That doesn't make sense! 299 | #halfC = [(3426.56, 4.00)] 300 | #for (sim, res) in zip(sims, halfC): 301 | # pilstring = template(None) 302 | # simulation = sim 303 | # reporter = 'RG' 304 | # metric = 'completion-time' 305 | # current.add_system_simulation_setup(pilstring, simulation, reporter, metric, '4', 306 | # res, simargs=sim[sim.find('C43='):]) 307 | 308 | 309 | current.pepperargs['default'] = current.pepperargs['condensed'].copy() 310 | 311 | if evaluate: 312 | current.eval() 313 | 314 | if verbose: 315 | for df in current.get_dataframes(): 316 | print(df) 317 | 318 | return [F3A, F3B, F3C, F3D]#, F10C, F10F] 319 | 320 | if __name__ == '__main__': 321 | data(evaluate=True, verbose=1) 322 | 323 | 324 | 325 | -------------------------------------------------------------------------------- /case_studies/zhang2011.py: -------------------------------------------------------------------------------- 1 | 2 | def zhang2011_F1_pil(x): 3 | return """ 4 | # Domains 5 | length d1 = 8 6 | length d2a = 7 7 | length d2b = 7 8 | length d2c = 4 9 | length d3a = 14 10 | length d3b = 4 11 | length d4 = 8 12 | 13 | sup-sequence d2 = d2a d2b d2c : 18 14 | sup-sequence d3 = d3a d3b : 18 15 | 16 | # Setup Figure 1 17 | D1 = d2( d3( + d4* ) ) d1* 18 | T2 = d3 d4 19 | II = d1( d2( + d2 d3( + d4* ) ) ) 20 | IJ = d2( d3 + d3( d4( + ) ) ) d1* 21 | T1 = d1 d2 22 | H1 = d1( d2( + d3( d4( + ) ) ) ) @initial 0 M 23 | 24 | # Result 25 | P1 = d2 d3 @initial 0 M 26 | 27 | # Reporter System Figure 2 28 | R = d2c( d3a( + ) ) d2b* 29 | F = d2c d3a @initial 0 M 30 | FQ = d2a d2b( d2c( d3a( d3b + ) ) ) @initial 0 M 31 | 32 | """.format(x) 33 | 34 | def data(evaluate=False, verbose = 0): 35 | from figure_analysis import FigureData 36 | 37 | # Default pilsimulator call 38 | psim = "pilsimulator --no-jacobian --nxy --header" 39 | psim += " --atol 1e-10 --rtol 1e-10 --mxstep 1000" 40 | psim += " --t8 54000 --t-lin 54000" 41 | rates = {'k_slow': 0.001, 'k_fast': 0.1} 42 | 43 | # Setup 44 | F3A = FigureData('Zhang (2011) Fig. 3A - Cooperative strand displacement') 45 | F3A.fname = 'Zhang2011-F3A' 46 | current = F3A 47 | template = zhang2011_F1_pil 48 | sims = [psim + ' --pyplot-labels R D1 T1 T2 F --p0 R=60 D1=20 T1=18 T2=18', 49 | psim + ' --pyplot-labels R D1 T1 T2 F --p0 R=60 D1=20 T1=12 T2=12', 50 | psim + ' --pyplot-labels R D1 T1 T2 F --p0 R=60 D1=20 T1=6 T2=6'] 51 | 52 | diagX = [(409.46, 9.15), (425.68, 6.14), (300.00, 3.25)] 53 | diagXe = [('1800','12'), ('1800','8'), ('1800','4')] 54 | 55 | for (sim, res, tc) in zip(sims, diagX, diagXe): 56 | pilstring = template(None) 57 | simulation = sim 58 | reporter = 'F' 59 | metric = 'diagonal-crossing-time' 60 | tmax = tc[0] 61 | cmax = tc[1] 62 | current.add_system_simulation_setup(pilstring, simulation, reporter, metric, 63 | ':'.join([tmax, cmax]), res, simargs=sim[sim.find('T1='):]) 64 | 65 | halfC = [(381.08, 9.02), (385.14, 6.01), (263.51, 3.02)] 66 | 67 | for (sim, res) in zip(sims, halfC): 68 | pilstring = template(None) 69 | simulation = sim 70 | reporter = 'F' 71 | metric = 'completion-time' 72 | current.add_system_simulation_setup(pilstring, simulation, reporter, metric, 73 | '50%', res, simargs=sim[sim.find('T1='):]) 74 | 75 | current.pepperargs['default'] = current.pepperargs['Condensed'].copy() 76 | current.pepperargs['default'].update(rates) 77 | 78 | if evaluate: 79 | current.eval(verbose=verbose) 80 | 81 | if verbose: 82 | for df in current.get_dataframes(): 83 | print(df) 84 | 85 | return [F3A] 86 | 87 | if __name__ == '__main__': 88 | data(evaluate=True, verbose=1) 89 | 90 | 91 | 92 | 93 | -------------------------------------------------------------------------------- /peppercornenumerator/__init__.py: -------------------------------------------------------------------------------- 1 | # 2 | # __init__.py 3 | # EnumeratorProject 4 | # 5 | __version__ = "v1.1.1" 6 | 7 | import logging 8 | logging.getLogger(__name__).addHandler(logging.NullHandler()) 9 | 10 | from .enumerator import (enumerate_pil, 11 | enumerate_ssw, 12 | Enumerator, 13 | PolymerizationError) 14 | from .utils import PeppercornUsageError 15 | from .condense import CondensationError 16 | 17 | -------------------------------------------------------------------------------- /peppercornenumerator/objects.py: -------------------------------------------------------------------------------- 1 | # 2 | # peppercornenumerator/objects.py 3 | # EnumeratorProject 4 | # 5 | import gc 6 | import logging 7 | log = logging.getLogger(__name__) 8 | 9 | from itertools import chain 10 | 11 | from dsdobjects import SingletonError, clear_singletons, show_singletons 12 | from dsdobjects.base_classes import ObjectInitError, DomainS, StrandS, ComplexS, MacrostateS, ReactionS 13 | 14 | def clear_memory(): 15 | # This is for unittests only! The memory of a Singleton clears 16 | # automatically if there is no hard reference to the object. 17 | gc.collect() 18 | if list(show_memory()): 19 | log.warning('Could not collect singleton objects, trying other means.') 20 | clear_singletons(PepperDomain) 21 | clear_singletons(PepperStrand) 22 | clear_singletons(PepperComplex) 23 | clear_singletons(PepperMacrostate) 24 | clear_singletons(PepperReaction) 25 | 26 | def show_memory(): 27 | # This is for unittests only! The memory of a Singleton clears 28 | # automatically if there is no hard reference to the object. 29 | for x in chain(show_singletons(PepperDomain), 30 | show_singletons(PepperStrand), 31 | show_singletons(PepperComplex), 32 | show_singletons(PepperMacrostate), 33 | show_singletons(PepperReaction)): 34 | yield x 35 | 36 | class PepperDomain(DomainS): 37 | pass 38 | 39 | class PepperStrand(StrandS): 40 | pass 41 | 42 | class PepperComplex(ComplexS): 43 | PREFIX = 'e' 44 | @property 45 | def available_domains(self): 46 | ad = [] 47 | for x, y in self.exterior_domains: 48 | ad.append((self.get_domain((x, y)), x, y)) 49 | return ad 50 | 51 | class PepperMacrostate(MacrostateS): 52 | pass 53 | 54 | class PepperReaction(ReactionS): 55 | RTYPES = set(['condensed', 'open', 'bind11', 'bind21', 'branch-3way', 'branch-4way']) 56 | 57 | @property 58 | def const(self): 59 | log.warning('deprecated property PepperReaction.const') 60 | return self.rate_constant[0] 61 | 62 | @const.setter 63 | def const(self, value): 64 | log.warning('deprecated property PepperReaction.const') 65 | self.rate_constant = value 66 | 67 | class Loop: 68 | """ A (part of a) single open or closed loop region. 69 | 70 | Args: 71 | loop [(domain, paired_loc, domain_loc), ...]: A list of domains and 72 | their structure: 73 | [0] A Domain Object, 74 | [1] its binding partner position (or None), 75 | [2] the domain position. 76 | None marks the 3' or 5' end of a strand. 77 | """ 78 | def __init__(self, loop): 79 | self._parts = loop 80 | 81 | bases = 0 82 | stems = 0 83 | is_open = False 84 | stem_list = set() 85 | for step in loop: 86 | if step is None: 87 | if is_open: 88 | raise ObjectInitError('Double strand break in Loop Object.') 89 | is_open = True 90 | else: 91 | (dom, ploc, dloc) = step 92 | if ploc is None: 93 | bases += len(dom) 94 | elif ploc in stem_list: 95 | raise ObjectInitError('Double stem count in Loop Object.') 96 | else: 97 | stems += 1 98 | stem_list.add(dloc) 99 | # cache properties 100 | self._is_open = is_open 101 | self._bases = bases 102 | self._stems = stems 103 | 104 | @property 105 | def domains(self): 106 | return (part[0] if part is not None else None for part in self._parts) 107 | 108 | @property 109 | def domain_locs(self): 110 | return (part[2] if part is not None else None for part in self._parts) 111 | 112 | @property 113 | def pair_locs(self): 114 | return (part[1] if part is not None else None for part in self._parts) 115 | 116 | @property 117 | def parts(self): 118 | """ list: (dom, struct, loc) tuples associated with this loop. """ 119 | return self._parts[:] 120 | 121 | @property 122 | def stems(self): 123 | """ int: the number of stems. """ 124 | return self._stems 125 | 126 | @property 127 | def bases(self): 128 | """ int: the number of bases. """ 129 | return self._bases 130 | 131 | @property 132 | def is_open(self): 133 | """ bool: True if there is a strand break in the loop. """ 134 | return self._is_open 135 | 136 | @property 137 | def dlength(self): 138 | """ int: the sum over all involved domain lengths. """ 139 | assert None not in self.domains 140 | return sum(len(d) for d in self.domains) 141 | 142 | @property 143 | def llength(self): 144 | """ flt: the *linker length* expressed in number of nucleotides. """ 145 | if self.is_open: 146 | return float('inf') 147 | else: 148 | # approximate number of single-stranded nucleotides to span a stem 149 | stemL = 2.0 / 0.43 150 | return 1 + self.bases + self.stems + (stemL * self.stems) 151 | 152 | def __repr__(self): 153 | return f"Loop({self.parts})" 154 | 155 | -------------------------------------------------------------------------------- /peppercornenumerator/pilsimulator.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python3 2 | # 3 | # pilsimulator: simulate PIL files using ODEs 4 | # 5 | # Written by Stefan Badelt (badelt@caltech.edu). 6 | # 7 | # Use at your own risk. 8 | # 9 | # 10 | import logging 11 | import os 12 | import sys 13 | import argparse 14 | 15 | from crnsimulator import ReactionGraph, get_integrator 16 | from crnsimulator.odelib_template import add_integrator_args 17 | 18 | from . import __version__ 19 | from .input import load_pil_crn 20 | 21 | class SimulationSetupError(Exception): 22 | pass 23 | 24 | def main(): 25 | """Translate a CRN into a system of ODEs. Optional: Simulate ODEs on-the-fly. """ 26 | parser = argparse.ArgumentParser( 27 | formatter_class=argparse.ArgumentDefaultsHelpFormatter) 28 | parser.add_argument('--version', action='version', version='%(prog)s ' + __version__) 29 | parser.add_argument("-v", "--verbose", action='count', default = 0, 30 | help = "Print logging output. (-vv increases verbosity.)") 31 | parser.add_argument('--logfile', default = '', action = 'store', metavar = '', 32 | help = "Redirect logging information to a file.") 33 | parser.add_argument("--force", action='store_true', 34 | help="Overwrite existing files") 35 | parser.add_argument("--dry-run", action='store_true', 36 | help="Do not run the simulation, only write the files.") 37 | parser.add_argument("-o", "--output", default='odesystem', metavar='', 38 | help="Name of ODE library files.") 39 | parser.add_argument("--no-jacobian", action='store_true', 40 | help=argparse.SUPPRESS) 41 | parser.add_argument("--jacobian", action='store_true', 42 | help="""Symbolic calculation of Jacobi-Matrix. 43 | This may generate a very large simulation file.""") 44 | add_integrator_args(parser) 45 | args = parser.parse_args() 46 | 47 | # ~~~~~~~~~~~~~ 48 | # Logging Setup 49 | # ~~~~~~~~~~~~~ 50 | logger = logging.getLogger('crnsimulator') 51 | logger.setLevel(logging.DEBUG) 52 | handler = logging.FileHandler(args.logfile) if args.logfile else logging.StreamHandler() 53 | if args.verbose == 0: 54 | handler.setLevel(logging.WARNING) 55 | elif args.verbose == 1: 56 | handler.setLevel(logging.INFO) 57 | elif args.verbose == 2: 58 | handler.setLevel(logging.DEBUG) 59 | elif args.verbose >= 3: 60 | handler.setLevel(logging.NOTSET) 61 | formatter = logging.Formatter('%(levelname)s - %(message)s') 62 | handler.setFormatter(formatter) 63 | logger.addHandler(handler) 64 | 65 | if args.no_jacobian: 66 | logging.warning('Deprecated argument: --no-jacobian, OFF by default.') 67 | if args.pyplot_labels: 68 | logging.warning('Deprecated argument: --pyplot_labels, use --labels.') 69 | args.labels = args.pyplot_labels 70 | args.pyplot_labels = None 71 | 72 | # ********************* # 73 | # ARGUMENT PROCESSING 1 # 74 | # ..................... # 75 | filename = args.output + \ 76 | '.py' if args.output[-3:] != '.py' else args.output 77 | odename = 'odesystem' 78 | 79 | input_crn = sys.stdin.readlines() 80 | input_crn = "".join(input_crn) 81 | 82 | crn, species = load_pil_crn(input_crn) 83 | 84 | if crn == []: 85 | raise SystemExit('No Input CRN provided.') 86 | 87 | V = [] # sorted species (vertices) vector 88 | C = [] # corresponding concentration vector 89 | seen = set() # keep track of what species are covered 90 | 91 | # Move interesting species to the front, in their given order. 92 | const = [] 93 | labels = args.labels 94 | for s in labels: 95 | if s in seen : 96 | raise SimulationSetupError('Multiple occurances of {} in labels.'.format(s)) 97 | V.append(s) 98 | const.append(False if species[s][0][0] == 'i' else True) 99 | C.append(species[s][1]) 100 | seen.add(s) 101 | 102 | # Append the remaining specified species 103 | for s in sorted(species): 104 | if s in seen : continue 105 | V.append(s) 106 | const.append(False if species[s][0][0] == 'i' else True) 107 | C.append(species[s][1]) 108 | seen.add(s) 109 | 110 | # Split CRN into irreversible reactions 111 | new = [] 112 | for [r, p, k] in crn: 113 | assert not (None in k) 114 | if len(k) == 2: 115 | new.append([r, p, k[0]]) 116 | new.append([p, r, k[1]]) 117 | else: 118 | new.append([r, p, k[0]]) 119 | crn = new 120 | 121 | # **************** # 122 | # WRITE ODE SYSTEM # 123 | # ................ # 124 | if filename != 'odesystem.py' and not args.force and os.path.exists(filename): 125 | logger.warning(f'Reading ODE system from existing file: {filename}') 126 | else: 127 | # ******************* # 128 | # BUILD REACTIONGRAPH # 129 | # ................... # 130 | RG = ReactionGraph(crn) 131 | if len(RG.species) > len(V): 132 | raise SimulationSetupError('Undefined species in the CRN.') 133 | elif len(RG.species) < len(V): 134 | raise SimulationSetupError('Some species do not appear in the CRN.') 135 | 136 | # ********************* # 137 | # PRINT ODE TO TEMPLATE # 138 | # ..................... # 139 | filename, odename = RG.write_ODE_lib(sorted_vars = V, concvect = C, 140 | const = const if any(const) else None, 141 | jacobian = not args.no_jacobian, 142 | filename = filename, 143 | odename = odename) 144 | logger.info(f'CRN to ODE translation successful. Wrote file: {filename}') 145 | 146 | # ******************* # 147 | # SIMULATE ODE SYSTEM # 148 | # ................... # 149 | if args.dry_run: 150 | logger.info('Dry run: Simulate the ODE system using:') 151 | logger.info(f" python {filename} --help ") 152 | else: 153 | logger.info('Simulating the ODE system, change parameters using:') 154 | logger.info(f" python {filename} --help ") 155 | 156 | integrate = get_integrator(filename) 157 | 158 | # ********************* # 159 | # ARGUMENT PROCESSING 2 # 160 | # ..................... # 161 | integrate(args, setlogger = True) 162 | 163 | return 164 | 165 | 166 | if __name__ == '__main__': 167 | main() 168 | -------------------------------------------------------------------------------- /peppercornenumerator/ratemodel.py: -------------------------------------------------------------------------------- 1 | # 2 | # peppercornenumerator/ratemodel.py 3 | # EnumeratorProject 4 | # 5 | import logging 6 | log = logging.getLogger(__name__) 7 | 8 | import math 9 | 10 | def polymer_link_length(before, after): 11 | """ Length estimates in nucleotides for linkers connecting two domains. 12 | 13 | Args: 14 | before (Loop): A loop object for which we measure the length. 15 | after (Loop): A loop object for which we measure the length. 16 | 17 | Returns: 18 | [float]: The length of the shorter loop. 19 | """ 20 | L_stem = 2.0 / 0.43 # rough equivalent number of single-stranded nucleotides to span a stem 21 | L_before = float('inf') if before.is_open else \ 22 | 1 + before.bases + before.stems + L_stem * before.stems 23 | L_after = float('inf') if after.is_open else \ 24 | 1 + after.bases + after.stems + L_stem * after.stems 25 | if after.is_open and before.is_open: 26 | raise ValueError("Computing polymer lengths for disconnected complexes!") 27 | return min(L_before, L_after) 28 | 29 | def polymer_link_rate(hllen, ha = 1e6, hb = -2.5, kmax = 33_000): 30 | """ Unimolecular hairpin closing rate, as a function of hairpin loop length. 31 | 32 | References for default values: 33 | * Bonnet et al. (1998) 34 | * Kuznetsov et al. (2008) 35 | * Nayak et al. (2012) 36 | * Tsukanov et al. (2013) 37 | 38 | Args: 39 | hllen (flt): Hairpin loop length. The number of unpaired bases in a 40 | hairpin loop, or an arbitrary linker length in terms of an 41 | equivalently long chain of unpaired bases. 42 | ha (flt, optional): The rate for closing the first base-pair. 43 | Defaults to 1_000_000 [/s]. 44 | hb (flt, optional): Exponential factor to relate hllen to the 45 | probability of forming the initial contact. Defaults to -2.5. 46 | kmax (flt, optional): Fastest hairpin closing rate. Defaults to 33_000 [/s]. 47 | (E.g. hairpins shorter than 4 nt cannot close any faster than this.) 48 | 49 | Returns: 50 | [flt]: The rate for closing the initial base-pair of a hairpin. 51 | """ 52 | return min(ha * hllen**hb, kmax) 53 | 54 | def unimolecular_binding_rate(length, before, after): 55 | """ 56 | Rate constant formula for unimolecular binding of a domain of the given length. 57 | Could be zippering, hairpin closing, bubble closing, bulge formation, multiloop formation, 58 | depending on the flanking loops, which may be open or closed. 59 | """ 60 | if not before.is_open and before.stems == 1 and before.bases == 0: 61 | if not after.is_open and after.stems == 1 and after.bases == 0: 62 | return 1e4 # bubble closing rate from Altan-Bonnet 2003 63 | # zippering from Wetmur&Davidson 1968, Gueron&Leroy 1995, Srinivas et al 2013, low end 64 | return (1e6) / length 65 | if not after.is_open and after.stems == 1 and after.bases == 0: 66 | # zippering from Wetmur&Davidson 1968, Gueron&Leroy 1995, Srinivas et al 2013, low end 67 | return (1e6) / length 68 | # bulge closing assumed to be similar to faster of two hairpin closings 69 | L = polymer_link_length(before, after) 70 | # hairpin closing adapted (simplified) from data in Bonnet et al 1998 71 | return polymer_link_rate(L) 72 | 73 | def bimolecular_binding_rate(length, k_nuc = 3e5): 74 | """ Rate constant formula for bimolecular association (binding). 75 | 76 | Hybridization is determined by well-aligned initial contacts, therefore 77 | dependent linearly on length 78 | 79 | Literature: 80 | Wetmur 1976 review, 81 | Srinivas et al. 2013 AEL model, 82 | Zhang & Winfree 2009. 83 | 84 | Args: 85 | length (int): The length of a domain. 86 | k_nuc (flt, optional): The hybridization rate per nucleotide. 87 | Defaults to 3*10^5. 88 | 89 | Returns: 90 | [float]: The rate constant for bimolecular binding. 91 | """ 92 | return length * k_nuc 93 | 94 | def opening_rate(length, dG_bp = -1.7, dG_assoc = 1.9, kelvin = 298.15, dissoc = True): 95 | """ Rate constant for opening a duplex of a given `length`. 96 | 97 | k_open = k_bind * exp( (length * dG_bp + dG_assoc) / RT ) 98 | 99 | Args: 100 | dG_bp (flt): Energy contribution of a single WC base pair. 101 | Defaults to -1.7 kcal/mol. 102 | dG_assoc (flt): Association energy penalty. 103 | Defaults to 1.9 kcal/mol. 104 | kelvin (flt): Temperature in K. Defaults to 298.15 (25 C). 105 | 106 | Returns: 107 | [float]: The rate constant. 108 | """ 109 | # R = 0.001987 kcal/mol/K 110 | # T = (273.15 + 25) K 111 | RT = 0.001987 * kelvin 112 | 113 | if True or dissoc: # stay with simple model! 114 | k_bind21 = bimolecular_binding_rate(length) 115 | dG = (length * dG_bp) + dG_assoc 116 | rate = k_bind21 * math.exp(dG/RT) 117 | else: 118 | k_bind11 = 1e6 * length # using zipping rate, not bubble-closing 119 | dG = length * dG_bp 120 | rate = k_bind11 * math.exp(dG/RT) 121 | return rate 122 | 123 | def branch_3way_remote_rate(length, before, after): 124 | """ Rate constant for a 3-way branch-migration reaction. 125 | 126 | Args: 127 | length (int): the length of the domain 128 | before (:obj:Loop): the loop object on the initiation site. 129 | after (:obj:Loop): the other (remote) loop object. 130 | 131 | Returns: 132 | k1 = P(link) * k_init / l 133 | """ 134 | # step = 0.1e-3 # 100us branch migration step time from Srinivas et al 2013 (not relevant) 135 | # k_init = k_uni exp(-dGsp / RT) with k_uni = 7.5e7, dGsp = 7.3 kcal/mol, 136 | # T = 273.15 + 25 K, R = 0.001987 kcal/mol/K 137 | 138 | # Experimentally derived time for a single step of 3-way branch migration. 139 | t_step = 1e-4 # sec 140 | k_step = 1/t_step 141 | 142 | if after._parts[0] is None: 143 | # Initialtion penalty if there is *no* danling end on the displaced side. 144 | t_init = 3.0e-3 145 | k_init = 1/t_init 146 | else : 147 | # Initialtion penalty if there is a danling end on the displaced side, 148 | # in which case it is just a regular displacement step. 149 | t_init = t_step 150 | k_init = k_step 151 | 152 | k1 = None # The probability of a successfull branch migration scales with 1/L 153 | k2 = None # The time spent on branch migration scales with 1/L^2 154 | 155 | # "standard" 3-way bm initiation (plus "after" being closed) 156 | if not before.is_open and before.stems == 1 and before.bases == 0: 157 | k1 = k_init / length 158 | #k2 = k_init / length + k_step / length**2 159 | else : 160 | # consider a slowdown analogous to Genot et al 2011 (remote) supp info derivation 161 | # bulge closing assumed to be similar to faster of two hairpin closings 162 | L = polymer_link_length(before, after) 163 | 164 | # how much slower than our (admittedly slow) zippering rate is this? 165 | ratio = polymer_link_rate(L) / 1e6 166 | 167 | # we slow down initiation and thus success probability (note: ratio < 1/30) 168 | k1 = ratio * k_init / length 169 | #k2 = ratio * k_init / length + k_step / length**2 170 | 171 | return k1 172 | 173 | def branch_4way_remote_rate(length, before, after): 174 | """ Rate constant for a 4-way branch-migration reaction. 175 | """ 176 | # rates recalculated from Nadine Dabby, PhD Thesis, 2013, based on 177 | # assuming last 6 bp dissociate faster than 4way bm step 178 | open_step = 107 # sec, = 1/k_first (this is for open 4-way case only) 179 | # sec, = 1/k_bm (this is used for initiating closed 4-way case; 180 | # consistent with Panyutin&Hsieh 1993) 181 | closed_step = 3.0 182 | 183 | # open_step = 200 # fudge ! 184 | if not before.is_open and not after.is_open: 185 | init = closed_step 186 | if before.bases == 0 and before.stems == 1 and after.bases == 0 and after.stems == 1: 187 | return 1.0 / init / length # closed & ready-to-rock-and-roll 4 way initiation 188 | if before.is_open: 189 | init = open_step 190 | if after.bases == 0 and after.stems == 1: 191 | # we care about probability of taking this path, not actual time 192 | return 1.0 / init / length 193 | if after.is_open: 194 | init = open_step 195 | if before.bases == 0 and before.stems == 1: 196 | # we care about probability of taking this path, not actual time 197 | return 1.0 / init / length 198 | 199 | # consider a slowdown analogous to Genot et al 2011 (remote) supp info derivation 200 | # bulge closing assumed to be similar to faster of two hairpin closings 201 | L = polymer_link_length(before, after) 202 | # how much slower than our (admittedly slow) zippering rate is this? 203 | ratio = polymer_link_rate(L) / (1e6) 204 | # we slow down initiation and thus success probability (note: ratio < 1/30) 205 | return ratio / init / length 206 | 207 | -------------------------------------------------------------------------------- /peppercornenumerator/utils.py: -------------------------------------------------------------------------------- 1 | # 2 | # peppercornenumerator/utils.py 3 | # EnumeratorProject 4 | # 5 | import logging 6 | log = logging.getLogger(__name__) 7 | 8 | import sys 9 | sys.setrecursionlimit(10**6) 10 | 11 | class PeppercornUsageError(Exception): 12 | pass 13 | 14 | def wrap(x, m): 15 | """ 16 | Mathematical modulo; wraps x so that 0 <= wrap(x,m) < m. x can be negative. 17 | """ 18 | return (x % m + m) % m 19 | 20 | def tarjans(complexes, products): 21 | """ Tarjans algorithm to find strongly connected components. """ 22 | stack, SCCs = [], [] 23 | def strongconnect(at, index): 24 | stack.append(at) 25 | at.index = index 26 | at.llink = index 27 | index += 1 28 | for to in products[at]: 29 | if to.index is None: 30 | # Product hasn't been traversed; recurse 31 | strongconnect(to, index) 32 | if to in stack: 33 | # Product is in the current neighborhood 34 | at.llink = min(at.llink, to.llink) 35 | 36 | if at.index == at.llink: 37 | # Back to the start, get the SCC. 38 | scc = [] 39 | while True: 40 | nc = stack.pop() 41 | nc.llink == at.index 42 | scc.append(nc) 43 | if nc == at: 44 | break 45 | SCCs.append(scc) 46 | 47 | for cplx in complexes: 48 | cplx.index = None 49 | 50 | for i, cplx in enumerate(complexes): 51 | if cplx.index is None: 52 | strongconnect(cplx, i) 53 | return SCCs 54 | 55 | -------------------------------------------------------------------------------- /pyproject.toml: -------------------------------------------------------------------------------- 1 | [build-system] 2 | requires = ["flit_core >=3.8,<4"] 3 | build-backend = "flit_core.buildapi" 4 | 5 | [project] 6 | name = 'peppercornenumerator' 7 | description = 'Domain-level nucleic acid reaction enumerator' 8 | authors = [{name = "Stefan Badelt", email = "bad-ants-fleet@posteo.eu"}, 9 | {name = "Casey Grun"}, 10 | {name = "Karthik Sarma"}, 11 | {name = "Brian Wolfe"}, 12 | {name = "Seung Woo Shin"}, 13 | {name = "Erik Winfree", email = "winfree@caltech.edu"}] 14 | maintainers = [{name = "Stefan Badelt", email = "bad-ants-fleet@posteo.eu"}] 15 | readme = "README.md" 16 | license = {file = "LICENSE"} 17 | classifiers = [ 18 | "Intended Audience :: Science/Research", 19 | "Programming Language :: Python :: 3.8", 20 | "Programming Language :: Python :: 3.9", 21 | "Programming Language :: Python :: 3.10", 22 | "Programming Language :: Python :: 3.11", 23 | "License :: OSI Approved :: MIT License", 24 | "Development Status :: 5 - Production/Stable", 25 | ] 26 | requires-python = ">=3.8" 27 | dependencies = [ 28 | "numpy", 29 | "pandas", 30 | "natsort", 31 | "dsdobjects>=0.8", 32 | "crnsimulator>=0.9", 33 | ] 34 | dynamic = ["version"] 35 | 36 | [project.scripts] 37 | peppercorn = "peppercornenumerator.peppercorn:main" 38 | pilsimulator = "peppercornenumerator.pilsimulator:main" 39 | 40 | [project.optional-dependencies] 41 | dev = [ 42 | "pytest", 43 | "pytest-cov", 44 | "codecov", 45 | ] 46 | 47 | [project.urls] 48 | Home = "http://www.github.com/DNA-and-Natural-Algorithms-Group/peppercorn" 49 | -------------------------------------------------------------------------------- /tests/__init__.py: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/DNA-and-Natural-Algorithms-Group/peppercornenumerator/488537edb75b4a6f3e911bb24d9f040e4e2483c9/tests/__init__.py -------------------------------------------------------------------------------- /tests/examples/README.md: -------------------------------------------------------------------------------- 1 | # Various examples that have been enumerated using peppercorn. 2 | 3 | Help with cleaning up this directory would be greatly appreciated. For example, 4 | in form of a unified naming scheme or directory structure that helps to find 5 | those system specifications in DSD literature. 6 | 7 | Also, many of the examples here have been used to test this software at an early 8 | stage, so the comments may not be up do date. Any new comments should include 9 | the current version number of Peppercorn. 10 | 11 | 12 | -------------------------------------------------------------------------------- /tests/examples/literature/badelt2019_F5.pil: -------------------------------------------------------------------------------- 1 | # 2 | # Badelt, Grun, Sarma, Wolfe, Shin, Winfree (in preparation) 3 | # 4 | # Figure 5: Delayed choice. 5 | # 6 | 7 | # Domains 8 | length a = 5 9 | length b = 15 10 | length c = 15 11 | length d = 15 12 | length e = 15 13 | length z = 15 14 | 15 | # Initial resting complexes (3) 16 | R0 = a b c 17 | RC1a = d( e( z ) ) b*( a* + ) c( + ) d 18 | RC1b = d e( z ) d*( b*( a* + ) c( + ) ) 19 | 20 | # Names for potential resting complexes (5) 21 | R21 = b c( + ) d @i 0.0 M 22 | R22 = d( e( z ) ) b*( a*( + ) ) c @i 0.0 M 23 | R31 = b c @i 0.0 M 24 | Rc32a = d( e( z ) ) b*( a*( + ) ) c( + ) d @i 0.0 M 25 | RC32b = d e( z ) d*( b*( a*( + ) ) c( + ) ) @i 0.0 M 26 | 27 | # Names for potential transient complexes (3) 28 | TC1 = a( b c + b( c( + ) d + d( e( z ) ) ) ) @i 0.0 M 29 | TC2 = a( b c + b( c( + ) d( + d e( z ) ) ) ) @i 0.0 M 30 | TC3 = a( b( c + b c( + ) d( + d e( z ) ) ) ) @i 0.0 M 31 | 32 | -------------------------------------------------------------------------------- /tests/examples/literature/kotani2017_F2.pil: -------------------------------------------------------------------------------- 1 | # 2 | # Shohei Kotani and William L. Hughes (2017) 3 | # Multi-Arm Junctions for Dynamic DNA Nanotechnology 4 | # 5 | # Figure 2A: Single-layer catalytic system with three-arm junction substrates. 6 | # 7 | 8 | length a = 22 9 | length b = 22 10 | length c = 22 11 | length t1 = 6 # name = 1 in Figure 12 | length t2 = 6 # name = 2 in Figure 13 | length t3 = 10 # name = 3 in Figure 14 | length T2 = 2 15 | 16 | length d1s = 16 17 | length d2 = 6 18 | 19 | S1 = d1s T2 b( a( t2( + ) ) c*( t1* + ) ) 20 | S2 = t1( c( a( + t2* ) b*( d2 t3 + ) ) ) 21 | C1 = t1 c a 22 | 23 | P1 = t2* a*( c*( t1*( + ) ) ) @initial 0 M 24 | I1 = d1s T2 b( a t2 + c ) @initial 0 M 25 | I2 = d1s T2 b( a( t2( + ) ) b*( d2 t3 + ) c*( t1* + ) ) @initial 0 M 26 | 27 | P2 = d1s T2 b( a( t2( + ) ) ) d2 t3 @initial 0 M 28 | P3 = b( c*( t1* + ) ) @initial 0 M 29 | 30 | R = d1s( d2( + t3* ) ) 31 | 32 | D = d1s d2 @initial 0 M 33 | RW = d1s( T2 b( a( t2( + ) ) ) d2( t3( + ) ) ) @initial 0 M 34 | 35 | -------------------------------------------------------------------------------- /tests/examples/literature/thachuk2015_fig5.pil: -------------------------------------------------------------------------------- 1 | # Thachuk, Winfree, Soloveichik (2015) 2 | # Figure 5 3 | 4 | length a1a = 5 5 | length a1b = 5 6 | length a1c = 5 7 | length a2 = 15 8 | length a3a = 5 9 | length a3b = 5 10 | length a3c = 5 11 | 12 | length b1a = 5 13 | length b1b = 5 14 | length b1c = 5 15 | length b2a = 5 16 | length b2b = 5 17 | length b2c = 5 18 | length b3a = 5 19 | length b3b = 5 20 | length b3c = 5 21 | 22 | length x1 = 15 23 | length x2 = 15 24 | length x3 = 15 25 | 26 | A = a1a a1b a1c a2 a3a a3b a3c 27 | B = b1a b1b b1c b2a b2b b2c b3a b3b b3c 28 | X = x1 x2 x3 29 | 30 | F1 = a3c* a3b*( a3a*( a2*( b2c*( b2b*( b2a*( b1c*( b1b*( b1a*( + ) ) ) ) ) + ) ) ) ) 31 | F2 = a1b( a1c( b3a( b3b( b3c( x1 + ) ) ) ) ) a1a* 32 | F3 = b3b( b3c( x1( x3 + ) ) ) b3a* 33 | F4 = x1( x2 x3( + ) ) b3c* 34 | 35 | 36 | -------------------------------------------------------------------------------- /tests/examples/literature/thachuk2015_fig9.pil: -------------------------------------------------------------------------------- 1 | # Thachuk, Winfree, Soloveichik (2015) 2 | # Figure 9 3 | 4 | length a1a = 5 5 | length a1b = 5 6 | length a1c = 5 7 | length a2a = 5 8 | length a2b = 5 9 | length a2c = 5 10 | length a3a = 5 11 | length a3b = 5 12 | length a3c = 5 13 | 14 | length b1a = 5 15 | length b1b = 5 16 | length b1c = 5 17 | length b2a = 5 18 | length b2b = 5 19 | length b2c = 5 20 | length b3a = 5 21 | length b3b = 5 22 | length b3c = 5 23 | 24 | length x1 = 15 25 | length x2 = 15 26 | length x3a = 5 27 | length x3b = 5 28 | length x3c = 5 29 | 30 | length y1 = 15 31 | length y2 = 15 32 | length y3a = 5 33 | length y3b = 5 34 | length y3c = 5 35 | 36 | length zero = 5 37 | 38 | A = a1a a1b a1c a2a a2b a2c a3a a3b a3c 39 | B = b1a b1b b1c b2a b2b b2c b3a b3b b3c 40 | X = x1 x2 x3a x3b x3c a3a a3b a3c 41 | Y = y1 y2 y3a y3b y3c b3a b3b b3c 42 | 43 | F1 = b2a( b2b( x2( x3a( x3b( x3c( a2c* a2b*( a2a*( a1c*( a1b*( a1a*( zero*( + ) ) ) ) ) ) y2 y3a y3b + ) ) ) ) ) ) b1c* @initial 100 nM 44 | F2 = a2a( a2b( y2( y3a( y3b( y3c( b2c* b2b*( b2a*( b1c*( b1b*( b1a*( zero*( + ) ) ) ) ) ) x2 x3a x3b + ) ) ) ) ) ) a1c* @initial 100 nM 45 | 46 | F3 = x1 x2( x3a( x3b( x3c( a3a( a3b( a3c( + ) ) ) ) ) ) ) b2b* @initial 100 nM 47 | F4 = y1 y2( y3a( y3b( y3c( b3a( b3b( b3c( + ) ) ) ) ) ) ) a2b* @initial 100 nM 48 | 49 | -------------------------------------------------------------------------------- /tests/examples/literature/wang2018_DLD.pil: -------------------------------------------------------------------------------- 1 | length rX1 = 10 2 | length DX1 = 10 3 | length rX2 = 10 4 | length DX2 = 10 5 | length rY1 = 10 6 | length DY1 = 10 7 | length rY2 = 10 8 | length DY2 = 10 9 | 10 | sup-sequence X1 = DX1 rX1 11 | sup-sequence X2 = DX2 rX2 12 | sup-sequence Y1 = DY1 rY1 13 | sup-sequence Y2 = DY2 rY2 14 | 15 | X = X2 X1 16 | Y = Y2 Y1 DX2 17 | 18 | F1 = Y1 X2( DX1( + rX1* ) ) 19 | F2 = Y2 Y1( DX2( + rX2* ) ) 20 | R = Y2( DY1( + rY1* ) ) 21 | 22 | F1T = Y1 X2 DX1 23 | RT = Y2 DY1 24 | 25 | W1 = X2( X1( + ) ) 26 | W2 = Y1( X2( DX1 + ) ) 27 | W3 = Y2( Y1( DX2 + ) ) 28 | -------------------------------------------------------------------------------- /tests/examples/literature/wang2018_SLD.pil: -------------------------------------------------------------------------------- 1 | length lX1 = 15 2 | length dX1 = 5 3 | length lX2 = 15 4 | length dX2 = 5 5 | length lY1 = 15 6 | length dY1 = 5 7 | length lY2 = 15 8 | length dY2 = 5 9 | 10 | sup-sequence X1 = dX1 lX1 11 | sup-sequence X2 = dX2 lX2 12 | sup-sequence Y1 = dY1 lY1 13 | sup-sequence Y2 = dY2 lY2 14 | 15 | X = X2 dX1 16 | Y = Y2 Y1 17 | 18 | F1 = Y1 X2( + dX1* ) 19 | F2 = Y2 Y1( + dX2* ) 20 | R = Y2( + dY1* ) 21 | 22 | F1T = Y1 X2 23 | RT = Y2 24 | 25 | W1 = X2( dX1( + ) ) 26 | W2 = Y1( dX2( lX2 + ) ) 27 | W3 = Y2( dY1( lY1 + ) ) 28 | -------------------------------------------------------------------------------- /tests/examples/literature/wang2018_TLD.pil: -------------------------------------------------------------------------------- 1 | length rX1 = 10 2 | length DX1 = 10 3 | length rX2 = 10 4 | length DX2 = 10 5 | length rX3 = 10 6 | length DX3 = 10 7 | length rY1 = 10 8 | length DY1 = 10 9 | length rY2 = 10 10 | length DY2 = 10 11 | length rY3 = 10 12 | length DY3 = 10 13 | 14 | sup-sequence X1 = DX1 rX1 15 | sup-sequence X2 = DX2 rX2 16 | sup-sequence X3 = DX3 rX3 17 | sup-sequence Y1 = DY1 rY1 18 | sup-sequence Y2 = DY2 rY2 19 | sup-sequence Y3 = DY3 rY3 20 | 21 | X = X3 X2 X1 22 | Y = Y3 Y2 Y1 DX3 23 | 24 | F1 = Y1 X3( X2( DX1( + rX1* ) ) ) 25 | F2 = Y2 Y1( X3( DX2( + rX2* ) ) ) 26 | F3 = Y3 Y2( Y1( DX3( + rX3* ) ) ) 27 | R = Y3( Y2( DY1( + rY1* ) ) ) 28 | 29 | F1T = Y1 X3 X2 DX1 30 | F2T = Y2 Y1 X3 DX2 31 | RT = Y3 Y2 DY1 32 | 33 | W1 = X3( X2( X1( + ) ) ) 34 | W2 = Y1( X3( X2( DX1 + ) ) ) 35 | W3 = Y2( Y1( X3( DX2 + ) ) ) 36 | W4 = Y3( Y2( Y1( DX3 + ) ) ) 37 | -------------------------------------------------------------------------------- /tests/examples/oldfileformats/3-arm-junction.enum: -------------------------------------------------------------------------------- 1 | domain d1 : 6 2 | domain d2 : 6 3 | domain d3 : 6 4 | 5 | strand n1 = d2* d1* 6 | strand n2 = d1 d2 d3* d2* 7 | strand n3 = d2 d3 d1* d3* 8 | strand n4 = d3 d1 d2* d1* 9 | 10 | complex n1 : 11 | n1 12 | .. 13 | 14 | complex n2 : 15 | n2 16 | .(.) 17 | 18 | complex n3 : 19 | n3 20 | .(.) 21 | 22 | complex n4 : 23 | n4 24 | .(.) 25 | -------------------------------------------------------------------------------- /tests/examples/oldfileformats/DLD_simple_AND.pil: -------------------------------------------------------------------------------- 1 | # A bimolecular DLD AND gate (maybe) 2 | 3 | length a1 = 6 4 | length a2 = 6 5 | length a3 = 6 6 | length b1 = 6 7 | length b2 = 6 8 | length b3 = 6 9 | length c1 = 6 10 | length c2 = 6 11 | length c3 = 6 12 | length d1 = 6 13 | length d2 = 6 14 | length d3 = 6 15 | length x1 = 6 16 | length x2 = 6 17 | length x3 = 6 18 | length y1 = 6 19 | length y2 = 6 20 | length y3 = 6 21 | 22 | 23 | # Input strands 24 | input1 = a1 a2 a3 b1 b2 b3 25 | input2 = c1 c2 c3 d1 d2 d3 26 | 27 | # AND gate 28 | andGate = a2( a3( b1( b2( b3( c1( c2( c3( d1( d2( + d3* ) ) ) ) ) + ) ) ) ) ) a1* 29 | 30 | # Translator gates 31 | transBC2CX = b2( b3( c1( c2( c3( x1 x2 x3 + ) ) ) ) ) b1* 32 | transCX2XY = c2( c3( x1( x2( x3( y1 y2 y3 + ) ) ) ) ) c1* 33 | 34 | # Various waste products and intermediates 35 | andGateI1 = a2 a3 b1 b2 b3 c1( c2( c3( d1( d2( + d3* ) ) ) ) ) 36 | andGateI2 = a2( a3( b1( b2( b3( c1 c2 c3 d1 d2 + ) ) ) ) ) a1* 37 | andGateI3 = a2 a3 b1 b2 b3 c1 c2 c3 d1 d2 38 | #andGateI4 = b2 b3 @60 c1 c2 c3 x1 x2 x3 39 | #andGateI5 = c2 c3 @60 x1 x2 x3 y1 y2 y3 40 | andGateI4 = b2 b3 c1 c2 c3 x1 x2 x3 41 | andGateI5 = c2 c3 x1 x2 x3 y1 y2 y3 42 | input1waste = a1( a2( a3( b1( b2( b3( + ) ) ) ) ) ) 43 | input2waste = c1( c2( c3( d1( d2( d3( + ) ) ) ) ) ) 44 | andGateWaste1 = a2 a3 b1( b2( b3( c1( c2( c3( d1 d2 + ) ) ) ) ) ) 45 | andGateWaste2 = b2 b3 c1( c2( c3( x1( x2( x3( + ) ) ) ) ) ) 46 | 47 | # andGateI5 is also known as the output strand.... 48 | 49 | # Command (on Thachuk's computer): 50 | # ./enumerator.py --max-complex-size 4 --max-complex-count 10000 --max-reaction-count 10000 --release-cutoff-1-1 5 ~/f/src/dsd-leakless/notes/dld-simple-and.pil 51 | 52 | # The following is the desired behavior. Without condensing, you can see that all the detailed rates are in a reasonable range. 53 | # But the release cutoff artificially prevents toehold-sized domains from opening intramolecularly. 54 | # ../../enumerator.py DLD_simple_AND.pil --release-cutoff-1-1 5 -c 55 | 56 | # Here we see that only one super-slow (5x10^-10 /M/s) bimolecular reaction occurs (ignoreing complexes larger than 4): 57 | # ../../enumerator.py DLD_simple_AND.pil --max-complex-size 4 --max-complex-count 10000 --max-reaction-count 10000 -c 58 | 59 | # This would be the most satisfying run, but it results in a singular matrix during condensation. If k-slow worked, perhaps this could be avoided. 60 | # Of course, setting release cutoff 1-1 to 5 (as above) yields an easy and unproblematical enumeration. 61 | # ../../enumerator.py DLD_simple_AND.pil --no-max-helix --max-complex-size 6 --max-complex-count 100000 --max-reaction-count 100000 --release-cutoff-1-n 6 --release-cutoff-1-1 6 -c 62 | 63 | -------------------------------------------------------------------------------- /tests/examples/oldfileformats/DLD_translator_displacement.pil: -------------------------------------------------------------------------------- 1 | 2 | ### Experiment A -- Add an invader to toehold-mediated 3-way displace 3c 3d 4a 4b 4c 5a 3 | 4 | # DLD_translator_displacement.pil 5 | 6 | length 1a = 5 7 | length 1b = 10 8 | length 2a = 5 9 | length 2b = 10 10 | length 3a = 2 11 | length 3b = 3 12 | length 3c = 9 13 | length 3d = 1 14 | length 4a = 2 15 | length 4b = 11 16 | length 4c = 2 17 | length 5a = 2 18 | 19 | #fuel1 = 1b( 2a( 2b( 3a( 3b 3c 3d + )))) 1a* 20 | #fuel2 = 2b( 3a( 3b( 3c( 3d( 4a( 4b 4c + )))))) 2a* 21 | S1 = 3a 3b 3c 3d 4a 4b 4c 22 | FlRep = 3c( 3d( 4a( 4b( 4c( 5a( + )))))) 3b* 3a* 23 | 24 | # ../../enumerator.py --no-max-helix --max-complex-size 3 --max-complex-count 200000 --max-reaction-count 200000 DLD_translator_displacement.pil -c -r 25 | 26 | # In the enumerated output, we find that the strand is indeed displaced 27 | # structure 385 = 3c_3d_4a_4b_4c_5a : ...... 28 | -------------------------------------------------------------------------------- /tests/examples/oldfileformats/DLD_translator_leak.pil: -------------------------------------------------------------------------------- 1 | ### Experiment B - Fuel1 and Fuel2 interact to toehold-mediated 3-way displace 3c 3d 4a 4b 4c 5a 2 | 3 | # DLD_translator_leak.pil 4 | 5 | length 1a = 5 6 | length 1b = 10 7 | length 2a = 5 8 | length 2b = 10 9 | length 3a = 2 10 | length 3b = 3 11 | length 3c = 9 12 | length 3d = 1 13 | length 4a = 2 14 | length 4b = 11 15 | length 4c = 2 16 | length 5a = 2 17 | 18 | fuel1 = 1b( 2a( 2b( 3a( 3b 3c 3d + )))) 1a* 19 | fuel2 = 2b( 3a( 3b( 3c( 3d( 4a( 4b 4c + )))))) 2a* 20 | 21 | # uncomment the complex below if you want to see the reporter interact with any slow leak intermediate 22 | # FlRep = 3c( 3d( 4a( 4b( 4c( 5a( + )))))) 3b* 3a* 23 | 24 | # uncomment the strand below if you want to trigger the reporter directly 25 | # S1 = 3a 3b 3c 3d 4a 4b 4c 26 | 27 | # uncomment the (end result of leak) structure below if you want to see where it occurs 28 | # FF2 = 1b( 2a( 2b( 3a( 3b( 3c( 3d + 4a* )))) 2a* + 2b( 3a( 3b 3c 3d 4a 4b 4c + )))) 1a* 29 | 30 | 31 | # this runs with or without -c, but there is no condensed reaction because in the low-concentration limit, there is no reaction 32 | # ../../enumerator.py --no-max-helix --max-complex-size 6 --max-complex-count 200000 --max-reaction-count 200000 DLD_translator_leak.pil -c -r 33 | 34 | # this runs with or without -c, but there is no condensed reaction here either... k_fast = 0.0002 does not catch the intended intermediate? oops, no, it doesn't. 35 | # ../../enumerator.py --no-max-helix --max-complex-size 6 --max-complex-count 200000 --max-reaction-count 200000 DLD_translator_leak.pil -r --k-fast 0.0002 -c 36 | 37 | # FF2 changes to FF1.5 with rate 0.000935 ... that's what we want to catch as a "slow" unimolecular reaction 38 | # ../../enumerator.py --no-max-helix --max-complex-size 6 --max-complex-count 200000 --max-reaction-count 400000 DLD_translator_leak.pil -r --k-fast 0.001 -c 39 | # kinetic [0.000004 /M/s] fuel1 + fuel2 -> 44559 40 | # kinetic [0.000467 /s] 44559 -> fuel1 + fuel2 41 | 42 | # note that max-complex-size 8 would be desirable, but the above exceeds the max reaction count and doesn't complete the condensing step in a day, in that case. 43 | 44 | -------------------------------------------------------------------------------- /tests/examples/oldfileformats/DLD_translator_leak_reporter.pil: -------------------------------------------------------------------------------- 1 | ### Experiment B - Fuel1 and Fuel2 interact to toehold-mediated 3-way displace 3c 3d 4a 4b 4c 5a 2 | 3 | # DLD_translator_leak.pil 4 | 5 | length 1a = 5 6 | length 1b = 10 7 | length 2a = 5 8 | length 2b = 10 9 | length 3a = 2 10 | length 3b = 3 11 | length 3c = 9 12 | length 3d = 1 13 | length 4a = 2 14 | length 4b = 11 15 | length 4c = 2 16 | length 5a = 2 17 | 18 | # fuel1 = 1b( 2a( 2b( 3a( 3b 3c 3d + )))) 1a* 19 | # fuel2 = 2b( 3a( 3b( 3c( 3d( 4a( 4b 4c + )))))) 2a* 20 | 21 | # uncomment the complex below if you want to see the reporter interact with any slow leak intermediate 22 | FlRep = 3c( 3d( 4a( 4b( 4c( 5a( + )))))) 3b* 3a* 23 | 24 | # uncomment the strand below if you want to trigger the reporter directly. this is an analog of FF2. 25 | S1 = 3a 3b 3c 3d 4a 4b 4c 26 | 27 | # uncomment the (end result of leak) structure below if you want to see where it occurs 28 | # FF2 = 1b( 2a( 2b( 3a( 3b( 3c( 3d + 4a* )))) 2a* + 2b( 3a( 3b 3c 3d 4a 4b 4c + )))) 1a* 29 | 30 | 31 | # this runs with or without -c, and gets a fine result: 32 | # ../../enumerator.py --no-max-helix --max-complex-size 6 --max-complex-count 200000 --max-reaction-count 200000 DLD_translator_leak_reporter.pil -c -r 33 | # kinetic [30666.838217 /M/s] S1 + FlRep -> 43028 + 43007 34 | # kinetic [184.976920 /M/s] 43028 + 43007 -> S1 + FlRep 35 | 36 | 37 | -------------------------------------------------------------------------------- /tests/examples/oldfileformats/DLD_translator_leak_reporter_fuel1.pil: -------------------------------------------------------------------------------- 1 | ### Experiment B - Fuel1 and Fuel2 interact to toehold-mediated 3-way displace 3c 3d 4a 4b 4c 5a 2 | 3 | # DLD_translator_leak.pil 4 | 5 | length 1a = 5 6 | length 1b = 10 7 | length 2a = 5 8 | length 2b = 10 9 | length 3a = 2 10 | length 3b = 3 11 | length 3c = 9 12 | length 3d = 1 13 | length 4a = 2 14 | length 4b = 11 15 | length 4c = 2 16 | length 5a = 2 17 | 18 | fuel1 = 1b( 2a( 2b( 3a( 3b 3c 3d + )))) 1a* 19 | # fuel2 = 2b( 3a( 3b( 3c( 3d( 4a( 4b 4c + )))))) 2a* 20 | 21 | # uncomment the complex below if you want to see the reporter interact with any slow leak intermediate 22 | FlRep = 3c( 3d( 4a( 4b( 4c( 5a( + )))))) 3b* 3a* 23 | 24 | # uncomment the strand below if you want to trigger the reporter directly. this is an analog of FF2. 25 | # S1 = 3a 3b 3c 3d 4a 4b 4c 26 | 27 | # uncomment the (end result of leak) structure below if you want to see where it occurs 28 | # FF2 = 1b( 2a( 2b( 3a( 3b( 3c( 3d + 4a* )))) 2a* + 2b( 3a( 3b 3c 3d 4a 4b 4c + )))) 1a* 29 | 30 | 31 | # this runs with or without -c, and gets a fine result: no reactions 32 | # ../../enumerator.py --no-max-helix --max-complex-size 6 --max-complex-count 200000 --max-reaction-count 200000 DLD_translator_leak_reporter_fuel1.pil -c -r 33 | 34 | # this should check for third-order reactions... also no reactions found 35 | # ../../enumerator.py --no-max-helix --max-complex-size 6 --max-complex-count 200000 --max-reaction-count 200000 DLD_translator_leak_reporter_fuel2.pil -c -r --k-fast 0.001 36 | 37 | 38 | -------------------------------------------------------------------------------- /tests/examples/oldfileformats/DLD_translator_leak_reporter_fuel2.pil: -------------------------------------------------------------------------------- 1 | ### Experiment B - Fuel1 and Fuel2 interact to toehold-mediated 3-way displace 3c 3d 4a 4b 4c 5a 2 | 3 | # DLD_translator_leak.pil 4 | 5 | length 1a = 5 6 | length 1b = 10 7 | length 2a = 5 8 | length 2b = 10 9 | length 3a = 2 10 | length 3b = 3 11 | length 3c = 9 12 | length 3d = 1 13 | length 4a = 2 14 | length 4b = 11 15 | length 4c = 2 16 | length 5a = 2 17 | 18 | # fuel1 = 1b( 2a( 2b( 3a( 3b 3c 3d + )))) 1a* 19 | fuel2 = 2b( 3a( 3b( 3c( 3d( 4a( 4b 4c + )))))) 2a* 20 | 21 | # uncomment the complex below if you want to see the reporter interact with any slow leak intermediate 22 | FlRep = 3c( 3d( 4a( 4b( 4c( 5a( + )))))) 3b* 3a* 23 | 24 | # uncomment the strand below if you want to trigger the reporter directly. this is an analog of FF2. 25 | # S1 = 3a 3b 3c 3d 4a 4b 4c 26 | 27 | # uncomment the (end result of leak) structure below if you want to see where it occurs 28 | # FF2 = 1b( 2a( 2b( 3a( 3b( 3c( 3d + 4a* )))) 2a* + 2b( 3a( 3b 3c 3d 4a 4b 4c + )))) 1a* 29 | 30 | 31 | # this runs with or without -c, and gets a fine result: no reactions. 32 | # ../../enumerator.py --no-max-helix --max-complex-size 6 --max-complex-count 200000 --max-reaction-count 200000 DLD_translator_leak_reporter_fuel2.pil -c -r 33 | 34 | # this should check for third-order reactions... also no reactions found. 35 | # ../../enumerator.py --no-max-helix --max-complex-size 6 --max-complex-count 200000 --max-reaction-count 200000 DLD_translator_leak_reporter_fuel2.pil -c -r --k-fast 0.001 36 | 37 | 38 | -------------------------------------------------------------------------------- /tests/examples/oldfileformats/DLD_translator_leak_simple.pil: -------------------------------------------------------------------------------- 1 | ### Experiment B - Fuel1 and Fuel2 interact to produce a slow intermediate that could react downstream. 2 | 3 | # DLD_translator_leak_simple.pil 4 | 5 | length 1a = 5 6 | length 1b = 10 7 | length 2a = 5 8 | length 2b = 10 9 | length 3a = 2 10 | length 3b = 12 11 | length 3c = 1 12 | length 4a = 2 13 | length 4b = 13 14 | 15 | fuel1 = 1b( 2a( 2b( 3a( 3b 3c + )))) 1a* 16 | fuel2 = 2b( 3a( 3b( 3c( 4a( 4b + ))))) 2a* 17 | 18 | # uncomment the (end result of leak) structure below if you want to see where it occurs 19 | # FF2 = 1b( 2a( 2b( 3a( 3b( 3c( + 4a* )))) 2a* + 2b( 3a( 3b 3c 4a 4b + )))) 1a* 20 | 21 | 22 | # this doesn't find anything, of course. but it's fast. 23 | # ../../enumerator.py --no-max-helix --max-complex-size 6 --max-complex-count 200000 --max-reaction-count 200000 DLD_translator_leak_simple.pil -c -r --release-cutoff-1-1 2 24 | 25 | # this is supposed to find something, and it's reasonably fast, but there appears to be a numerical problem with the condensed kinetics 26 | # ../../enumerator.py --no-max-helix --max-complex-size 8 --max-complex-count 200000 --max-reaction-count 200000 DLD_translator_leak_simple.pil -c -r --k-fast 0.001 --release-cutoff-1-1 2 27 | 28 | # this emits a warning during condensation, but it completes successfully, and (in detailed mode) it appears to find the expected slow leak structure (with an outgoing rate 0.000935) 29 | # ../../enumerator.py --no-max-helix --max-complex-size 8 --max-complex-count 200000 --max-reaction-count 200000 DLD_translator_leak_simple.pil -r --k-fast 0.001 --release-cutoff-1-1 2 -c 30 | # kinetic [0.000003 /M/s] fuel1 + fuel2 -> 8158 31 | # kinetic [0.000467 /s] 8158 -> fuel1 + fuel2 32 | # kinetic [0.000480 /M/s] 8158 + 8158 -> fuel1 + 8158 + fuel2 -------------------------------------------------------------------------------- /tests/examples/oldfileformats/DLD_translator_leak_simple_reporter.pil: -------------------------------------------------------------------------------- 1 | ### Experiment B - Fuel1 and Fuel2 interact to produce a slow intermediate that could react downstream. 2 | 3 | # DLD_translator_leak_simple.pil 4 | 5 | length 1a = 5 6 | length 1b = 10 7 | length 2a = 5 8 | length 2b = 10 9 | length 3a = 2 10 | length 3b = 12 11 | length 3c = 1 12 | length 4a = 2 13 | length 4b = 13 14 | 15 | length 3x = 5 16 | length 3y = 10 17 | length 4 = 15 18 | length 5a = 2 19 | 20 | # fuel1 = 1b( 2a( 2b( 3a( 3b 3c + )))) 1a* 21 | # fuel2 = 2b( 3a( 3b( 3c( 4a( 4b + ))))) 2a* 22 | 23 | # uncomment the (end result of leak) structure below if you want to see where it occurs 24 | # FF2 = 1b( 2a( 2b( 3a( 3b( 3c( + 4a* )))) 2a* + 2b( 3a( 3b 3c 4a 4b + )))) 1a* 25 | 26 | # this is the FF2 analog, but to match domains for the reporter, we re-label it 27 | # S1 = 3b 3c 4a 4b 28 | S1 = 3x 3y 4 29 | 30 | FlRep = 3y( 4( 5a( + ))) 3x* 31 | 32 | # This gets the basic reporter rate constant, according to Peppercorn: 33 | # ../../enumerator.py --no-max-helix --max-complex-size 6 --max-complex-count 200000 --max-reaction-count 200000 DLD_translator_leak_simple_reporter.pil -c -r 34 | # kinetic [570560.736555 /M/s] S1 + FlRep -> 67 + 56 35 | # kinetic [104.017352 /M/s] 67 + 56 -> S1 + FlRep 36 | -------------------------------------------------------------------------------- /tests/examples/oldfileformats/SLC_standard_input.enum: -------------------------------------------------------------------------------- 1 | # This file describes the suppressed-leak catalyst system 2 | # by DY Zhang and K Sarma 3 | 4 | domain 1 : short 5 | domain 2 : short 6 | domain 3 : short 7 | domain 4 : long 8 | domain 5 : short 9 | domain 6 : long 10 | domain 7 : short 11 | 12 | strand PS : 3* 2* 1* 5 6 13 | strand OP : 1 2 3 4 14 | strand SP : 5 6 15 | strand BS : 7* 6* 5* 1 2 3 16 | strand Cat : 6 7 17 | 18 | complex C1 : 19 | PS OP 20 | (((.. + ))). 21 | 22 | complex C2 : 23 | SP BS 24 | (( + .))... 25 | 26 | complex Cat : 27 | Cat 28 | .. 29 | 30 | 31 | 32 | -------------------------------------------------------------------------------- /tests/examples/oldfileformats/SLD_translator_leak.pil: -------------------------------------------------------------------------------- 1 | # 2 base clamps. This description allows fuel2 to be invaded from either side. 2 | # One side is depicted in figure 2b of the paper. 3 | 4 | length 0abc = 10 5 | length 0d = 5 6 | length 1a = 10 7 | length 1b = 5 8 | length 2a = 1 9 | length 2b = 1 10 | length 2c = 8 11 | length 2d = 5 12 | length 3a = 1 13 | length 3b = 1 14 | length 3c = 13 15 | 16 | fuel1 = 1a( 1b( 2a( 2b( 2c 2d + )))) 0d* 17 | fuel2 = 2a( 2b( 2c( 2d( 3a( 3b( 3c + )))))) 1b* 18 | FlRep = 3a( 3b( 3c( + ))) 2d* 19 | 20 | # this runs without -c, but it takes a very long time... when run with -c, ... it also seems to work! 21 | # ../../enumerator.py --no-max-helix --max-complex-size 4 --max-complex-count 200000 --max-reaction-count 200000 SLD_translator_leak.pil -r -c 22 | 23 | 24 | 25 | ### 26 | # for desired pathway rates, uncomment the species below 27 | 28 | #X = 0abc 0d 1a 1b 29 | #flux = 1a 1b 2a 2b 2c 2d 30 | #Y = 2a 2b 2c 2d 3a 3b 3c 31 | #Output = 3a 3b 3c 32 | 33 | # all three fuels can be enumerated together, using the default max-helix semantics: 34 | # ../../enumerator.py SLD_translator_leak.pil -r -c 35 | 36 | # each intended reaction can be enumerated separately, by commenting out 2 of the 3 fuels: 37 | # ../../enumerator.py --no-max-helix --max-complex-size 4 --max-complex-count 200000 --max-reaction-count 200000 SLD_translator_leak.pil -r -c 38 | -------------------------------------------------------------------------------- /tests/examples/oldfileformats/SLD_translator_simpler_leak.pil: -------------------------------------------------------------------------------- 1 | # This specification allows leak initiated only from the 'left' side 2 | # of fuel2 (like figure2b in the paper). 3 | 4 | length 0 = 5 5 | length 1a = 10 6 | length 1b = 5 7 | length 2a = 1 8 | length 2b = 1 9 | length 2c = 13 10 | length 3a = 1 11 | length 3b = 1 12 | length 3c = 13 13 | 14 | fuel1 = 1a( 1b( 2a( 2b( 2c + )))) 0* 15 | fuel2 = 2a( 2b( 2c( 3a( 3b( 3c + ))))) 1b* 16 | 17 | -------------------------------------------------------------------------------- /tests/examples/oldfileformats/TMSD_domain_helix.pil: -------------------------------------------------------------------------------- 1 | # test the effect of breaking toeholds and branch migration domains into subdomains 2 | 3 | length t = 5 4 | length t1 = 2 5 | length t2 = 3 6 | length b = 25 7 | length b1 = 12 8 | length b2 = 1 9 | length b3 = 12 10 | 11 | inputHH = t b 12 | reporterHH = b( + ) t* 13 | 14 | inputDH = t1 t2 b 15 | reporterDH = b( + ) t2* t1* 16 | 17 | inputHD = t b1 b2 b3 18 | reporterHD = b1( b2( b3( + ))) t* 19 | 20 | inputDD = t1 t2 b1 b2 b3 21 | reporterDD = b1( b2( b3( + ))) t2* t1* 22 | 23 | # ../../enumerator.py TMSD_domain_helix.pil -c -r 24 | # kinetic [570686.399729 /M/s] reporterHH + inputHH -> 65 + 64 25 | # kinetic [570686.399729 /M/s] reporterDH + inputDH -> 65 + 90 26 | # kinetic [570686.399729 /M/s] reporterHD + inputHD -> 25 + 41 27 | # kinetic [570686.399729 /M/s] reporterDD + inputDD -> 25 + 24 28 | 29 | # ../../enumerator.py --no-max-helix TMSD_domain_helix.pil -c -r --max-complex-count 1000 --max-reaction-count 10000 30 | # kinetic [570686.399729 /M/s] reporterHH + inputHH -> 12357 + 12359 31 | # kinetic [22365.153621 /M/s] reporterDH + inputDH -> 12357 + 12878 32 | # kinetic [585163.033638 /M/s] reporterHD + inputHD -> 132 + 9939 33 | # kinetic [23275.239723 /M/s] reporterDD + inputDD -> 132 + 154 34 | 35 | # now, with only the DH case uncommented 36 | # ../../enumerator.py --no-max-helix TMSD_domain_helix.pil -r 37 | 38 | # grep " 17" TMSD_domain_helix-enum.pil 39 | # grep " 18" TMSD_domain_helix-enum.pil 40 | # grep " 19" TMSD_domain_helix-enum.pil 41 | # structure 17 = b + b*_t2*_t1* + t1_t2_b : (+).(+).. 42 | # structure 18 = b + b*_t2*_t1* + t1_t2_b : (+)(.+.). 43 | # structure 19 = b + b*_t2*_t1* + t1_t2_b : (+)((+)). 44 | # kinetic [600000.000000 /M/s] reporterDH + inputDH -> 17 45 | # kinetic [900000.000000 /M/s] reporterDH + inputDH -> 18 46 | # kinetic [47644.669800 /s] 17 -> reporterDH + inputDH 47 | # kinetic [4052.179166 /s] 18 -> reporterDH + inputDH 48 | # kinetic [21.712184 /s] 19 -> reporterDH + inputDH (* this shouldn't happen *) 49 | # kinetic [4052.179166 /s] 19 -> 17 50 | # kinetic [333333.333333 /s] 17 -> 19 51 | # kinetic [500000.000000 /s] 18 -> 19 52 | # kinetic [47644.669800 /s] 19 -> 18 53 | # kinetic [0.028775 /s] 17 -> 40 + 51 54 | # kinetic [13.333333 /s] 18 -> 40 + 39 55 | # kinetic [13.333333 /s] 19 -> 40 + 41 56 | -------------------------------------------------------------------------------- /tests/examples/oldfileformats/bounded-dendrimer.enum: -------------------------------------------------------------------------------- 1 | domain 4 : 8 2 | domain 3 : 2 3 | domain 2 : 8 4 | domain 1 : 8 5 | domain 6 : 8 6 | domain 5 : 8 7 | domain 7 : 2 8 | domain 9 : 8 9 | domain 8 : 8 10 | domain 13 : 8 11 | domain 12 : 8 12 | domain 11 : 8 13 | domain 10 : 8 14 | domain 18 : 8 15 | domain 17 : 8 16 | domain 16 : 2 17 | domain 15 : 8 18 | domain 14 : 8 19 | domain 19 : 8 20 | domain 20 : 8 21 | domain 21 : 2 22 | domain 22 : 8 23 | domain 23 : 8 24 | 25 | strand I_m0 = 1* 2* 3* 4* 26 | strand A1_m2 = 4 3 2 1 5* 6* 7* 1* 2* 3* 5* 6* 27 | strand A2_m2 = 1 7 6 5 8* 9* 3* 5* 6* 7* 8* 9* 28 | strand B2_m2 = 2 3 5 6 9* 8* 7* 6* 5* 3* 9* 8* 29 | strand A3_m2 = 5 3 9 8 10* 11* 7* 8* 9* 3* 12* 13* 30 | strand B3_m2 = 6 7 8 9 13* 12* 3* 9* 8* 7* 11* 10* 31 | strand A4_m2 = 8 7 11 10 14* 15* 16* 10* 11* 7* 17* 18* 32 | strand B4_m2 = 9 3 12 13 19* 20* 21* 13* 12* 3* 22* 23* 33 | 34 | complex I : 35 | I_m0 36 | .... 37 | 38 | complex A1 : 39 | A1_m2 40 | .(((...))).. 41 | 42 | complex A2 : 43 | A2_m2 44 | .(((...))).. 45 | 46 | complex B2 : 47 | B2_m2 48 | .(((...))).. 49 | 50 | complex A3 : 51 | A3_m2 52 | .(((...))).. 53 | 54 | complex B3 : 55 | B3_m2 56 | .(((...))).. 57 | 58 | complex A4 : 59 | A4_m2 60 | .(((...))).. 61 | 62 | complex B4 : 63 | B4_m2 64 | .(((...))).. -------------------------------------------------------------------------------- /tests/examples/oldfileformats/catalytic-circuit.enum: -------------------------------------------------------------------------------- 1 | domain 4 : 8 2 | domain 3 : 2 3 | domain 2 : 8 4 | domain 1 : 8 5 | domain 6 : 2 6 | domain 5 : 8 7 | domain 8 : 8 8 | domain 7 : 8 9 | 10 | strand n1 = 4* 3* 2* 1* 11 | strand n2 = 3* 2* 1* 6* 5* 4* 1 2 3 4 12 | strand n3 = 8* 7* 6* 5* 4* 3* 2* 1* 4 5 6 1 13 | strand n4 = 5 6 7 8 5* 4* 3* 8* 7* 6* 14 | strand n5 = 8 3 4 5 8* 7* 6* 5* 4* 3* 2* 1* 15 | 16 | complex n1 : 17 | n1 18 | .... 19 | 20 | complex n2 : 21 | n2 22 | (((...))). 23 | 24 | complex n3 : 25 | n3 26 | ..(((...))). 27 | 28 | complex n4 : 29 | n4 30 | .(((...))) 31 | 32 | complex n5 : 33 | n5 34 | .(((...))).. -------------------------------------------------------------------------------- /tests/examples/oldfileformats/delayedchoice1.enum: -------------------------------------------------------------------------------- 1 | # Example of strand displacement on a bulged duplex that yields a single-stranded species that can fold up two ways. 2 | # The resting state complexes look right, but two structures are named "substrate". 3 | # The transient complexes are too many to check, but two of them are both called "4". 4 | # Condensing the reactions appears to hang. 5 | 6 | domain a : short 7 | domain t : short 8 | domain x : long 9 | domain p : long 10 | 11 | strand folder : x* p* x a* x* p x a 12 | strand bottom : a* x p x t* 13 | strand trigger : t x* p* x* a 14 | 15 | complex substrate : 16 | folder bottom 17 | ((..(..( + )))). 18 | 19 | complex input : 20 | trigger 21 | ..... 22 | 23 | 24 | 25 | -------------------------------------------------------------------------------- /tests/examples/oldfileformats/fate-example.pil: -------------------------------------------------------------------------------- 1 | sequence t = NNNN 2 | sequence d2 = NNNNNNNN 3 | sequence d3 = NNNNNNNN 4 | sequence a = NNNNNNNN 5 | sequence b = NNNNNNNN 6 | sequence c = NNNNNNNN 7 | 8 | strand t23 = t d2 d3 9 | strand 23 = d2 d3 10 | strand 3a = d3* a* 11 | strand gate = a* b* c b a d2* t* 12 | 13 | structure t23 = t23 : ... 14 | structure gate = 23 + 3a + gate : ((+)(+.(.))). 15 | -------------------------------------------------------------------------------- /tests/examples/oldfileformats/genot2011fig3.pil: -------------------------------------------------------------------------------- 1 | # ss-ss remote toeholds from Genot et al 2011, figure 3 -- unimolecular step (we assume the 14-bp toehold doesn't dissociate) 2 | # buffer: TE + 12.5 mM Mg at 25 C and pH 8.0 (paper does not mention carrier DNA) 3 | 4 | length tail = 15 5 | length branch = 22 6 | length toe = 14 7 | length n7 = 7 8 | length n17 = 17 9 | length n20 = 20 10 | length n23 = 23 11 | length m8 = 8 12 | length m17 = 17 13 | length m20 = 20 14 | length m23 = 23 15 | 16 | remote_n7m8 = tail branch( + branch n7 toe( + ) m8 ) 17 | remote_n17m17 = tail branch( + branch n17 toe( + ) m17 ) 18 | remote_n20m20 = tail branch( + branch n20 toe( + ) m20 ) 19 | remote_n23m23 = tail branch( + branch n23 toe( + ) m23 ) 20 | remote_n17m0 = tail branch( + branch n17 toe( + ) ) 21 | remote_n0m17 = tail branch( + branch toe( + ) m17 ) 22 | 23 | # ../../enumerator.py genot2011fig3.pil 24 | 25 | # except for n0m17 (which was too slow to measure experimentally), Peppercorn rates are within 15 of published values. 26 | # mostly, Peppercorn is too slow... 27 | -------------------------------------------------------------------------------- /tests/examples/oldfileformats/genot2011fig4b.pil: -------------------------------------------------------------------------------- 1 | # ss-ss remote toeholds from Genot et al 2011, figure 4b (other panels can be done similarly) 2 | # buffer: TE + 12.5 mM Mg at 25 C and pH 8.0 (paper does not mention carrier DNA) 3 | # 4 | # panel a: t = 9 or 11. s = 0. kinetics saturated at 3x10^6 /M/s and toehold binding is essentially irreversible. 5 | # panel b: t = 9 or 11. s = 1. roughly estimate k = 8x10^5 /M/s and 3x10^6 /M/s respectively (approx 4-fold slowdown). 6 | # panel c: t = 6. s=0. roughly estimate k = 7x10^4 /M/s. (Zhang & Winfree params give 2x10^6 for n=6, 5x10^4 for n=4.) 7 | # panel d: with t=14, these are all rate-limited by the unimolecular step, and thus not compatible with our condensation assumptions. 8 | 9 | # note that since the enumerator uses Zhang & Winfree parameters, the equivalent toehold lengths for panel b would be 6 and 7. 10 | # there is little clear justification for this, other than mysteriously Genot has a slow 6nt toehold rate, 11 | # so we multiply all toehold lengths by 2/3. 12 | 13 | length d = 8 # d + t = 14 for full substrate toehold 14 | length t = 6 15 | length b = 22 16 | length s = 1 17 | invading = t b 18 | remote_substrate = b( + ) s t* d* 19 | proximal_substrate = b( + ) t* d* 20 | 21 | # ../../enumerator.py genot2011fig4b.pil --release-cutoff 8 -c 22 | # 23 | # changing t to 6 and 7 gives 1.5x10^5 /M/s and 1.2x10^6 /M/s respectively for the remote substate (s==1). 24 | # respectively 1.6x10^6 /M/s and 2.1x10^6 /M/s for the proximal substrate (s==0). 25 | # that is, for the shorter toehold, we get a 10-fold slowdown in the model, compared to a 4-fold slowdown in the experiments. 26 | -------------------------------------------------------------------------------- /tests/examples/oldfileformats/genot2013figS3.pil: -------------------------------------------------------------------------------- 1 | # Figure S3 of Anthony Genot et al, Angewandte Chemie 2013, 2 | # "Combinatorial Displacement of DNA Strands: Application to Matrix Multiplication and Weighted Sums" 3 | # buffer: TAE + 12mM Mg++, pH 8.0, 23.5 C (paper does not mention carrier DNA) 4 | # 5 | # measured second order bimolecular rate constant is 4x10^4 /M/s 6 | 7 | length t = 10 8 | length A = 17 9 | length s = 2 10 | length p = 1 11 | length d = 15 12 | length r = 12 13 | 14 | input1 = t s A 15 | input2 = A* s p d 16 | input = t s A( + ) s p d 17 | substrate = d*( p* s t* + ) r 18 | 19 | # ../../enumerator.py genot2013figS3.pil --release-cutoff 10 -c 20 | # 21 | # the five resulting reactions look right, although simulator thinks rates should be much faster with toehold length 10. 22 | # i.e. Peppercorn predicts 3x10^6 /M/s instead of 4x10^4. 23 | # 24 | # we could follow the mysterious 2/3 equivalent toehold length formula from the genot2011fig4b.pil analysis, 25 | # in which case we would use t=6 above. remarkably, that gives input + substrate reacting at 7.5x10^4, off by just x2. 26 | 27 | 28 | -------------------------------------------------------------------------------- /tests/examples/oldfileformats/grun2014fig3.pil: -------------------------------------------------------------------------------- 1 | # Figure 3 of Grun et al 2014 (The Peppercorn Paper) 2 | # 3 | # Domain representation for catalytic formation of 3-arm junction, exactly as shown in figure 2 of 4 | # Yin, Choi, Calvert, Pierce, "Progamming Biomolecular Self-Assembly Pathways", Nature (2008) 5 | # 6 | # (Figure 3 Grun et al uses numbered domains instead of alphabetical, and is somewhat different) 7 | # 8 | # In the experiments of Yin et al, every domain is 6nt. 9 | # That is the default for Peppercorn toeholds, but all those ^'s are ugly, so we'll list them anyway. 10 | 11 | length a = 6 12 | length b = 6 13 | length c = 6 14 | length x = 6 15 | length y = 6 16 | length z = 6 17 | 18 | I = y* b* x* a* 19 | A = a x( b( y( z* c* ))) 20 | B = b y( c( z( x* a* ))) 21 | C = c z( a( x( y* b* ))) 22 | 23 | # ../../enumerator.py grun2014fig3.pil 24 | # more grun2014fig3-enum.pil 25 | 26 | # status as of 10/31/2014: doesn't enumerate some bimolecular reactions 27 | # this is because, in fact, hairpin hybridization is reversible and thus is transient in the low concentration limit 28 | -------------------------------------------------------------------------------- /tests/examples/oldfileformats/grun2014fig3_alt.pil: -------------------------------------------------------------------------------- 1 | # Figure 3 of Grun et al 2014 (The Peppercorn Paper) 2 | # 3 | # Domain representation for catalytic formation of 3-arm junction, from 4 | # Yin, Choi, Calvert, Pierce, "Progamming Biomolecular Self-Assembly Pathways", Nature (2008) 5 | # 6 | # Figure 3 Grun et al uses numbered domains instead of alphabetical, and adds some extra domains. 7 | # And that's what we do here too. 8 | # 9 | # In the experiments of Yin et al, every domain is 6nt. 10 | # That is the default for Peppercorn toeholds, but all those ^'s are ugly, so we'll list them anyway. 11 | 12 | length 1 = 6 13 | length 2 = 6 14 | length 3 = 6 15 | length 4 = 6 16 | length 5 = 6 17 | length 6 = 6 18 | length 7 = 6 19 | length 8 = 6 20 | length 9 = 6 21 | 22 | n1 = 4* 3* 2* 1* 23 | n2 = 3*( 2*( 1*( 7* 6* 5* ))) 4 24 | n3 = 7*( 6*( 5*( 9* 8* 4* ))) 1 25 | n4 = 9*( 8*( 4*( 3* 2* 1* ))) 5 26 | 27 | # ../../enumerator.py grun2014fig3_alt.pil 28 | # more grun2014fig3_alt-enum.pil 29 | 30 | # status as of 10/31/2014: doesn't enumerate some bimolecular reactions 31 | # this is because, in fact, hairpin hybridization is reversible and thus is transient in the low concentration limit -------------------------------------------------------------------------------- /tests/examples/oldfileformats/grun2014fig3_irrev.pil: -------------------------------------------------------------------------------- 1 | # Figure 3 of Grun et al 2014 (The Peppercorn Paper) 2 | # -- modified to have irreversible hairpin-opening steps 3 | # 4 | # Domain representation for catalytic formation of 3-arm junction, exactly as shown in figure 2 of 5 | # Yin, Choi, Calvert, Pierce, "Progamming Biomolecular Self-Assembly Pathways", Nature (2008) 6 | # but with additional 1nt domains that lock the hairping-opening steps 7 | # 8 | # (Figure 3 Grun et al uses numbered domains instead of alphabetical, and is somewhat different) 9 | # 10 | # In the experiments of Yin et al, every domain is 6nt. 11 | # That is the default for Peppercorn toeholds, but all those ^'s are ugly, so we'll list them anyway. 12 | 13 | length a = 6 14 | length b = 6 15 | length c = 6 16 | length x = 6 17 | length y = 6 18 | length z = 6 19 | length r = 1 20 | length s = 1 21 | length t = 1 22 | 23 | I = t* y* b* x* a* 24 | A = a x( b( y( t r* z* c* ))) 25 | B = b y( c( z( r s* x* a* ))) 26 | C = c z( a( x( s t* y* b* ))) 27 | 28 | # ../../enumerator.py grun2014fig3_irrev.pil 29 | # more grun2014fig3_irrev-enum.pil 30 | 31 | # status as of 11/2/2014: works great! 32 | -------------------------------------------------------------------------------- /tests/examples/oldfileformats/multiplicities.pil: -------------------------------------------------------------------------------- 1 | # test whether the enumerator correctly handles cases where there are two distinct reactions that have the same reactants and products 2 | length a = long 3 | length b = long 4 | length c = long 5 | length w = long 6 | length x = long 7 | length y = long 8 | length z = long 9 | 10 | asym = a( b*(+) a*(+) c(+) ) 11 | 12 | sym = a( b*(+) a*(+) b*(+) ) 13 | 14 | symtails = a( b*( x + ) a*( y + ) b*( z + ) ) w 15 | 16 | # ../../enumerator.py multiplicities.pil 17 | 18 | # looks like it's not correct for kinetics. sym should react twice as fast as asym, i.e. the sum of the two symtails reactions. 19 | 20 | # but if we're happy with factors of two... 21 | 22 | # Note: do not use condensation on this example. no reactions are produced. 23 | # this is correct behavior: the initial complexes are not resting complexes, 24 | # and none of the resting complexes that result from their decomposition can react. 25 | -------------------------------------------------------------------------------- /tests/examples/oldfileformats/muscat2011fig1.pil: -------------------------------------------------------------------------------- 1 | # system of Muscat et al 2011 ("A Programmable Molecular Robot"), figure 1. 2 | # SPSC buffer, 200 mM NaCl, 50 mM sodium phosphate, pH 7.5, "room temperature" (paper does not mention carrier DNA) 3 | # not interested in rate constants here, just the pathway enumeration. 4 | # (may want to look at kinetics from figure S5, for example with rate constants) 5 | 6 | length X1 = 7 7 | length X2 = 4 8 | length Y1 = 7 9 | length Y2 = 4 10 | length a = 5 11 | length b = 7 12 | length c = 5 13 | length y = 6 14 | 15 | hairpin = X1 X2 b( c y* ) a* Y1* 16 | robot = a b( c( + ) ) X2* X1* 17 | target = Y1( a b( y + c* ) Y2* ) 18 | moved_robot = a b( c( + ) ) Y2* Y1* 19 | 20 | robohp = X1( X2( b( c( y* b*( a*( Y1* + ) ) c + ) ) ) ) 21 | waste = Y1( a( b( y( + c*( b*( X2*( X1*( + ) ) ) ) ) ) ) ) 22 | 23 | # enumerates "correctly" with all lengths being the default 12 (i.e. comment out all the length statements above.) 24 | # however, this results in an irreversible reaction between 25 | # the fuel and the moved_robot via domain Y1. 26 | 27 | # even so, numerics go negative when condensing. 28 | 29 | # if the actual lengths are used, it seems to hit an infinite loop (with default release cutoff 6) 30 | # even though this does not eliminate the spurious irreversible reaction. 31 | 32 | # with release cutoff 7, too many reactions are produced, but this completes, and gives positive condensed rates: 33 | # ../../enumerator.py muscat2011fig1.pil --release-cutoff 7 --max-complex-count 10000 --max-reaction-count 10000 -c 34 | 35 | 36 | -------------------------------------------------------------------------------- /tests/examples/oldfileformats/qian2011science_fig2_detailed.pil: -------------------------------------------------------------------------------- 1 | # This is the AND/OR gate seesaw network from Figure 2 of Qian & Winfree, Science (2011) 2 | # but implemented explicitly using the details of clamping and extended toeholds on thresholds per figure S16. 3 | 4 | # TAE + 12.5 mM Mg++, at 20C (but sqrt was at 25C) 5 | # (paper does not mention carrier DNA, but Lulu's notebook says 1.7uM poly-T20 carrier for sqrt, others have a bit more or a bit less) 6 | 7 | 8 | # Enumeration explores a variety of remote-toehold-type strand displacement steps involving the 2nt clamp "c". 9 | # These are valid, but seem to lead to some kind of infinite loop in the enumerator, 10 | # even when started with just the "sumgate" by itself. 11 | 12 | length t = 3 13 | length c = 2 14 | length s1a = 4 15 | length s1b = 7 16 | length s2a = 4 17 | length s2b = 7 18 | length s3a = 4 19 | length s3b = 7 20 | length s5a = 4 21 | length s5b = 7 22 | length s6a = 4 23 | length s6b = 7 24 | length s7a = 4 25 | length s7b = 7 26 | 27 | # input1 = c s2a s2b c t c s1a s1b c 28 | # input2 = c s2a s2b c t c s3a s3b c 29 | sumgate = c s5a s5b c(t(c( s2a( s2b( c( + c* t* )))))) 30 | 31 | # threshold = c( s5a( s5b( c( + s2a* c* t* )))) 32 | # ampgate = c s6a s6b c(t(c( s5( s5b( c( + c* t* )))))) 33 | # fuel = c s7a s7b c t c s5a s5b c 34 | # reporter = c( s6a( s6b( c( + c* t* )))) 35 | -------------------------------------------------------------------------------- /tests/examples/oldfileformats/qian_andor.pil: -------------------------------------------------------------------------------- 1 | length T = 5 2 | length S4a = 4 3 | length S4b = 11 4 | length S8a = 4 5 | length S8b = 11 6 | length S9a = 4 7 | length S9b = 11 8 | length S3a = 4 9 | length S3b = 11 10 | length S2a = 4 11 | length S2b = 11 12 | length S1a = 4 13 | length S1b = 11 14 | length S5a = 4 15 | length S5b = 11 16 | length S0a = 4 17 | length S0b = 11 18 | length S6a = 4 19 | length S6b = 11 20 | 21 | x1_Wire_4_to_8 = S4a S4b T S8a S8b 22 | Gate_4_to_1 = S1a S1b T( S4a( S4b( + T* ))) 23 | -------------------------------------------------------------------------------- /tests/examples/oldfileformats/qian_reporter4way.pil: -------------------------------------------------------------------------------- 1 | # reversible 4-way reporter for surface CRNs, as designed and experimentally measured by Lulu Qian and Wei Li (11.7.2014) 2 | 3 | # 3-way initiated 4-way branch migration and strand displacement 4 | length T1 = 6 5 | length T2 = 6 6 | length B = 15 7 | length X = 15 8 | length s = 10 # actually, this is 6, but Peppercorn in that case allows it to pop open, which introduces problems. 9 | length h = 4 10 | signal4 = B X( T2*( + )) T1 11 | reporter4 = T1* s( h ) B*( T1*( + )) 12 | 13 | # compare to standard 3-way toehold-mediated strand displacement 14 | length TT = 6 15 | length BB = 20 16 | signal3 = BB TT 17 | reporter3 = TT* BB*( TT*( + )) 18 | 19 | # compare to associative toehold configuration (not expected to be modeled well) 20 | length Tt1 = 6 21 | length Tt2 = 6 22 | length Bb = 15 23 | length Xx = 15 24 | signalA = Bb Xx( Tt2*( + )) Tt1 25 | reporterA = Tt1* Bb*( Tt1*( + )) 26 | # signalA is exactly the same as signal4, but unique domains to avoid considering crosstalk -------------------------------------------------------------------------------- /tests/examples/oldfileformats/rarerates.pil: -------------------------------------------------------------------------------- 1 | # investigate whether multi-complex resting sets correctly adjust their condensed reaction rates based on equilibrium occupancy 2 | # simple example: a pair of hairpins that, only when both have popped open, can hybridize fully. 3 | 4 | length b = 5 5 | length h = 10 6 | 7 | one = b( h ) 8 | two = b( h* ) -------------------------------------------------------------------------------- /tests/examples/oldfileformats/sadowski-tetrahedron.enum: -------------------------------------------------------------------------------- 1 | domain 1 : 6 2 | domain 2 : 6 3 | domain 3 : 6 4 | domain 4 : 6 5 | domain 5 : 6 6 | domain 6 : 6 7 | domain 7 : 6 8 | domain 8 : 6 9 | domain 9 : 6 10 | domain 10 : 6 11 | domain 11 : 6 12 | domain 12 : 6 13 | domain 13 : 6 14 | domain 14 : 6 15 | domain 15 : 6 16 | domain 16 : 6 17 | domain 17 : 6 18 | domain 18 : 6 19 | 20 | strand n1 = 1* 2* 3* 4* 5* 3 2 6* 7* 21 | strand n2 = 3* 5 4 1 8* 4* 5* 9* 10* 22 | strand n3 = 4 8 1* 3 2 1 8* 11* 12* 23 | strand n4 = 7 6 2* 7* 13* 10 14* 6* 24 | strand n5 = 6 14 10* 15* 10 14* 25 | strand n6 = 10 9 5 10* 15 12 16* 9* 26 | strand n7 = 9 16 12* 17* 12 16* 27 | strand n8 = 12 11 8 12* 17 7 18* 11* 28 | strand n9 = 11 18 7* 13 7 18* 29 | strand n10 = 3 2 1 30 | 31 | complex n1 : 32 | n1 33 | .((..)).. 34 | 35 | complex n2 : 36 | n2 37 | .((..)).. 38 | 39 | complex n3 : 40 | n3 41 | .((..)).. 42 | 43 | complex n4 : 44 | n4 45 | ..((.)). 46 | 47 | complex n5 : 48 | n5 49 | .((.)) 50 | 51 | complex n6 : 52 | n6 53 | ..((.)). 54 | 55 | complex n7 : 56 | n7 57 | .((.)) 58 | 59 | complex n8 : 60 | n8 61 | ..((.)). 62 | 63 | complex n9 : 64 | n9 65 | .((.)) 66 | 67 | complex n10 : 68 | n10 69 | ... -------------------------------------------------------------------------------- /tests/examples/oldfileformats/sarma2010_biggate.in: -------------------------------------------------------------------------------- 1 | # trying to find the minimal subset of gate.in that produces the polymer bug, but here it's finite. 2 | # But lots of transients and reactions that I haven't checked. 3 | # The resting-state complexes look right, at first glance at least. 4 | domain 1 : long 5 | domain 2 : short 6 | domain 3 : short 7 | domain 4 : long 8 | domain 5 : short 9 | 10 | # a strands refer to blue "top" strands, labeled left to right 11 | strand a1 : 1 4* 3 12 | strand a2 : 1 4* 13 | strand a3 : 5 1 14 | strand a4 : 5 1 3 15 | 16 | # b strands refer to bottom strands, labeled left to right 17 | strand b1 : 3* 4 1* 1* 18 | strand b2 : 4 1* 5* 4 19 | 20 | complex In : 21 | a1 22 | ... 23 | 24 | complex G1 : 25 | a2 b1 26 | (( + .)). 27 | 28 | -------------------------------------------------------------------------------- /tests/examples/oldfileformats/sarma2010_fig1.in: -------------------------------------------------------------------------------- 1 | # Figure 1 from Sarma2010report.pdf 2 | 3 | domain 1 : long 4 | domain 2 : long 5 | 6 | strand a1 : 1 2 7 | strand a2 : 2 8 | strand b1 : 2* 1* 9 | 10 | complex initial : 11 | a1 a2 b1 12 | (. + ( + )) 13 | -------------------------------------------------------------------------------- /tests/examples/oldfileformats/sarma2010_fig2.in: -------------------------------------------------------------------------------- 1 | # Figure 2 from Sarma2010report.pdf, which is the entropy-driven catalyst from Zhang et al, Science, 2007 2 | # The intermediate complexes I1, I2, I3, I4, I5, I6 are not explicitly given; the enumerator labels them 0,3,4,7,12,17. 3 | # Also note that the detailed reactions enumerated are more complete than in Figure 2 (e.g. unproductive C + W binding 4 | # and an alternate pathway for 4+F->OP+C+W) but that the condensed reactions show less details than in Figure 2. 5 | 6 | domain 1 : long 7 | domain 2 : long 8 | domain 3 : short 9 | domain 4 : long 10 | domain 5 : short 11 | domain 6 : long 12 | 13 | strand c : 4 5 14 | strand sig : 6 3 4 15 | strand out : 1 2 16 | strand bot : 5* 4* 3* 2* 17 | strand fuel : 2 3 4 18 | 19 | complex C : 20 | c 21 | .. 22 | 23 | complex S : 24 | out sig bot 25 | .( + .(( + .))) 26 | 27 | complex SB : 28 | sig 29 | ... 30 | 31 | complex F : 32 | fuel 33 | ... 34 | 35 | complex OP : 36 | out 37 | .. 38 | 39 | complex W : 40 | fuel bot 41 | ((( + .))) 42 | -------------------------------------------------------------------------------- /tests/examples/oldfileformats/sarma2010_fig3.in: -------------------------------------------------------------------------------- 1 | # Figure 3 from Sarma2010report.pdf 2 | # Correctly computes the complexes, but gives them weird names. 3 | 4 | domain 1 : long 5 | domain 2 : long 6 | domain 3 : long 7 | domain 4 : long 8 | domain 5 : long 9 | domain 6 : long 10 | domain 7 : long 11 | 12 | strand h : 1* 2 1 13 | strand a : 1 2 14 | strand b : 3 4 5 15 | strand c : 5* 7 16 | strand d : 7* 6 3* 1* 17 | 18 | complex open : 19 | h 20 | ... 21 | 22 | complex initial : 23 | a b c d 24 | (. + (.. + .( + ).)) 25 | 26 | 27 | -------------------------------------------------------------------------------- /tests/examples/oldfileformats/sarma2010_fig4.in: -------------------------------------------------------------------------------- 1 | # Figure 4 from Sarma2010report.pdf 2 | # Correctly computes the steps shown, plus a bunch more subsequent steps and cross-interaction steps, in detailed mode. 3 | # But hangs when trying to compute the condensed reactions. 4 | 5 | domain 1 : long 6 | domain 2 : long 7 | domain 3 : short 8 | domain 4 : long 9 | domain 5 : short 10 | domain 6 : long 11 | domain 7 : short 12 | 13 | strand h1 : 1 14 | strand h2 : 1* 15 | strand a1 : 3* 2* 1* 5 6 16 | strand a2 : 1 2 3 4 17 | strand b1 : 6 7 18 | strand b2 : 7* 6* 5* 1 2 3 19 | 20 | complex top : 21 | h1 22 | . 23 | 24 | complex bot : 25 | h2 26 | . 27 | 28 | complex com1 : 29 | a1 a2 30 | (((.. + ))). 31 | 32 | complex com2 : 33 | b1 b2 34 | (( + )).... 35 | 36 | 37 | 38 | -------------------------------------------------------------------------------- /tests/examples/oldfileformats/sarma2010_gate.in: -------------------------------------------------------------------------------- 1 | # Figure 10 from Sarma2010report.pdf 2 | domain 1 : long 3 | domain 2 : short 4 | domain 3 : short 5 | domain 4 : long 6 | domain 5 : short 7 | 8 | # a strands refer to blue "top" strands, labeled left to right 9 | strand a1 : 1 4* 3 10 | strand a2 : 1 4* 11 | strand a3 : 5 1 12 | strand a4 : 5 1 3 13 | 14 | # b strands refer to bottom strands, labeled left to right 15 | strand b1 : 3* 4 1* 1* 16 | strand b2 : 4 1* 5* 4 17 | 18 | complex In : 19 | a1 20 | ... 21 | 22 | complex G1 : 23 | a2 b1 24 | (( + .)). 25 | 26 | complex I1 : 27 | a2 a1 b1 28 | (. + .(( + ))). 29 | 30 | complex T : 31 | a2 32 | .. 33 | 34 | complex G2 : 35 | a3 b2 36 | (( + .)). 37 | 38 | complex I2 : 39 | a3 a2 b2 40 | (. + (( + ))). 41 | 42 | complex Out : 43 | a4 44 | ... 45 | 46 | complex P1 : 47 | a2 a3 a2 b2 a1 b1 48 | (( + (. + (( + )))) + .(( + ))). -------------------------------------------------------------------------------- /tests/examples/oldfileformats/sarma2010_hybridize.in: -------------------------------------------------------------------------------- 1 | # This is a test of the resting state / transient state dichotomy during enumeration. 2 | # Without it, hybridizing strands with two long domains will lead to enumeration of infinite polymers. 3 | # However, successfully, no infinite polymers are formed. 4 | domain 1 : long 5 | domain 2 : short 6 | domain 3 : short 7 | domain 4 : long 8 | domain 5 : short 9 | 10 | # a strands refer to blue "top" strands, labeled left to right 11 | strand a1 : 1 4* 3 12 | strand a2 : 1 4* 13 | strand a3 : 5 1 14 | strand a4 : 5 1 3 15 | 16 | # b strands refer to bottom strands, labeled left to right 17 | strand b1 : 3* 4 1* 1* 18 | strand b2 : 4 1* 5* 4 19 | 20 | complex G1top : 21 | a2 22 | .. 23 | 24 | complex G1bot : 25 | b1 26 | .... 27 | 28 | complex G1 : 29 | a2 b1 30 | (( + .)). 31 | 32 | -------------------------------------------------------------------------------- /tests/examples/oldfileformats/sarma2010_hybridizelong.in: -------------------------------------------------------------------------------- 1 | # This is a test of remote toeholds for 1-1 3-way branch migration. A slight variant of hybridize.in 2 | # Behaves identical to hybridize.in, as it should. 3 | # Of course with rates, the intramolecular reactions should be slower. 4 | 5 | domain 1 : long 6 | domain 2 : short 7 | domain 3 : short 8 | domain 4 : long 9 | domain 5 : short 10 | 11 | # a strands refer to blue "top" strands, labeled left to right 12 | strand a1 : 1 4* 3 13 | strand a2 : 1 4* 14 | strand a3 : 5 1 15 | strand a4 : 5 1 3 16 | strand a5 : 1 5 4* 17 | 18 | # b strands refer to bottom strands, labeled left to right 19 | strand b1 : 3* 4 1* 1* 20 | strand b2 : 4 1* 5* 4 21 | strand b3 : 3* 4 1* 3* 1* 22 | 23 | complex G1toplong : 24 | a5 25 | ... 26 | 27 | complex G1botlong : 28 | b3 29 | ..... 30 | 31 | complex G1long : 32 | a5 b3 33 | (.( + .)).. 34 | 35 | -------------------------------------------------------------------------------- /tests/examples/oldfileformats/sarma2010_mediumgate.in: -------------------------------------------------------------------------------- 1 | # trying to find the minimal subset of gate.in that produces the polymer bug, but here it's finite. 2 | # But lots of transients and reactions that I haven't checked. 3 | # The resting-state complexes look right. 4 | domain 1 : long 5 | domain 2 : short 6 | domain 3 : short 7 | domain 4 : long 8 | domain 5 : short 9 | 10 | # a strands refer to blue "top" strands, labeled left to right 11 | strand a1 : 1 4* 3 12 | strand a2 : 1 4* 13 | strand a3 : 5 1 14 | strand a4 : 5 1 3 15 | 16 | # b strands refer to bottom strands, labeled left to right 17 | strand b1 : 3* 4 1* 1* 18 | strand b2 : 4 1* 5* 4 19 | 20 | complex In : 21 | a1 22 | ... 23 | 24 | complex G2 : 25 | a3 b2 26 | (( + .)). 27 | 28 | -------------------------------------------------------------------------------- /tests/examples/oldfileformats/sarma2010_polymer.in: -------------------------------------------------------------------------------- 1 | # finding the minimal subset of gate.in that produces the polymer bug (if it is a bug) 2 | # still not sure what's happening here 3 | domain 1 : long 4 | domain 2 : short 5 | domain 3 : short 6 | domain 4 : long 7 | domain 5 : short 8 | 9 | # a strands refer to blue "top" strands, labeled left to right 10 | strand a1 : 1 4* 3 11 | strand a2 : 1 4* 12 | strand a3 : 5 1 13 | strand a4 : 5 1 3 14 | 15 | # b strands refer to bottom strands, labeled left to right 16 | strand b1 : 3* 4 1* 1* 17 | strand b2 : 4 1* 5* 4 18 | 19 | complex In : 20 | a1 21 | ... 22 | 23 | complex G1 : 24 | a2 b1 25 | (( + .)). 26 | 27 | complex G2 : 28 | a3 b2 29 | (( + .)). 30 | 31 | -------------------------------------------------------------------------------- /tests/examples/oldfileformats/sarma2010_smallgate.in: -------------------------------------------------------------------------------- 1 | # gate.in enumerates to an error, suggesting polymer formation. G1, G2, In is a minimal error input. 2 | # Here, the input G1, G2, Out produces a finite reaction graph. 3 | domain 1 : long 4 | domain 2 : short 5 | domain 3 : short 6 | domain 4 : long 7 | domain 5 : short 8 | 9 | # a strands refer to blue "top" strands, labeled left to right 10 | strand a1 : 1 4* 3 11 | strand a2 : 1 4* 12 | strand a3 : 5 1 13 | strand a4 : 5 1 3 14 | 15 | # b strands refer to bottom strands, labeled left to right 16 | strand b1 : 3* 4 1* 1* 17 | strand b2 : 4 1* 5* 4 18 | 19 | complex Out : 20 | a4 21 | ... 22 | 23 | complex G1 : 24 | a2 b1 25 | (( + .)). 26 | 27 | complex G2 : 28 | a3 b2 29 | (( + .)). 30 | 31 | -------------------------------------------------------------------------------- /tests/examples/oldfileformats/sarma2010_transient.in: -------------------------------------------------------------------------------- 1 | # Test to see if an input complex that is a transient will be handled correctly. 2 | # Also test to see if a single-toehold-mediated 4-way branch migration is handled correctly. 3 | # Answer is yes to to both. 4 | domain 1 : long 5 | domain 2 : short 6 | domain 3 : short 7 | domain 4 : long 8 | domain 5 : short 9 | 10 | # a strands refer to blue "top" strands, labeled left to right 11 | strand a1 : 1 4* 3 12 | strand a2 : 1 4* 13 | strand a3 : 5 1 14 | strand a4 : 5 1 3 15 | 16 | # b strands refer to bottom strands, labeled left to right 17 | strand b1 : 3* 4 1* 1* 18 | strand b2 : 4 1* 5* 4 19 | 20 | complex Transient : 21 | a1 b1 a2 b2 22 | ((( + )((. + )) + )).. 23 | 24 | 25 | -------------------------------------------------------------------------------- /tests/examples/oldfileformats/seelig2006_fig2c.enum: -------------------------------------------------------------------------------- 1 | # Thresholding demonstration circuit from Seelig et al, Science 2006, Figure 2c 2 | # Encoded for the enumerator by E. Winfree 6/26/2012 3 | 4 | # Using lowercase for toeholds and short domains; uppercase for longer domains. 5 | # Domain lengths agree with those in the paper; domain names are new since none were used in the paper. 6 | # Note that we assume the enumerator is case-sensitive. 7 | domain a : 6 8 | domain b : 6 9 | domain c : 3 10 | domain D : 27 11 | domain e : 3 12 | domain E : 12 13 | domain f : 6 14 | domain g : 6 15 | domain H : 15 16 | domain i : 6 17 | domain J : 24 18 | domain k : 6 19 | domain L : 15 20 | 21 | # Strand names are identical to those in the paper. 22 | strand A_out = k i H e f g L 23 | strand Th2_in = i* J* g* 24 | strand Th1_short = g* f* e* H* i* 25 | strand Th2 = H e f g J i 26 | strand Th1 = g* f* e* H* i* J* 27 | strand Th_out = H a b c E e f g 28 | strand P_f = f* e* E* c* b* a* 29 | strand Q_out = a b c D E e 30 | 31 | # Only the initial complexes that were put in the test tube are defined. (Shown in Figure 2c.) 32 | # The rest must be enumerated. (Almost: for convenience, we add the intermediate and output signals.) 33 | complex Input : 34 | A_out 35 | ....... 36 | 37 | complex AndGate3 : 38 | Th1 Th1_short Th2 Th_out 39 | (((((( + ((((. + )))))) + )....))) 40 | 41 | complex Helper : 42 | Th2_in 43 | ... 44 | 45 | complex Reporter : 46 | P_f Q_out 47 | .((((( + ))).)) 48 | 49 | complex Signal : 50 | Th_out 51 | ........ 52 | 53 | complex Output : 54 | Q_out 55 | ...... 56 | 57 | -------------------------------------------------------------------------------- /tests/examples/oldfileformats/seelig2006_fig2c_error.enum: -------------------------------------------------------------------------------- 1 | # Thresholding demonstration circuit from Seelig et al, Science 2006, Figure 2c 2 | # Encoded for the enumerator by E. Winfree 6/26/2012 3 | 4 | # Using lowercase for toeholds and short domains; uppercase for longer domains. 5 | # Domain lengths agree with those in the paper; domain names are new since none were used in the paper. 6 | # Note that we assume the enumerator is case-sensitive. 7 | domain a : 6 8 | domain b : 6 9 | domain c : 3 10 | domain D : 27 11 | domain e : 3 12 | domain E : 12 13 | domain f : 6 14 | domain g : 6 15 | domain H : 15 16 | domain i : 6 17 | domain J : 24 18 | domain k : 6 19 | domain L : 15 20 | 21 | # Strand names are identical to those in the paper. 22 | strand A_out = k i H e f g L 23 | strand Th2_in = i* J* g* 24 | strand Th1_short = g* f* e* H* i* 25 | strand Th2 = H e f g J i 26 | strand Th1 = g* f* e* H* i* J* 27 | strand Th_out = H a b c E e f g 28 | strand P_f = f* e* E* c* b* a* 29 | strand Q_out = a b c D E e 30 | 31 | # Only the initial complexes that were put in the test tube are defined. (Shown in Figure 2c.) 32 | # The rest must be enumerated. (Almost: for convenience, we add the intermediate and output signals.) 33 | complex Input : 34 | A_out 35 | ....... 36 | 37 | complex AndGate3 : 38 | Th1 Th1_short Th2 Th_out 39 | (((((( + ((((. + )))))) + )....))) 40 | 41 | complex Helper : 42 | Th2_in 43 | ... 44 | 45 | complex Reporter : 46 | P_f Q_out 47 | (((((. + )).))) 48 | 49 | complex Signal : 50 | Th_out 51 | ........ 52 | 53 | complex Output : 54 | Q_out 55 | ...... 56 | 57 | -------------------------------------------------------------------------------- /tests/examples/oldfileformats/seesaw.enum: -------------------------------------------------------------------------------- 1 | domain S1 : 15 2 | domain S2 : 15 3 | domain S3 : 15 4 | domain S4 : 15 5 | domain T : 5 6 | 7 | strand S1_T_S3 = S1 T S3 8 | strand T_S3_T = T* S3* T* 9 | strand S3_T_S4 = S3 T S4 10 | strand S2_T_S3 = S2 T S3 11 | 12 | complex Gate : 13 | S1_T_S3 T_S3_T 14 | .(( + .)) 15 | 16 | complex Input : 17 | S3_T_S4 18 | ... 19 | 20 | complex Fuel : 21 | S2_T_S3 22 | ... 23 | 24 | complex Waste : 25 | S2_T_S3 T_S3_T 26 | .(( + .)) 27 | 28 | complex Output : 29 | S1_T_S3 30 | ... 31 | 32 | complex Intermediate : 33 | S3_T_S4 T_S3_T 34 | ((. + )). 35 | -------------------------------------------------------------------------------- /tests/examples/oldfileformats/seesaw2.enum: -------------------------------------------------------------------------------- 1 | domain S1 : 15 2 | domain S2 : 15 3 | domain S3 : 15 4 | domain S4 : 15 5 | domain T : 5 6 | 7 | strand S2_T_S3_T = S2 T S3 T* 8 | strand T_S3 = T* S3* 9 | strand S2_T_S3 = S2 T S3 10 | 11 | complex C1 : 12 | S2_T_S3_T T_S3 13 | .((. + )) 14 | 15 | complex C2 : 16 | S2_T_S3 17 | ... 18 | 19 | complex C3 : 20 | S2_T_S3_T S2_T_S3 T_S3 21 | .((( + .). + )) -------------------------------------------------------------------------------- /tests/examples/oldfileformats/srinivas_P_CApAq.pil: -------------------------------------------------------------------------------- 1 | 2 | length hI = 15 3 | length sI = 7 4 | length mI = 15 5 | length sX = 7 6 | length mX = 15 7 | length fX = 7 8 | length hY = 15 9 | flux_strand = hI sI mI 10 | produce_gate = sX mX fX( hY( + sX mX fX( hI( + sI* )))) 11 | output_strand = sX mX fX hI 12 | intermediate = sX mX fX( hY( + hI( sI( mI + )) fX* )) 13 | 14 | # ../../enumerator.py srinivas_P_CApAq.pil --release-cutoff 8 -c 15 | -------------------------------------------------------------------------------- /tests/examples/oldfileformats/venkataraman2007.pil: -------------------------------------------------------------------------------- 1 | sequence a = NNNNNN 2 | sequence c = NNNNNN 3 | sequence b = NNNNNNNNNNNNNNNNNN 4 | sequence x = NNN 5 | sequence y = NNN 6 | 7 | strand h1 = a b c b* x* 8 | strand h2 = y* b* a* b c* 9 | strand A = b* a* 10 | strand R = x b y 11 | 12 | structure h1 = h1 : .(.). 13 | structure h2 = h2 : .(.). 14 | structure AR = A R : (.+.). 15 | -------------------------------------------------------------------------------- /tests/examples/oldfileformats/xichen2012fig2.pil: -------------------------------------------------------------------------------- 1 | # Figure 2 of Xi Chen, JACS 2012, Expanding the rule set of DNA circuitry with associative toehold activation. 2 | # TNKMg = 20 mM Tris + 140 mM NaCl + 5 mM KCl + 5 mM MgCl2 + 0.5 mM EDTA all at 37 C (plus 1 uM carrier dT21), pH 7.5 3 | # 4 | # values read "by eye" from figure 2: 5 | # 6 | # for direct associative toeholds (1 stem, 0 bases in intervening loop) 7 | # toehold lengths 8, 10, 14 give second order bimolecular rate constants 6x10^2, 8x10^3, 1x10^5 /M/s (w/o 2nt spacer) 8 | # 9 | # for bulged associative toeholds (1 stem, 2 bases in intervening loop) 10 | # toehold lengths 8, 10, 14 give second order bimolecular rate constants 3x10^3, 5x10^4, 2x10^5 /M/s (w/ 2nt spacer) 11 | # 12 | # compared to regular toehold-mediated strand displacement (0 stems, 0 bases) 13 | # toehold length 8 gives second order bimolecular rate constants 2x10^5 /M/s 14 | # 15 | # these experimental results are at 37 C, in a less stabilizing buffer, while our rate formulas are for 25 C in a stronger buffer. 16 | # it might make sense, therefore, to approximate T = 8 @ 37C using T = 5 @ 25 C, for which the model gives regular displacement 5x10^5 /M/s. 17 | # Similarly, 6 and 8 as 25C equivalents for the 10 and 14 at 37C cases. 18 | # But since we don't know branch migration and initiation rates at 37C, this is a shot in the dark. 19 | 20 | length T = 5 21 | length D = 24 22 | length C = 3 23 | length P = 19 24 | length h = 9 25 | length p = 2 26 | length b = 2 27 | 28 | substrate = C( D( T + )) P 29 | direct_invader = T* h(p) D* 30 | bulged_invader = T* b h(p) D* 31 | invader = T* D* 32 | 33 | # ../../enumerator.py xichen2012fig2.pil --release-cutoff 8 -c 34 | # more xichen2012fig2-enum.pil 35 | # 36 | # this generates a lot of detailed reactions, but the condensed reactions seem plausible, 37 | # other than the remote toehold slowdown not being enough using the original toehold lengths. 38 | # so, we will change to use T=5, or T=6, or T=8, above. 39 | # 40 | # for the associative toehold reactions, the bulged case works out well after "toehold length conversion": 41 | # 2x10^3 (model T=5) vs 3x10^3 (exp T=8), 3x10^4 (model T=6) vs 5x10^4 (exp T=10), 2x10^6 (model T=8) vs 2x10^5 (exp T=14) 42 | # for the "direct" case, the enumerator model doesn't predict the experimentally observed 2x to 5x slowdown; in fact it slightly speeds up. 43 | # 44 | # that's generally good, but there is a lot of the combinatorics prior to condensation (due to the hairpin opening?) 45 | # and some "slow reaction" rates go negative during the condensation, even when only one invader strand is used. (e.g. for T=5 and T=6) 46 | # 47 | # so (a) there is a numerics issue, and (b) we might want to have a different release-cutoff for 1-1 and 1-2 reactions. 48 | # 49 | # overall conclusion is that the remote-toehold initiation rate formula is not ridiculously bad. 50 | # we could consider special-casing some slow-down for non-bulged intiation, but this is just one of a thousand special cases 51 | # where the domain-level model is too simple to be very accurate. 52 | -------------------------------------------------------------------------------- /tests/examples/oldfileformats/zhang2007fig1.pil: -------------------------------------------------------------------------------- 1 | # Figure 1 of David Yu Zhang et al, "Engineering entropy-driven reactions and networks catalyzed by DNA" 2 | 3 | length 1 = 10 4 | length 2 = 24 5 | length 3 = 4 6 | length 4 = 16 7 | length 5 = 6 8 | length 6 = 16 9 | 10 | F = 2 3 4 11 | C = 4 5 12 | S = 1 2( + 6 3( 4( + 5* ))) 13 | W = 2( 3( 4( + 5* ))) 14 | SB = 6 3 4 15 | OB = 1 2 16 | 17 | I3 = 1 2( + 4( 5( + )) 3* ) 18 | 19 | -------------------------------------------------------------------------------- /tests/examples/oldfileformats/zhang2011fig1.pil: -------------------------------------------------------------------------------- 1 | # Figure 1 of David Yu Zhang, "Cooperative hybridization of oligonucleotides", JACS, 2012 2 | 3 | length 1 = 8 4 | length 2 = 18 5 | length 3 = 18 6 | length 4 = 8 7 | 8 | target_T1 = 1 2 9 | target_T2 = 3 4 10 | complex_D1 = 2( 3( + 4* ) ) 1* 11 | complex_end = 2 3 12 | 13 | # this does fine with and without -c, but no net reaction occurs, but that's correct for the low-concentration limit 14 | # ../../enumerator.py --release-cutoff 8 zhang2011fig1.pil -r 15 | 16 | # this creates some additional resting state complexes, and thus enables the desired multistep pathway for cooperative hybridization. 17 | # ../../enumerator.py --release-cutoff 8 zhang2011fig1.pil -r --k-fast 0.01 18 | # works fine with or without -c 19 | 20 | -------------------------------------------------------------------------------- /tests/test_input.py: -------------------------------------------------------------------------------- 1 | # 2 | # tests/test_input.py 3 | # 4 | import logging 5 | logger = logging.getLogger('peppercornenumerator') 6 | logger.setLevel(logging.INFO) 7 | import unittest 8 | 9 | from dsdobjects import SingletonError, clear_singletons 10 | from peppercornenumerator.input import read_pil 11 | from peppercornenumerator.objects import PepperDomain, PepperComplex, PepperMacrostate, PepperReaction 12 | 13 | SKIP = False 14 | 15 | @unittest.skipIf(SKIP, "skipping tests.") 16 | class TestPilIO(unittest.TestCase): 17 | def tearDown(self): 18 | clear_singletons(PepperDomain) 19 | clear_singletons(PepperComplex) 20 | clear_singletons(PepperMacrostate) 21 | clear_singletons(PepperReaction) 22 | 23 | def test_read_pil_01(self): 24 | complexes, reactions = read_pil( 25 | """ 26 | # Domains (12) 27 | sequence a = NNNNNN 28 | sequence b = NNNNNN 29 | sequence c = NNNNNN 30 | sequence x = NNNNNN 31 | sequence y = NNNNNN 32 | sequence z = NNNNNN 33 | 34 | # Resting complexes (8) 35 | A = a x( b( y( z* c* ) ) ) @i 1e-08 M 36 | B = b y( c( z( x* a* ) ) ) @i 1e-08 M 37 | C = c z( a( x( y* b* ) ) ) @i 1e-08 M 38 | I = y* b* x* a* @i 1e-08 M 39 | 40 | IA = a( x( b( y( z* c* y* b* x* + ) ) ) ) @i 0.0 M 41 | IAB = y*( b*( x*( a*( + ) ) ) ) z*( c*( y*( b*( x* + ) ) ) ) x* a* z* c* y* @i 0.0 M 42 | IABC = y*( b*( x*( a*( + ) ) ) ) z*( c*( y*( b*( x* + ) ) ) ) x*( a*( z*( c*( y* + ) ) ) ) y* b* x* a* z* @i 0.0 M 43 | ABC = a( x( b( y( z*( c*( y*( b*( x* + ) ) ) ) x*( a*( z*( c*( y* + ) ) ) ) ) ) ) ) z* @i 0.0 M 44 | 45 | # Resting macrostates (8) 46 | macrostate A = [A] 47 | macrostate B = [B] 48 | macrostate C = [C] 49 | macrostate I = [I] 50 | macrostate IA = [IA] 51 | macrostate IAB = [IAB] 52 | macrostate IABC = [IABC] 53 | macrostate ABC = [ABC] 54 | 55 | # Condensed reactions (10) 56 | reaction [condensed = 1.66666e+06 /M/s ] A + I -> IA 57 | reaction [condensed = 1.66666e+06 /M/s ] IA + B -> IAB 58 | reaction [condensed = 1.66646e+06 /M/s ] IAB + C -> IABC 59 | reaction [condensed = 0.0261637 /s ] IABC -> ABC + I 60 | """) 61 | 62 | # A preliminary interface to start testing prototype functions. 63 | #a, b, c = dom['a'], dom['b'], dom['c'] 64 | #assert a is PepperDomain('a') 65 | #assert b is PepperDomain('b') 66 | #assert c is PepperDomain('c') 67 | assert PepperComplex(None, None, 'IA').kernel_string == 'a( x( b( y( z* c* y* b* x* + ) ) ) )' 68 | #assert PepperMacrostate(None, 'A').kernel_string == 'a x( b( y( z* c* ) ) )' 69 | #PepperReaction(None, None, None, name = '[condensed] A + I -> IA') 70 | -------------------------------------------------------------------------------- /tests/test_objects.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python 2 | # 3 | # test_objects.py 4 | # EnumeratorProject 5 | # 6 | import unittest 7 | 8 | from peppercornenumerator.objects import (SingletonError, 9 | clear_memory, 10 | ObjectInitError, 11 | PepperDomain, 12 | PepperComplex, 13 | Loop) 14 | 15 | SKIP = False 16 | 17 | @unittest.skipIf(SKIP, "skipping tests") 18 | class TestPepperDomain(unittest.TestCase): 19 | def tearDown(self): 20 | clear_memory() 21 | 22 | def test_domain_length(self): 23 | foo = PepperDomain('foo', dtype = 'short') 24 | bar = PepperDomain('bar', dtype = 'long') 25 | assert foo.length < bar.length 26 | 27 | def test_new_constructor(self): 28 | with self.assertRaises(SingletonError): 29 | bar = PepperDomain('foo') 30 | 31 | foo = PepperDomain('foo', dtype = 'short') 32 | bar = PepperDomain('foo', dtype = 'short') 33 | self.assertTrue(foo is bar) 34 | 35 | bar = PepperDomain('foo') 36 | self.assertTrue(foo is bar) 37 | 38 | with self.assertRaises(SingletonError): 39 | bar = PepperDomain('foo', dtype = 'long') 40 | 41 | class TestLoop(unittest.TestCase): 42 | def setUp(self): 43 | self.d1 = PepperDomain('d1', 15) 44 | self.d2 = PepperDomain('d2', 15) 45 | self.d3 = PepperDomain('d3', 15) 46 | self.d4 = PepperDomain('d4', 15) 47 | 48 | def tearDown(self): 49 | clear_memory() 50 | 51 | def _triple(self, cplx, loc): 52 | return None if loc is None else (cplx.get_domain(loc), cplx.get_paired_loc(loc), loc) 53 | 54 | def testLoop_01(self): 55 | d1, d2, d3, d4 = self.d1, self.d2, self.d3, self.d4 56 | cplx = PepperComplex([d1, d2, d3, ~d3, '+', d4], list('..()+.')) 57 | 58 | llocs = [(0, 0), (0, 1), (0, 2), None, (1, 0)] 59 | parts = [self._triple(cplx, l) for l in llocs] 60 | 61 | loop = Loop(parts) 62 | assert loop.is_open 63 | assert loop.bases == 15 * 3 64 | assert loop.stems == 1 65 | with self.assertRaises(AssertionError): 66 | loop.dlength == 15 * 4 67 | 68 | llocs = [(0, 0), (0, 1), (0, 2), (0, 3), None, (1, 0)] 69 | parts = [self._triple(cplx, l) for l in llocs] 70 | with self.assertRaises(ObjectInitError): 71 | loop = Loop(parts) 72 | 73 | if __name__ == '__main__': 74 | unittest.main() 75 | -------------------------------------------------------------------------------- /tests/test_output.py: -------------------------------------------------------------------------------- 1 | import unittest 2 | import warnings 3 | 4 | try: 5 | from roadrunner import RoadRunner 6 | SKIP_ROADRUNNER = False 7 | except ImportError as err: 8 | warnings.warn('Testing the SBML output requires libroadrunner') 9 | SKIP_ROADRUNNER = True 10 | 11 | from peppercornenumerator import enumerate_pil 12 | from peppercornenumerator.output import write_sbml, write_crn 13 | from peppercornenumerator.objects import clear_memory 14 | 15 | SKIP = False 16 | 17 | @unittest.skipIf(SKIP or SKIP_ROADRUNNER, "skipping tests that require libroadrunner") 18 | class Test_SBML_roadrunner(unittest.TestCase): 19 | def tearDown(self): 20 | clear_memory() 21 | 22 | def test_delayed_choice(self): 23 | inpil = """ 24 | length a = 5 25 | length b = 15 26 | length c = 15 27 | length d = 15 28 | length e = 15 29 | length z = 15 30 | 31 | RC1 = d( e( z ) ) b*( a* + ) c( + ) d @i 1e-8 M 32 | RC1b = d e( z ) d*( b*( a* + ) c( + ) ) @i 1e-8 M 33 | R0 = a b c @i 1e-7 M 34 | 35 | R21 = b c( + ) d @i 0 M 36 | R22 = d( e( z ) ) b*( a*( + ) ) c @i 0 M 37 | 38 | R31 = b c @i 0 M 39 | RC32b = d e( z ) d*( b*( a*( + ) ) c( + ) ) @i 0 M 40 | RC32 = d( e( z ) ) b*( a*( + ) ) c( + ) d @i 0 M 41 | 42 | TC1 = a( b c + b( c( + ) d + d( e( z ) ) ) ) @i 0 M 43 | TC2 = a( b c + b( c( + ) d( + d e( z ) ) ) ) @i 0 M 44 | TC3 = a( b( c + b c( + ) d( + d e( z ) ) ) ) @i 0 M 45 | """ 46 | 47 | enum, out = enumerate_pil(inpil, is_file = False, condensed = True) 48 | xml = write_sbml(enum, condensed = True) 49 | 50 | rr = RoadRunner() 51 | rr.load(xml) 52 | ExecutableModel = rr.model 53 | 54 | RC32 = 'RC32' if 'RC32' in rr.model.getFloatingSpeciesIds() else 'RC32b' 55 | RC1 = 'RC1' if 'RC1' in rr.model.getFloatingSpeciesIds() else 'RC1b' 56 | 57 | # Compartment 58 | assert ExecutableModel.getCompartmentVolumes() == 1. 59 | assert ExecutableModel.getNumCompartments() == 1 60 | assert ExecutableModel.getCompartmentIds() == ['TestTube'] 61 | 62 | # Species 63 | speciesIDs = ['R0', RC32, 'R22', 'R31', 'R21', RC1] 64 | ini_spIDs = sorted('init({})'.format(x) for x in speciesIDs) 65 | concIDs = ['[R0]', '[' + RC32 + ']', '[R22]', '[R31]', '[R21]', '[' + RC1 + ']'] 66 | ini_coIDs = sorted('init({})'.format(x) for x in concIDs) 67 | assert ExecutableModel.getNumFloatingSpecies() == len(speciesIDs) 68 | assert sorted(ExecutableModel.getFloatingSpeciesIds()) == sorted(speciesIDs) 69 | assert sorted(ExecutableModel.getFloatingSpeciesInitAmountIds()) == sorted(ini_spIDs) 70 | assert sorted(ExecutableModel.getFloatingSpeciesInitConcentrationIds()) == sorted(ini_coIDs) 71 | #print(sorted(ini_coIDs)) 72 | #print(ExecutableModel.getFloatingSpeciesInitAmounts()) 73 | #print(ExecutableModel.getFloatingSpeciesInitConcentrations()) 74 | 75 | # Reactions 76 | rxnIDs = ['R0_' + RC1 + '__' + RC32 + '_R31', 'R0_' + RC1 + '__R22_R21'] 77 | assert ExecutableModel.getNumReactions() == len(rxnIDs) 78 | assert sorted(ExecutableModel.getReactionIds()) == sorted(rxnIDs) 79 | assert rr.model[RC32] == 0 80 | assert rr.model[RC1] == 2e-8 81 | 82 | # simulate deterministic 83 | rr.model['init([R0])'] = 1e-8 84 | assert rr.model['init(R0)'] == 1e-8 85 | 86 | Vol = 1.66e-15 87 | rr.model.setCompartmentVolumes([Vol]) 88 | rr.model['init([R0])'] = 1e-8 * Vol 89 | rr.model[f'init({RC1})'] = 2e-8 * Vol 90 | rr.integrator.absolute_tolerance = 1e-12 * Vol 91 | rr.integrator.relative_tolerance = 1e-12 * Vol 92 | rr.integrator.initial_time_step = 0.00001 93 | result = rr.simulate(0, 500, steps=100) 94 | #print(result) 95 | #rr.plot() # look at it if you like! 96 | 97 | # NOTE: something is off with the units with stochastic simulations, weird... 98 | #print(rr.model.getCompartmentVolumes()) 99 | #print(rr.model.getFloatingSpeciesInitConcentrations()) 100 | #print(rr.model.getFloatingSpeciesInitAmounts()) 101 | #print(rr.model.getFloatingSpeciesConcentrations()) 102 | #print(rr.model.getFloatingSpeciesAmounts()) 103 | rr.reset() 104 | 105 | @unittest.skipIf(SKIP, "skipping tests") 106 | class Test_SBML_output(unittest.TestCase): 107 | def tearDown(self): 108 | clear_memory() 109 | 110 | def test_SCL_system_01(self): 111 | SCL_input = """ 112 | # This file describes the suppressed-leak catalyst system 113 | # by DY Zhang and K Sarma 114 | 115 | # Domains (13) 116 | length d1 = 5 117 | length d2 = 5 118 | length d3 = 5 119 | length d4 = 15 120 | length d5 = 5 121 | length d6 = 15 122 | length d7 = 5 123 | 124 | # Strands or composite domains (10) 125 | sup-sequence sPS = d3* d2* d1* d5 d6 : 35 126 | sup-sequence sSP = d5 d6 : 20 127 | sup-sequence sCat = d6 d7 : 20 128 | sup-sequence sBS = d7* d6* d5* d1 d2 d3 : 40 129 | sup-sequence sOP = d1 d2 d3 d4 : 30 130 | 131 | # Resting complexes (7) 132 | U = d1 d2 d3 @initial 0 M 133 | C1 = d3*( d2*( d1*( d5 d6 + ) ) ) d4 134 | C2 = d5( d6( + d7* ) ) d1 d2 d3 135 | Cat = d6 d7 136 | I3 = d7*( d6*( d5* d1 d2 d3 + ) ) 137 | OP = d1 d2 d3 d4 138 | SP = d5 d6 139 | W = d7* d6*( d5*( d1( d2( d3( + ) ) ) ) ) 140 | 141 | # Transient complexes (7) 142 | new1 = d7*( d6*( d5*( d1 d2 d3 + d1( d2( d3( d4 + ) ) ) ) ) + d6 ) 143 | new2 = d7* d6*( d5*( d1 d2 d3 + d1( d2( d3( d4 + ) ) ) ) ) 144 | I1 = d5( d6( + d6 d7( + ) ) ) d1 d2 d3 145 | I2 = d5( d6 + d6( d7( + ) ) ) d1 d2 d3 146 | I4 = d7*( d6*( d5*( d1 d2 d3 + d1( d2( d3( d4 + ) ) ) ) d6 + ) ) 147 | I5 = d7*( d6*( d5*( d1( d2( d3( + ) ) ) ) d6 + ) ) 148 | I6 = d7*( d6*( d5*( d1( d2( d3( + ) ) ) ) ) + d6 ) 149 | """ 150 | 151 | enum, out = enumerate_pil(SCL_input, is_file = False) 152 | assert 'length' in out 153 | assert 'sup-sequence' in out 154 | assert write_crn(enum) 155 | assert write_crn(enum, condensed = True) 156 | assert write_sbml(enum) 157 | assert write_sbml(enum, condensed = True) 158 | 159 | def test_SCL_system_02(self): 160 | ARM3J = """ 161 | # Domains (12) 162 | length a = 6 163 | length b = 6 164 | length c = 6 165 | length x = 6 166 | length y = 6 167 | length z = 6 168 | 169 | # Strands or composite domains (8) 170 | sup-sequence A = a x b y z* c* y* b* x* : 54 171 | sup-sequence C = c z a x y* b* x* a* z* : 54 172 | sup-sequence B = b y c z x* a* z* c* y* : 54 173 | sup-sequence I = y* b* x* a* : 24 174 | 175 | # Complexes (8) 176 | A = a x( b( y( z* c* ) ) ) @i 1e-7M 177 | B = b y( c( z( x* a* ) ) ) @i 1e-7M 178 | C = c z( a( x( y* b* ) ) ) @i 1e-7M 179 | I = y* b* x* a* @i 1e-9M 180 | IA = y*( b*( x*( a*( + ) ) ) ) z* c* y* b* x* @i 0 M 181 | IAB = y*( b*( x*( a*( + ) ) ) ) z*( c*( y*( b*( x* + ) ) ) ) x* a* z* c* y* @i 0 M 182 | IABC = y*( b*( x*( a*( + ) ) ) ) z*( c*( y*( b*( x* + ) ) ) ) x*( a*( z*( c*( y* + ) ) ) ) y* b* x* a* z* @i 0 M 183 | ABC = a( x( b( y( z*( c*( y*( b*( x* + ) ) ) ) x*( a*( z*( c*( y* + ) ) ) ) ) ) ) ) z* @i 0 M 184 | """ 185 | 186 | enum, out = enumerate_pil(ARM3J, is_file = False, k_fast = 100, k_slow = 20) 187 | assert 'length' in out 188 | assert 'sup-sequence' in out 189 | assert write_crn(enum) 190 | assert write_crn(enum, condensed = True) 191 | assert write_sbml(enum) 192 | assert write_sbml(enum, condensed = True) 193 | 194 | if __name__ == '__main__': 195 | unittest.main() 196 | 197 | -------------------------------------------------------------------------------- /tests/test_ratemodel.py: -------------------------------------------------------------------------------- 1 | import unittest 2 | import peppercornenumerator.reactions as rxn 3 | from peppercornenumerator.input import read_pil, read_pil_line 4 | from peppercornenumerator.objects import clear_memory 5 | 6 | SKIP = False 7 | 8 | @unittest.skipIf(SKIP, "skipping tests") 9 | class RateBranch3WayTests(unittest.TestCase): 10 | def setUp(self): 11 | self.a = read_pil_line("domain a = 15") 12 | self.b = read_pil_line("domain b = 15") 13 | self.c = read_pil_line("domain c = 15") 14 | self.d = read_pil_line("domain d = 15") 15 | self.e = read_pil_line("domain e = 15") 16 | self.x = read_pil_line("domain x = 15") 17 | 18 | def tearDown(self): 19 | clear_memory() 20 | 21 | def test_max_helix_initiation_pen(self): 22 | """ 23 | A series of 3-way branch migration reactions. 24 | """ 25 | # INPUT 26 | complexes, reactions = read_pil(""" 27 | X = a( b( c + c( d( + ) ) ) ) 28 | Y = a( b( c( + c d( + ) ) ) ) 29 | """) 30 | X = complexes['X'] 31 | Y = complexes['Y'] 32 | output = rxn.branch_3way(X) 33 | reaction = output[0] 34 | self.assertEqual(int(reaction.const), 22) 35 | 36 | output = rxn.branch_3way(Y) 37 | reaction = output[0] 38 | self.assertEqual(int(reaction.const), 22) 39 | 40 | def test_max_helix_initiation_pen2(self): 41 | """ 42 | A series of 3-way branch migration reactions. 43 | """ 44 | # INPUT 45 | complexes, reactions = read_pil(""" 46 | X = a( b( c e + x c( d( + ) ) ) ) 47 | Y = a( b( c( e + x c d( + ) ) ) ) 48 | """) 49 | 50 | X = complexes['X'] 51 | Y = complexes['Y'] 52 | output = rxn.branch_3way(X) 53 | reaction = output[0] 54 | self.assertEqual(int(reaction.const), 666) 55 | 56 | output = rxn.branch_3way(Y) 57 | reaction = output[0] 58 | self.assertEqual(int(reaction.const), 666) 59 | -------------------------------------------------------------------------------- /tests/test_utils.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python 2 | # 3 | # test_utils.py 4 | # EnumeratorProject 5 | # 6 | import unittest 7 | 8 | from peppercornenumerator.utils import wrap, tarjans 9 | 10 | class MiscTests(unittest.TestCase): 11 | def test_wrap(self): 12 | assert wrap(0, 3) == 0 13 | assert wrap(2, 3) == 2 14 | assert wrap(3, 3) == 0 15 | assert wrap(4, 3) == 1 16 | assert wrap(-1, 3) == 2 17 | assert wrap(-2, 3) == 1 18 | 19 | class mock: 20 | def __init__(self, n): 21 | self.name = n 22 | def __repr__(self): 23 | return f'{self.name}' 24 | 25 | class TarjansTest(unittest.TestCase): 26 | def test_tarjans(self): 27 | # https://www.youtube.com/watch?v=wUgWX0nc4NY 28 | a = mock('a') 29 | b = mock('b') 30 | c = mock('c') 31 | d = mock('d') 32 | e = mock('e') 33 | f = mock('f') 34 | g = mock('g') 35 | h = mock('h') 36 | complexes = [a, b, c, d, e, f, g, h] 37 | products = {a: [b, e], 38 | b: [f], 39 | c: [b, g, d], 40 | d: [g], 41 | e: [a, f], 42 | f: [c, g], 43 | g: [h], 44 | h: [d]} 45 | 46 | sccs = tarjans(complexes, products) 47 | outp = [[d, h, g], [c, f, b], [e, a]] 48 | ss = sorted([sorted(s, key = repr) for s in sccs], key = repr) 49 | so = sorted([sorted(s, key = repr) for s in outp], key = repr) 50 | assert ss == so 51 | 52 | if __name__ == '__main__': 53 | unittest.main() 54 | --------------------------------------------------------------------------------