{"_id":"54e9099bf152c50d009b49b5","user":"5476beec817e8d080031f986","__v":53,"category":{"_id":"54e68328154f8e0d0007b55c","project":"5476bf0f817e8d080031f988","version":"5476bf10817e8d080031f98b","__v":8,"pages":["54e68e63a43fe13500db387a","54e68e98bdcbdc21000d55e6","54e6ca051415460d009fc118","54ecf59b172d6b2b003b3178","54ecf790172d6b2b003b317a","54eec2f35bf74a0d00ef4063","56d10611376b040b005b3135","56e36cf4f7d7a71700234792"],"sync":{"url":"","isSync":false},"reference":false,"createdAt":"2015-02-20T00:43:20.640Z","from_sync":false,"order":3,"slug":"design-rules-limitations","title":"Developing on Transcriptic"},"parentDoc":null,"project":"5476bf0f817e8d080031f988","version":{"_id":"5476bf10817e8d080031f98b","__v":17,"project":"5476bf0f817e8d080031f988","createdAt":"2014-11-27T06:05:04.263Z","releaseDate":"2014-11-27T06:05:04.263Z","categories":["5476bf10817e8d080031f98c","5477c46cf3736008009e9eb5","5477c474f3736008009e9eb6","5477c47ef3736008009e9eb7","5477c48ff3736008009e9eb8","5477c4948deb230800808bf0","54e68328154f8e0d0007b55c","54e90194c8e0c00d007ac061","54eed2275bf74a0d00ef4076","54f7a7be0a3cbb0d00d666fb","559b0ebf7ae7f80d0096d871","55d697f9ae529e0d00d34f03","562d4dcc8c6e5a0d00d6ed1d","562e591c4376430d006f17e0","568f0e73bdb9260d00149d8c","5719542aac1e2e0e001834c6","57a14a8ed778850e0047e230"],"is_deprecated":false,"is_hidden":false,"is_beta":false,"is_stable":true,"codename":"","version_clean":"1.0.0","version":"1.0"},"updates":["5560ea16c095630d0048c9fd"],"next":{"pages":[],"description":""},"createdAt":"2015-02-21T22:41:31.649Z","link_external":false,"link_url":"","githubsync":"","sync_unique":"","hidden":false,"api":{"results":{"codes":[]},"settings":"","auth":"required","params":[],"url":""},"isReference":false,"order":0,"body":"Writing a new protocol can be a complex undertaking, but following a structured process can help ensure better success. The basic workflow is:\n\n1. Using pencil and paper, draw out a flow chart of all of the steps in your current protocol. \n2. Annotate this chart with any information you need to consider while drafting the protocol. For example, what is your sample type? What are the details to the layout of your plate? What is the specific instruction as to how this sample has to be treated? For example, \"the sample has to be returned to -20C.\" \n3. Figure out the container form factor for each step in your flow chart.  What's in a 1.5 ml tube? What is in 96-well flat-bottom (assay) plates?  What should be done in 384-well PCR plates?  Taking a look at the available [container types](doc:containers) and their details such as dead volume can aid in this process.\n4. Decompose this flow chart into discrete processes.\n   - For example, in a cloning protocol you may have a fragment generation step, an assembly step, a transformation step, a screening step, and a final growth and DNA extraction step.\n5. Mark each step of each process with the relevant  [Autoprotocol](http://autoprotocol.org/specification/) instruction (for example: your PCR step would be called `thermocycle` using Autoprotocol).\n6. Make a list of all of the potential issues where a step might fail to result in successful, accurate results. This should include things like \"the liquid handling in step X wasn't accurate\", \"there was cross-contamination in the samples at step Y\" and \"reagent Y was bad\".\n7. Turn the list of failure modes into a list of controls you will need to include. Annotate these controls onto the relevant steps in your flow chart.\n8. Use the form factor and controls information to figure out how many sample wells you have at each step. From this, write down how you want to lay out samples on your containers at each step in your flow chart.  How many samples can you process per plate?\n9. Use the annotated flow chart you've now built to draft the protocol generation code. List all the autoprotocol instructions in the order required for your protocol and start to fill out the parameters for each. You can use the general [Autoprotocol JSON specifications](http://autoprotocol.org/specification/)  or use the [Autoprotocol python library](https://github.com/autoprotocol/autoprotocol-python). Each of the discrete processes will be a separate script. For example in cloning you will have several scripts to cover source amplification, assembly, transformation and verification. qPCR on the other hand is a single script process.\n10. [Add aliquots to your Transcriptic inventory](https://developers.transcriptic.com/#section-step-2-populate-your-inventory) using the shipping kit and finalize your draft by referring to those particular aliquots by their `id`s (an alphanumeric string starting with \"ct\"). \n11.  From this version you can generalize your protocol to take various numbers of aliquots or different types of reagents as well as other parameters. For example, to change the length of time you let the DNA anneal, you do not need to write a new qPCR script. You can simply adjust the parameter in the one you have already written.\n[block:api-header]\n{\n  \"type\": \"basic\",\n  \"title\": \"Designing controls\"\n}\n[/block]\nEvery protocol you write should include thorough biological and technical controls. Though Transcriptic continuously monitors and validates device performance, the remote nature of Transcriptic's cloud laboratory requires you to think in a more structured way regarding your controls than you might be accustomed to when working by hand.\n\nIn particular, automated liquid handling requires special attention. Whenever possible, you should include in-line technical controls using optical dyes to validate pipetting. The OrangeG dye, which is a part of the starter kit, is a convenient option as its absorbance at 475 nm correlates with its volume (this requires a clear flat-bottom plate). Pipetting a range of volumes randomly distributed across the plate should reveal a linear correlation of volume to absorbance with a correlation coefficient of >0.98. With this technical control you can, for example, distinguish between a general pipetting error and a source well running low in sample. \n\nIn addition to technical controls, biological controls should be included. Negative as well as positive controls. During your design you will have identified several possible failure modes of the experiment. To assess contamination in an experiment involving bacteria, a subset of wells can be filled with media only to serve as negative control. It is most effective to distribute these wells randomly across the plate. Similarly, you should include a positive control that will help you to determine if all components of the reaction were working as expected. This is commonly done by repeating a reaction that has succeeded multiple times. The difference between the reaction components in the control versus the samples should be minimal, in the best case it is a single factor only.\n\nFor example in a PCR reaction you would keep the PCR conditions and primers used stable, while changing the DNA template. Alternatively, you adjust a parameter in the PCR conditions, such as the annealing temperature, while keeping everything else (primers, DNA, etc.) constant. You may run many of these tests in parallel, where each well corresponds to a single change. With this setup you can screen a matrix of parameters in a small number of runs to optimize your conditions.\n[block:api-header]\n{\n  \"type\": \"basic\",\n  \"title\": \"Example: Design a PCR workflow\"\n}\n[/block]\nThis example experiment is a high-throughput qPCR screen of gDNA for the presence or absence of certain genes/alleles. All assays use two primers that have the same annealing temperature. The PCR product length is similar across all assays with a maximum of 250bp.\n\nTo date this has been done manually following this protocol:\n[block:image]\n{\n  \"images\": [\n    {\n      \"image\": [\n        \"https://files.readme.io/m5cvNIzFRRGlFEzxJbvj_Screen%20Shot%202015-03-23%20at%2012.28.55%20PM.png\",\n        \"Screen Shot 2015-03-23 at 12.28.55 PM.png\",\n        \"1208\",\n        \"1124\",\n        \"#e12222\",\n        \"\"\n      ],\n      \"caption\": \"Manual PCR protocol\"\n    }\n  ]\n}\n[/block]\n\nTo get us started, the general workflow can be represented in this basic flow chart:\n[block:image]\n{\n  \"images\": [\n    {\n      \"image\": [\n        \"https://files.readme.io/lqub8Uk9Tz6DP9Dvjj7B_Flowchart%20workflow.001.png\",\n        \"Flowchart workflow.001.png\",\n        \"1024\",\n        \"567\",\n        \"#339344\",\n        \"\"\n      ],\n      \"caption\": \"PCR basic workflow\"\n    }\n  ]\n}\n[/block]\nNow we can add some basic information from our experimental design. We assume we have 96 samples and have four assays developed already. These can be run all on one 384-well PCR plate:\n[block:image]\n{\n  \"images\": [\n    {\n      \"image\": [\n        \"https://files.readme.io/NeWgd3rZTPWLuHhUI4K9_Flowchart%20workflow.002.png\",\n        \"Flowchart workflow.002.png\",\n        \"1024\",\n        \"570\",\n        \"#349444\",\n        \"\"\n      ],\n      \"caption\": \"PCR workflow with experiment specific notes\"\n    }\n  ]\n}\n[/block]\nNow we can start adding the relevant Autoprotocol instructions and also consider any additional steps that need to be included. In this case, all source plates need to be sealed again and return to storage, whereas the tubes containing the SYBR Taq master mix can be discarded.\n[block:image]\n{\n  \"images\": [\n    {\n      \"image\": [\n        \"https://files.readme.io/sYj9n0TTqVMTCaL5cXAO_Flowchart%20workflow.003.png\",\n        \"Flowchart workflow.003.png\",\n        \"1024\",\n        \"768\",\n        \"#2d8d3e\",\n        \"\"\n      ],\n      \"caption\": \"PCR workflow annotated with autoprotocol instructions as  well as adding final destination of plates\"\n    }\n  ]\n}\n[/block]\nNext, we will consider control placement. Since this assay uses a PCR plate, we cannot read it in the plate reader to determine the amount of a standard dye that was added. But we can use positive and negative controls that are randomly distributed in our sample plate. Later, these will give us information about any potential contamination and sample quality. In addition to basic \"all-or-none\" control we can also add a standard curve using a serially diluted control. Using a serial dilution of known concentration we can later generate a standard curve and its linearity will be a proxy of pipetting accuracy.\n[block:image]\n{\n  \"images\": [\n    {\n      \"image\": [\n        \"https://files.readme.io/cZZngZ6ZRmiKw8leMOf0_Flowchart%20workflow.005.png\",\n        \"Flowchart workflow.005.png\",\n        \"1224\",\n        \"647\",\n        \"#337dab\",\n        \"\"\n      ],\n      \"caption\": \"Control placement\"\n    }\n  ]\n}\n[/block]\nFinally, we take our instructions from the flow chart and start writing the code. In a first step, we can bring them in the order they should execute, add a reference to the correct plate, and add any other parameters we want to consider later, such as `mix_after`.\nAvailable parameters for all instructions can be found in the  [Autoprotocol specification](http://autoprotocol.org/specification/).\n[block:image]\n{\n  \"images\": [\n    {\n      \"image\": [\n        \"https://files.readme.io/fHJJXSb4T0TKymje0Xuw_Flowchart%20workflow.006.png\",\n        \"Flowchart workflow.006.png\",\n        \"1024\",\n        \"319\",\n        \"#131313\",\n        \"\"\n      ],\n      \"caption\": \"Sort instructions to start writing the protocol\"\n    }\n  ]\n}\n[/block]\nFrom this basic skeleton of instructions, you can start to write your script using your favorite language. If you chose python, Autoprotocol has a [library](https://github.com/autoprotocol/autoprotocol-python) that will help you get started. The documentation can be found [here](http://autoprotocol-python.readthedocs.org/en/latest/) and the next section gives you a short primer on how to get your system ready to develop and test your own protocols.\n[block:api-header]\n{\n  \"type\": \"basic\",\n  \"title\": \"Installing all required tools\"\n}\n[/block]\n**MacOSX**\n1. Make sure you have the apple [command line tools](https://developer.apple.com/downloads/) or [XCode](http://developer.apple.com/xcode/) installed.\n2. Install [homebrew](http://brew.sh/) by pasting this into your Terminal prompt:\n  `ruby -e \"$(curl -fsSL https://raw.githubusercontent.com/Homebrew/install/master/install)\"`.\n3. Update your path variable to refer to the Homebrew directory first.\n   - In `~/.profile` add  `export PATH=/usr/local/bin:/usr/local/sbin:$PATH` to the bottom of the file.\n\n**Linux**\n1. You can install Linuxbrew, a version of homebrew, by following the instructions described [here](http://brew.sh/linuxbrew/).\n\n**Transcriptic tools**\n1. Install python through homebrew by typing `brew install python`.\n2. Use `pip install autoprotocol` to install the [autoprotocol python library](https://github.com/autoprotocol/autoprotocol-python).\n3. Use `pip install transcriptic` to install the [Transcriptic runner](https://github.com/transcriptic/runner), a command-line tool for interacting with the Transcriptic API.\n[block:api-header]\n{\n  \"type\": \"basic\",\n  \"title\": \"Writing your protocol\"\n}\n[/block]\nFrom the prior outlines, we can now think of our parameters for the script. First, we will need to examine all the containers and aliquots that will come from your inventory and determine their type. The `dna_plate` will be a single container, whereas for `taq_tubes` we will refer to several aliquots and for `primer_pairs` we will take several groups of one or more primers. Similarly, we will want to specify some other parameters that can be different every time we run this protocol, such as the amount of primer to add, master mix to distribute or DNA to transfer.\n[block:code]\n{\n  \"codes\": [\n    {\n      \"code\": \"\\\"inputs\\\": {\\n  \\\"dna_plate\\\":\\\"container\\\",\\n  \\\"taq_tubes\\\":\\\"aliquot+\\\",\\n  \\\"primer_vol_total\\\":\\\"volume\\\",\\n  \\\"mm_vol\\\":\\\"volume\\\",\\n  \\\"dna_vol\\\":\\\"volume\\\",\\n  \\\"primer_pairs\\\":\\\"aliquot++\\\",\\n  \\\"annealing_temp\\\":\\\"temperature\\\"\\n}\",\n      \"language\": \"json\"\n    }\n  ]\n}\n[/block]\nWe can now define some reasonable values for these parameters that we will use for trouble shooting the protocol and later on to create a preview of the protocol on the launch screen.\n\nTo determine the volumes, let's assume we want to make a 20uL reaction, of which 2uL will be DNA. Hence the master mix will be 18uL per well. We want to make 96 reactions per master mix and to account for well dead-volume and small, but compounding inaccuracies in pipetting we will make a master mix for 110 reactions. \nWe are using a SYBR master mix that is provided in the Taq tube as a 1x mix already. The vendor suggests we add 0.8uL of primer from a 400uM stock per reaction. So that means we have to add 88uL per each primer to its respective Taq tube. \n[block:code]\n{\n  \"codes\": [\n    {\n      \"code\": \"\\\"parameters\\\": {\\n  \\\"dna_plate\\\":\\\"dna_plate\\\",\\n  \\\"taq_tubes\\\":[\\\"taq1/0\\\", \\\"taq2/0\\\", \\\"taq3/0\\\", \\\"taq4/0\\\"],\\n  \\\"primer_vol_total\\\":\\\"88:microliter\\\",\\n  \\\"mm_vol\\\":\\\"18:microliter\\\",\\n  \\\"dna_vol\\\":\\\"2:microliter\\\",\\n  \\\"primer_pairs\\\": [\\n    [\\\"primer_plate/0\\\",\\\"primer_plate/1\\\"],\\n    [\\\"primer_plate/2\\\",\\\"primer_plate/3\\\"],\\n    [\\\"primer_plate/4\\\",\\\"primer_plate/5\\\"],\\n    [\\\"primer_plate/6\\\",\\\"primer_plate/7\\\"]\\n  ],\\n  \\\"annealing_temp\\\":\\\"60:celsius\\\"\\n}\",\n      \"language\": \"json\"\n    }\n  ]\n}\n[/block]\nIn order to create a package and validate the protocol at a later time, we have to create the containers that this code is referring to. This does not create real containers, it is just used for code validation only. At the appropriate time, these containers will be substituted for the containers you select from your inventory. It is good practice to make the volumes in these containers match as realistically as possible, but it is not absolutely required.\n\nWhile the volumes for the `dna_plate` and `primer_plate` are set arbitrarily, the volume we want to provide in the Taq tubes is 1804uL since (110reactions*18uL)-(88uL*2primers) is 1804uL. \n[block:code]\n{\n  \"codes\": [\n    {\n      \"code\": \"\\\"refs\\\":{\\n    \\\"primer_plate\\\": {\\n      \\\"type\\\": \\\"96-deep\\\",\\n      \\\"aliquots\\\": {\\n        \\\"0\\\": {\\\"volume\\\": \\\"500:microliter\\\"},\\n        \\\"1\\\": {\\\"volume\\\": \\\"500:microliter\\\"},\\n        \\\"2\\\": {\\\"volume\\\": \\\"500:microliter\\\"},\\n        \\\"3\\\": {\\\"volume\\\": \\\"500:microliter\\\"},\\n        \\\"4\\\": {\\\"volume\\\": \\\"500:microliter\\\"},\\n        \\\"5\\\": {\\\"volume\\\": \\\"500:microliter\\\"},\\n        \\\"6\\\": {\\\"volume\\\": \\\"500:microliter\\\"},\\n        \\\"7\\\": {\\\"volume\\\": \\\"500:microliter\\\"}\\n      },\\n      \\\"store\\\":\\\"cold_20\\\"\\n    },\\n    \\\"taq1\\\": {\\n      \\\"type\\\": \\\"micro-2.0\\\", \\n      \\\"aliquots\\\": {\\n        \\\"0\\\": {\\\"volume\\\": \\\"1804:microliter\\\"}\\n      },\\n      \\\"discard\\\": true\\n    },\\n    \\\"taq2\\\": {\\n      \\\"type\\\": \\\"micro-2.0\\\",\\n      \\\"aliquots\\\": {\\n        \\\"0\\\": {\\\"volume\\\": \\\"1804:microliter\\\"}\\n      },\\n      \\\"discard\\\": true\\n    },\\n    \\\"taq3\\\": {\\n      \\\"type\\\": \\\"micro-2.0\\\",\\n      \\\"aliquots\\\": {\\n        \\\"0\\\": {\\\"volume\\\": \\\"1804:microliter\\\"}\\n      },\\n      \\\"discard\\\": true\\n    },\\n    \\\"taq4\\\": {\\n      \\\"type\\\": \\\"micro-2.0\\\",\\n      \\\"aliquots\\\": {\\n        \\\"0\\\": {\\\"volume\\\": \\\"1804:microliter\\\"}\\n      },\\n      \\\"discard\\\": true\\n    },\\n    \\\"dna_plate\\\": {\\n      \\\"type\\\": \\\"96-pcr\\\",\\n      \\\"aliquots\\\": {\\n        \\\"0\\\": {\\\"volume\\\": \\\"50:microliter\\\"},\\n        \\\"1\\\": {\\\"volume\\\": \\\"50:microliter\\\"},\\n        \\\"2\\\": {\\\"volume\\\": \\\"50:microliter\\\"},\\n        \\\"3\\\": {\\\"volume\\\": \\\"50:microliter\\\"},\\n        \\\"4\\\": {\\\"volume\\\": \\\"50:microliter\\\"},\\n        \\\"5\\\": {\\\"volume\\\": \\\"50:microliter\\\"},\\n        \\\"6\\\": {\\\"volume\\\": \\\"50:microliter\\\"},\\n        \\\"7\\\": {\\\"volume\\\": \\\"50:microliter\\\"}\\n      },\\n      \\\"store\\\":\\\"cold_20\\\"\\n    }\\n  }\",\n      \"language\": \"javascript\",\n      \"name\": \"JSON\"\n    }\n  ]\n}\n[/block]\nWe can now start writing the first draft of our protocol, focusing on a single primer set. \n[block:code]\n{\n  \"codes\": [\n    {\n      \"code\": \"from autoprotocol.util import make_dottable_dict\\n\\n\\ndef myqPCR(protocol, params):\\n    params = make_dottable_dict(params)\\n    primer_plate = params.primer_pairs[0][0].container\\n    dest_plate = protocol.ref('dest_plate', cont_type='384-pcr', \\n                              storage='cold_4')\\n\\n    # transfer the first primer\\n    protocol.transfer(params.primer_pairs[0][0], params.taq_tubes[0],\\n                      params.primer_vol_total)\\n    # transfer the second primer and mix the solution\\n    protocol.transfer(params.primer_pairs[0][1], params.taq_tubes[0], \\n                      params.primer_vol_total,\\n                      mix_after=True, mix_vol=params.primer_vol_total, \\n                      repetitions=5)\\n    # distribute the master mix from the first Taq tube to the first \\n    # quadrant of the PCR plate, mix before aspirating the solution\\n    protocol.distribute(params.taq_tubes[0], dest_plate.quarter(0), \\n                        params.mm_vol,\\n                        allow_carryover=True, mix_before=True, \\n                        mix_vol=params.primer_vol_total, repetitions=4)\\n\\n    # add the DNA from the 96-well plate to the first quadrant and mix\\n    protocol.stamp(params.dna_plate, dest_plate, 0, params.dna_vol,\\n                   mix_after=True, mix_vol=params.dna_vol, repetitions=3)\\n    # seal and thermocycle\\n    protocol.seal(dest_plate)\\n    protocol.thermocycle(dest_plate, [{\\n          \\\"cycles\\\": 1, \\\"steps\\\": [{\\n              \\\"temperature\\\": \\\"95:celsius\\\",\\n              \\\"duration\\\": \\\"3:minute\\\"}]\\n        }, {\\n          \\\"cycles\\\": 40, \\\"steps\\\": [{\\n              \\\"temperature\\\": \\\"95:celsius\\\",\\n              \\\"duration\\\": \\\"5:second\\\"}, {\\n              \\\"temperature\\\": params.annealing_temp,\\n              \\\"duration\\\": \\\"30:second\\\", \\\"read\\\": True}]\\n        }],\\n                         volume=\\\"20:microliter\\\",\\n                         dataref=\\\"myqPCR_data\\\",\\n                         # read all wells for SYBR green dye\\n                         dyes={\\\"SYBR\\\": dest_plate.all_wells().indices()},\\n                         # standard melting curve parameters\\n                         melting_start=\\\"65:celsius\\\",\\n                         melting_end=\\\"95:celsius\\\",\\n                         melting_increment=\\\"0.5:celsius\\\",\\n                         melting_rate=\\\"5:second\\\")\\n\\t\\t# seal source plates before they go back to storage\\n    protocol.seal(primer_plate)\\n    protocol.seal(params.dna_plate)\\n    \\nif __name__ == '__main__':\\n    from autoprotocol.harness import run\\n    run(myqPCR)\",\n      \"language\": \"python\"\n    }\n  ]\n}\n[/block]\nNote how we identify the primer container by querying the container type of the first primer aliquot. This is needed for sealing the plate back later. To cover the case where the primers are presented on several 96-deep plates, we can do the following:\n[block:code]\n{\n  \"codes\": [\n    {\n      \"code\": \"primer_plates = []\\nfor primers in params.primer_pairs:\\n  for primer in primers:\\n    # list all containers that are used for primers\\n    primer_plates.append(primer.container)\\n# find which ones are unique\\nunique_primer_plates = set(primer_plates)\\n...\\nfor primer_plate in unique_primer_plates:\\n\\tprotocol.seal(primer_plate)\",\n      \"language\": \"python\"\n    }\n  ]\n}\n[/block]\nSimilarly, we should now loop through all primer pairs and add them to the correct Taq tube:\n[block:code]\n{\n  \"codes\": [\n    {\n      \"code\": \"for i, primer in enumerate(params.primer_pairs):\\n\\tprotocol.transfer(primer[0], params.taq_tubes[i], \\n                    params.primer_vol_total)\\n  protocol.transfer(primer[1], params.taq_tubes[i], \\n                    params.primer_vol_total, mix_after=True,\\n                    mix_vol=params.primer_vol_total, repetitions=5)\",\n      \"language\": \"python\"\n    }\n  ]\n}\n[/block]\nUsing the same approach, we can now implement our final protocol. It is good practice to assert that your protocol is used in the intended way. For example, this script can only take 4 different PCR reactions, so using an assert we can add a message that this script does currently not support `primer_pairs` with more than 4 entries.\n[block:code]\n{\n  \"codes\": [\n    {\n      \"code\": \"from autoprotocol.util import make_dottable_dict\\n\\n\\ndef myqPCR(protocol, params):\\n    params = make_dottable_dict(params)\\n\\n    dest_plate = protocol.ref('dest_plate', cont_type='384-pcr',\\n                              storage='cold_4')\\n\\n    primer_plates = []\\n    for primers in params.primer_pairs:\\n        for primer in primers:\\n            primer_plates.append(primer.container)\\n    unique_primer_plates = set(primer_plates)\\n\\n    assert len(params.taq_tubes) == len(params.primer_pairs), ('You are \\tusing more primer pairs then you supply taq tubes.')\\n    \\n    assert len(params.taq_tubes) < 5, ('Currently this script only '\\n                                       'supports up to 4 reactions as '\\n                                       'defined by primer pairs and Taq '\\n                                       'tubes')\\n\\n    for i, primer in enumerate(params.primer_pairs):\\n        protocol.transfer(primer[0], params.taq_tubes[i],\\n                          params.primer_vol_total)\\n        protocol.transfer(primer[1], params.taq_tubes[i],\\n                          params.primer_vol_total, mix_after=True,\\n                          mix_vol=params.primer_vol_total, repetitions=5)\\n\\n    for i, tube in enumerate(params.taq_tubes):\\n        protocol.distribute(tube, dest_plate.quadrant(i), params.mm_vol,\\n                            allow_carryover=True, mix_before=True,\\n                            mix_vol=params.primer_vol_total,\\n                            repetitions=4)\\n\\n    for i in xrange(0, 3):\\n        protocol.stamp(params.dna_plate, dest_plate, params.dna_vol, i,\\n                       mix_after=True, mix_vol=params.dna_vol,\\n                       repetitions=3)\\n\\n    protocol.seal(dest_plate)\\n\\n    protocol.thermocycle(dest_plate, [{\\n          \\\"cycles\\\": 1, \\\"steps\\\": [{\\n              \\\"temperature\\\": \\\"95:celsius\\\",\\n              \\\"duration\\\": \\\"3:minute\\\"}]\\n        }, {\\n          \\\"cycles\\\": 40, \\\"steps\\\": [{\\n              \\\"temperature\\\": \\\"95:celsius\\\",\\n              \\\"duration\\\": \\\"5:second\\\"}, {\\n              \\\"temperature\\\": params.annealing_temp,\\n              \\\"duration\\\": \\\"30:second\\\", \\\"read\\\": True}]\\n        }],\\n                         volume=\\\"20:microliter\\\",\\n                         dataref=\\\"myqPCR_data\\\",\\n                         dyes={\\\"SYBR\\\": dest_plate.all_wells().indices()},\\n                         melting_start=\\\"65:celsius\\\",\\n                         melting_end=\\\"95:celsius\\\",\\n                         melting_increment=\\\"0.5:celsius\\\",\\n                         melting_rate=\\\"5:second\\\")\\n    protocol.seal(params.dna_plate)\\n    for primer_plate in unique_primer_plates:\\n        protocol.seal(primer_plate)\\n\\nif __name__ == '__main__':\\n    from autoprotocol.harness import run\\n    run(myqPCR, 'MyqPCR')\",\n      \"language\": \"python\"\n    }\n  ]\n}\n[/block]\nFinally, we add our manifest.json with the information we defined first:\n[block:code]\n{\n  \"codes\": [\n    {\n      \"code\": \"{\\n  \\\"version\\\": \\\"1.0.0\\\",\\n  \\\"format\\\": \\\"python\\\",\\n  \\\"license\\\": \\\"MIT\\\",\\n  \\\"protocols\\\": [\\n    {\\n      \\\"name\\\": \\\"MyqPCR\\\",\\n      \\\"description\\\": \\\"This is my first qPCR script\\\",\\n      \\\"command_string\\\": \\\"python -m myqPCR\\\",\\n      \\\"inputs\\\": {\\n        \\\"dna_plate\\\":\\\"container\\\",\\n        \\\"taq_tubes\\\":\\\"aliquot+\\\",\\n        \\\"primer_vol_total\\\":\\\"volume\\\",\\n        \\\"mm_vol\\\":\\\"volume\\\",\\n        \\\"dna_vol\\\":\\\"volume\\\",\\n        \\\"primer_pairs\\\":\\\"aliquot++\\\",\\n        \\\"annealing_temp\\\":\\\"temperature\\\"\\n      },\\n      \\\"preview\\\": {\\n        \\\"refs\\\":{\\n          \\\"primer_plate\\\": {\\n            \\\"type\\\": \\\"96-deep\\\",\\n            \\\"aliquots\\\": {\\n              \\\"0\\\": {\\\"volume\\\": \\\"500:microliter\\\"},\\n              \\\"1\\\": {\\\"volume\\\": \\\"500:microliter\\\"},\\n              \\\"2\\\": {\\\"volume\\\": \\\"500:microliter\\\"},\\n              \\\"3\\\": {\\\"volume\\\": \\\"500:microliter\\\"},\\n              \\\"4\\\": {\\\"volume\\\": \\\"500:microliter\\\"},\\n              \\\"5\\\": {\\\"volume\\\": \\\"500:microliter\\\"},\\n              \\\"6\\\": {\\\"volume\\\": \\\"500:microliter\\\"},\\n              \\\"7\\\": {\\\"volume\\\": \\\"500:microliter\\\"}\\n            },\\n            \\\"store\\\":\\\"cold_20\\\"\\n          },\\n          \\\"taq1\\\": {\\n            \\\"type\\\": \\\"micro-2.0\\\", \\n            \\\"aliquots\\\": {\\n              \\\"0\\\": {\\\"volume\\\": \\\"1804:microliter\\\"}\\n            },\\n            \\\"discard\\\": true\\n          },\\n          \\\"taq2\\\": {\\n            \\\"type\\\": \\\"micro-2.0\\\",\\n            \\\"aliquots\\\": {\\n              \\\"0\\\": {\\\"volume\\\": \\\"1804:microliter\\\"}\\n            },\\n              \\\"discard\\\": true\\n          },\\n          \\\"taq3\\\": {\\n            \\\"type\\\": \\\"micro-2.0\\\",\\n            \\\"aliquots\\\": {\\n              \\\"0\\\": {\\\"volume\\\": \\\"1804:microliter\\\"}\\n            },\\n            \\\"discard\\\": true\\n          },\\n          \\\"taq4\\\": {\\n            \\\"type\\\": \\\"micro-2.0\\\",\\n            \\\"aliquots\\\": {\\n              \\\"0\\\": {\\\"volume\\\": \\\"1804:microliter\\\"}\\n            },\\n            \\\"discard\\\": true\\n          },\\n          \\\"dna_plate\\\": {\\n            \\\"type\\\": \\\"96-pcr\\\",\\n            \\\"aliquots\\\": {\\n              \\\"0\\\": {\\\"volume\\\": \\\"50:microliter\\\"},\\n              \\\"1\\\": {\\\"volume\\\": \\\"50:microliter\\\"},\\n              \\\"2\\\": {\\\"volume\\\": \\\"50:microliter\\\"},\\n              \\\"3\\\": {\\\"volume\\\": \\\"50:microliter\\\"},\\n              \\\"4\\\": {\\\"volume\\\": \\\"50:microliter\\\"},\\n              \\\"5\\\": {\\\"volume\\\": \\\"50:microliter\\\"},\\n              \\\"6\\\": {\\\"volume\\\": \\\"50:microliter\\\"},\\n              \\\"7\\\": {\\\"volume\\\": \\\"50:microliter\\\"}\\n            },\\n            \\\"store\\\":\\\"cold_20\\\"\\n          }\\n        },\\n        \\\"parameters\\\": {\\n            \\\"dna_plate\\\":\\\"dna_plate\\\",\\n            \\\"taq_tubes\\\":[\\\"taq1/0\\\", \\\"taq2/0\\\", \\\"taq3/0\\\", \\\"taq4/0\\\"],\\n            \\\"primer_vol_total\\\":\\\"88:microliter\\\",\\n            \\\"mm_vol\\\":\\\"18:microliter\\\",\\n            \\\"dna_vol\\\":\\\"2:microliter\\\",\\n            \\\"primer_pairs\\\": [\\n              [\\\"primer_plate/0\\\",\\\"primer_plate/1\\\"],\\n              [\\\"primer_plate/2\\\",\\\"primer_plate/3\\\"],\\n              [\\\"primer_plate/4\\\",\\\"primer_plate/5\\\"],\\n              [\\\"primer_plate/6\\\",\\\"primer_plate/7\\\"]\\n            ],\\n            \\\"annealing_temp\\\":\\\"60:celsius\\\"\\n          }\\n        },\\n      \\\"dependencies\\\": []\\n    }\\n  ]\\n}\\n\",\n      \"language\": \"json\"\n    }\n  ]\n}\n[/block]\nIn the folder containing those two files, you can now use the runner to see the JSON output of your protocol by executing `transcriptic preview MyqPCR`.\n\nCongratulations, you have written your first custom protocol!\n\nYou are now all set to follow the package upload direction in the package creation [quick-start guide](doc:package-creation-quickstart) to make this protocol available to all members of your organization.\n[block:api-header]\n{\n  \"type\": \"basic\",\n  \"title\": \"Submitting and testing your protocol\"\n}\n[/block]\nTo start writing your own protocol, please refer to the Autoprotocol specifications on [autoprotocol.org](http://www.autoprotocol.org) and the [autoprotocol-python library](https://github.com/autoprotocol/autoprotocol-python). \nTo access autoprotocol examples, you can fork the autoprotocol-core library. Another good place to start is to follow [the package creation quickstart](doc:package-creation-quickstart). \n\nIt is good practice to test the simplest case of each protocol first. If a protocol can be broken down into self-contained units, these should be tested separately first. For example for a cloning workflow (fragment generation, assembly, transformation, verification and final extraction) you can test each step separately before combining it in one workflow. Similarly, it is good practice to test the script with a small number of samples first. This reduces your turn-around times and costs. \n\nYou can submit a protocol of a package without uploading the entire package with the following command:\n\n`transcriptic preview MyProtocol | transcriptic submit --project MyProject`\n\nThis will use the preview parameters you specified in your `manifest.json` to create the run. \nNote that for Transcriptic runner to work you need to run `transcriptic login` first.\n\nWhen all individual parts of your protocol are optimized, you can combine them and run them together. Once you have completed this basic troubleshooting process you are ready to upload your package to your organization for easy use through the UI as illustrated [here](doc:package-creation-quickstart).","excerpt":"","slug":"how-to-write-a-new-protocol","type":"basic","title":"How to Write a New Protocol"}

How to Write a New Protocol


Writing a new protocol can be a complex undertaking, but following a structured process can help ensure better success. The basic workflow is: 1. Using pencil and paper, draw out a flow chart of all of the steps in your current protocol. 2. Annotate this chart with any information you need to consider while drafting the protocol. For example, what is your sample type? What are the details to the layout of your plate? What is the specific instruction as to how this sample has to be treated? For example, "the sample has to be returned to -20C." 3. Figure out the container form factor for each step in your flow chart. What's in a 1.5 ml tube? What is in 96-well flat-bottom (assay) plates? What should be done in 384-well PCR plates? Taking a look at the available [container types](doc:containers) and their details such as dead volume can aid in this process. 4. Decompose this flow chart into discrete processes. - For example, in a cloning protocol you may have a fragment generation step, an assembly step, a transformation step, a screening step, and a final growth and DNA extraction step. 5. Mark each step of each process with the relevant [Autoprotocol](http://autoprotocol.org/specification/) instruction (for example: your PCR step would be called `thermocycle` using Autoprotocol). 6. Make a list of all of the potential issues where a step might fail to result in successful, accurate results. This should include things like "the liquid handling in step X wasn't accurate", "there was cross-contamination in the samples at step Y" and "reagent Y was bad". 7. Turn the list of failure modes into a list of controls you will need to include. Annotate these controls onto the relevant steps in your flow chart. 8. Use the form factor and controls information to figure out how many sample wells you have at each step. From this, write down how you want to lay out samples on your containers at each step in your flow chart. How many samples can you process per plate? 9. Use the annotated flow chart you've now built to draft the protocol generation code. List all the autoprotocol instructions in the order required for your protocol and start to fill out the parameters for each. You can use the general [Autoprotocol JSON specifications](http://autoprotocol.org/specification/) or use the [Autoprotocol python library](https://github.com/autoprotocol/autoprotocol-python). Each of the discrete processes will be a separate script. For example in cloning you will have several scripts to cover source amplification, assembly, transformation and verification. qPCR on the other hand is a single script process. 10. [Add aliquots to your Transcriptic inventory](https://developers.transcriptic.com/#section-step-2-populate-your-inventory) using the shipping kit and finalize your draft by referring to those particular aliquots by their `id`s (an alphanumeric string starting with "ct"). 11. From this version you can generalize your protocol to take various numbers of aliquots or different types of reagents as well as other parameters. For example, to change the length of time you let the DNA anneal, you do not need to write a new qPCR script. You can simply adjust the parameter in the one you have already written. [block:api-header] { "type": "basic", "title": "Designing controls" } [/block] Every protocol you write should include thorough biological and technical controls. Though Transcriptic continuously monitors and validates device performance, the remote nature of Transcriptic's cloud laboratory requires you to think in a more structured way regarding your controls than you might be accustomed to when working by hand. In particular, automated liquid handling requires special attention. Whenever possible, you should include in-line technical controls using optical dyes to validate pipetting. The OrangeG dye, which is a part of the starter kit, is a convenient option as its absorbance at 475 nm correlates with its volume (this requires a clear flat-bottom plate). Pipetting a range of volumes randomly distributed across the plate should reveal a linear correlation of volume to absorbance with a correlation coefficient of >0.98. With this technical control you can, for example, distinguish between a general pipetting error and a source well running low in sample. In addition to technical controls, biological controls should be included. Negative as well as positive controls. During your design you will have identified several possible failure modes of the experiment. To assess contamination in an experiment involving bacteria, a subset of wells can be filled with media only to serve as negative control. It is most effective to distribute these wells randomly across the plate. Similarly, you should include a positive control that will help you to determine if all components of the reaction were working as expected. This is commonly done by repeating a reaction that has succeeded multiple times. The difference between the reaction components in the control versus the samples should be minimal, in the best case it is a single factor only. For example in a PCR reaction you would keep the PCR conditions and primers used stable, while changing the DNA template. Alternatively, you adjust a parameter in the PCR conditions, such as the annealing temperature, while keeping everything else (primers, DNA, etc.) constant. You may run many of these tests in parallel, where each well corresponds to a single change. With this setup you can screen a matrix of parameters in a small number of runs to optimize your conditions. [block:api-header] { "type": "basic", "title": "Example: Design a PCR workflow" } [/block] This example experiment is a high-throughput qPCR screen of gDNA for the presence or absence of certain genes/alleles. All assays use two primers that have the same annealing temperature. The PCR product length is similar across all assays with a maximum of 250bp. To date this has been done manually following this protocol: [block:image] { "images": [ { "image": [ "https://files.readme.io/m5cvNIzFRRGlFEzxJbvj_Screen%20Shot%202015-03-23%20at%2012.28.55%20PM.png", "Screen Shot 2015-03-23 at 12.28.55 PM.png", "1208", "1124", "#e12222", "" ], "caption": "Manual PCR protocol" } ] } [/block] To get us started, the general workflow can be represented in this basic flow chart: [block:image] { "images": [ { "image": [ "https://files.readme.io/lqub8Uk9Tz6DP9Dvjj7B_Flowchart%20workflow.001.png", "Flowchart workflow.001.png", "1024", "567", "#339344", "" ], "caption": "PCR basic workflow" } ] } [/block] Now we can add some basic information from our experimental design. We assume we have 96 samples and have four assays developed already. These can be run all on one 384-well PCR plate: [block:image] { "images": [ { "image": [ "https://files.readme.io/NeWgd3rZTPWLuHhUI4K9_Flowchart%20workflow.002.png", "Flowchart workflow.002.png", "1024", "570", "#349444", "" ], "caption": "PCR workflow with experiment specific notes" } ] } [/block] Now we can start adding the relevant Autoprotocol instructions and also consider any additional steps that need to be included. In this case, all source plates need to be sealed again and return to storage, whereas the tubes containing the SYBR Taq master mix can be discarded. [block:image] { "images": [ { "image": [ "https://files.readme.io/sYj9n0TTqVMTCaL5cXAO_Flowchart%20workflow.003.png", "Flowchart workflow.003.png", "1024", "768", "#2d8d3e", "" ], "caption": "PCR workflow annotated with autoprotocol instructions as well as adding final destination of plates" } ] } [/block] Next, we will consider control placement. Since this assay uses a PCR plate, we cannot read it in the plate reader to determine the amount of a standard dye that was added. But we can use positive and negative controls that are randomly distributed in our sample plate. Later, these will give us information about any potential contamination and sample quality. In addition to basic "all-or-none" control we can also add a standard curve using a serially diluted control. Using a serial dilution of known concentration we can later generate a standard curve and its linearity will be a proxy of pipetting accuracy. [block:image] { "images": [ { "image": [ "https://files.readme.io/cZZngZ6ZRmiKw8leMOf0_Flowchart%20workflow.005.png", "Flowchart workflow.005.png", "1224", "647", "#337dab", "" ], "caption": "Control placement" } ] } [/block] Finally, we take our instructions from the flow chart and start writing the code. In a first step, we can bring them in the order they should execute, add a reference to the correct plate, and add any other parameters we want to consider later, such as `mix_after`. Available parameters for all instructions can be found in the [Autoprotocol specification](http://autoprotocol.org/specification/). [block:image] { "images": [ { "image": [ "https://files.readme.io/fHJJXSb4T0TKymje0Xuw_Flowchart%20workflow.006.png", "Flowchart workflow.006.png", "1024", "319", "#131313", "" ], "caption": "Sort instructions to start writing the protocol" } ] } [/block] From this basic skeleton of instructions, you can start to write your script using your favorite language. If you chose python, Autoprotocol has a [library](https://github.com/autoprotocol/autoprotocol-python) that will help you get started. The documentation can be found [here](http://autoprotocol-python.readthedocs.org/en/latest/) and the next section gives you a short primer on how to get your system ready to develop and test your own protocols. [block:api-header] { "type": "basic", "title": "Installing all required tools" } [/block] **MacOSX** 1. Make sure you have the apple [command line tools](https://developer.apple.com/downloads/) or [XCode](http://developer.apple.com/xcode/) installed. 2. Install [homebrew](http://brew.sh/) by pasting this into your Terminal prompt: `ruby -e "$(curl -fsSL https://raw.githubusercontent.com/Homebrew/install/master/install)"`. 3. Update your path variable to refer to the Homebrew directory first. - In `~/.profile` add `export PATH=/usr/local/bin:/usr/local/sbin:$PATH` to the bottom of the file. **Linux** 1. You can install Linuxbrew, a version of homebrew, by following the instructions described [here](http://brew.sh/linuxbrew/). **Transcriptic tools** 1. Install python through homebrew by typing `brew install python`. 2. Use `pip install autoprotocol` to install the [autoprotocol python library](https://github.com/autoprotocol/autoprotocol-python). 3. Use `pip install transcriptic` to install the [Transcriptic runner](https://github.com/transcriptic/runner), a command-line tool for interacting with the Transcriptic API. [block:api-header] { "type": "basic", "title": "Writing your protocol" } [/block] From the prior outlines, we can now think of our parameters for the script. First, we will need to examine all the containers and aliquots that will come from your inventory and determine their type. The `dna_plate` will be a single container, whereas for `taq_tubes` we will refer to several aliquots and for `primer_pairs` we will take several groups of one or more primers. Similarly, we will want to specify some other parameters that can be different every time we run this protocol, such as the amount of primer to add, master mix to distribute or DNA to transfer. [block:code] { "codes": [ { "code": "\"inputs\": {\n \"dna_plate\":\"container\",\n \"taq_tubes\":\"aliquot+\",\n \"primer_vol_total\":\"volume\",\n \"mm_vol\":\"volume\",\n \"dna_vol\":\"volume\",\n \"primer_pairs\":\"aliquot++\",\n \"annealing_temp\":\"temperature\"\n}", "language": "json" } ] } [/block] We can now define some reasonable values for these parameters that we will use for trouble shooting the protocol and later on to create a preview of the protocol on the launch screen. To determine the volumes, let's assume we want to make a 20uL reaction, of which 2uL will be DNA. Hence the master mix will be 18uL per well. We want to make 96 reactions per master mix and to account for well dead-volume and small, but compounding inaccuracies in pipetting we will make a master mix for 110 reactions. We are using a SYBR master mix that is provided in the Taq tube as a 1x mix already. The vendor suggests we add 0.8uL of primer from a 400uM stock per reaction. So that means we have to add 88uL per each primer to its respective Taq tube. [block:code] { "codes": [ { "code": "\"parameters\": {\n \"dna_plate\":\"dna_plate\",\n \"taq_tubes\":[\"taq1/0\", \"taq2/0\", \"taq3/0\", \"taq4/0\"],\n \"primer_vol_total\":\"88:microliter\",\n \"mm_vol\":\"18:microliter\",\n \"dna_vol\":\"2:microliter\",\n \"primer_pairs\": [\n [\"primer_plate/0\",\"primer_plate/1\"],\n [\"primer_plate/2\",\"primer_plate/3\"],\n [\"primer_plate/4\",\"primer_plate/5\"],\n [\"primer_plate/6\",\"primer_plate/7\"]\n ],\n \"annealing_temp\":\"60:celsius\"\n}", "language": "json" } ] } [/block] In order to create a package and validate the protocol at a later time, we have to create the containers that this code is referring to. This does not create real containers, it is just used for code validation only. At the appropriate time, these containers will be substituted for the containers you select from your inventory. It is good practice to make the volumes in these containers match as realistically as possible, but it is not absolutely required. While the volumes for the `dna_plate` and `primer_plate` are set arbitrarily, the volume we want to provide in the Taq tubes is 1804uL since (110reactions*18uL)-(88uL*2primers) is 1804uL. [block:code] { "codes": [ { "code": "\"refs\":{\n \"primer_plate\": {\n \"type\": \"96-deep\",\n \"aliquots\": {\n \"0\": {\"volume\": \"500:microliter\"},\n \"1\": {\"volume\": \"500:microliter\"},\n \"2\": {\"volume\": \"500:microliter\"},\n \"3\": {\"volume\": \"500:microliter\"},\n \"4\": {\"volume\": \"500:microliter\"},\n \"5\": {\"volume\": \"500:microliter\"},\n \"6\": {\"volume\": \"500:microliter\"},\n \"7\": {\"volume\": \"500:microliter\"}\n },\n \"store\":\"cold_20\"\n },\n \"taq1\": {\n \"type\": \"micro-2.0\", \n \"aliquots\": {\n \"0\": {\"volume\": \"1804:microliter\"}\n },\n \"discard\": true\n },\n \"taq2\": {\n \"type\": \"micro-2.0\",\n \"aliquots\": {\n \"0\": {\"volume\": \"1804:microliter\"}\n },\n \"discard\": true\n },\n \"taq3\": {\n \"type\": \"micro-2.0\",\n \"aliquots\": {\n \"0\": {\"volume\": \"1804:microliter\"}\n },\n \"discard\": true\n },\n \"taq4\": {\n \"type\": \"micro-2.0\",\n \"aliquots\": {\n \"0\": {\"volume\": \"1804:microliter\"}\n },\n \"discard\": true\n },\n \"dna_plate\": {\n \"type\": \"96-pcr\",\n \"aliquots\": {\n \"0\": {\"volume\": \"50:microliter\"},\n \"1\": {\"volume\": \"50:microliter\"},\n \"2\": {\"volume\": \"50:microliter\"},\n \"3\": {\"volume\": \"50:microliter\"},\n \"4\": {\"volume\": \"50:microliter\"},\n \"5\": {\"volume\": \"50:microliter\"},\n \"6\": {\"volume\": \"50:microliter\"},\n \"7\": {\"volume\": \"50:microliter\"}\n },\n \"store\":\"cold_20\"\n }\n }", "language": "javascript", "name": "JSON" } ] } [/block] We can now start writing the first draft of our protocol, focusing on a single primer set. [block:code] { "codes": [ { "code": "from autoprotocol.util import make_dottable_dict\n\n\ndef myqPCR(protocol, params):\n params = make_dottable_dict(params)\n primer_plate = params.primer_pairs[0][0].container\n dest_plate = protocol.ref('dest_plate', cont_type='384-pcr', \n storage='cold_4')\n\n # transfer the first primer\n protocol.transfer(params.primer_pairs[0][0], params.taq_tubes[0],\n params.primer_vol_total)\n # transfer the second primer and mix the solution\n protocol.transfer(params.primer_pairs[0][1], params.taq_tubes[0], \n params.primer_vol_total,\n mix_after=True, mix_vol=params.primer_vol_total, \n repetitions=5)\n # distribute the master mix from the first Taq tube to the first \n # quadrant of the PCR plate, mix before aspirating the solution\n protocol.distribute(params.taq_tubes[0], dest_plate.quarter(0), \n params.mm_vol,\n allow_carryover=True, mix_before=True, \n mix_vol=params.primer_vol_total, repetitions=4)\n\n # add the DNA from the 96-well plate to the first quadrant and mix\n protocol.stamp(params.dna_plate, dest_plate, 0, params.dna_vol,\n mix_after=True, mix_vol=params.dna_vol, repetitions=3)\n # seal and thermocycle\n protocol.seal(dest_plate)\n protocol.thermocycle(dest_plate, [{\n \"cycles\": 1, \"steps\": [{\n \"temperature\": \"95:celsius\",\n \"duration\": \"3:minute\"}]\n }, {\n \"cycles\": 40, \"steps\": [{\n \"temperature\": \"95:celsius\",\n \"duration\": \"5:second\"}, {\n \"temperature\": params.annealing_temp,\n \"duration\": \"30:second\", \"read\": True}]\n }],\n volume=\"20:microliter\",\n dataref=\"myqPCR_data\",\n # read all wells for SYBR green dye\n dyes={\"SYBR\": dest_plate.all_wells().indices()},\n # standard melting curve parameters\n melting_start=\"65:celsius\",\n melting_end=\"95:celsius\",\n melting_increment=\"0.5:celsius\",\n melting_rate=\"5:second\")\n\t\t# seal source plates before they go back to storage\n protocol.seal(primer_plate)\n protocol.seal(params.dna_plate)\n \nif __name__ == '__main__':\n from autoprotocol.harness import run\n run(myqPCR)", "language": "python" } ] } [/block] Note how we identify the primer container by querying the container type of the first primer aliquot. This is needed for sealing the plate back later. To cover the case where the primers are presented on several 96-deep plates, we can do the following: [block:code] { "codes": [ { "code": "primer_plates = []\nfor primers in params.primer_pairs:\n for primer in primers:\n # list all containers that are used for primers\n primer_plates.append(primer.container)\n# find which ones are unique\nunique_primer_plates = set(primer_plates)\n...\nfor primer_plate in unique_primer_plates:\n\tprotocol.seal(primer_plate)", "language": "python" } ] } [/block] Similarly, we should now loop through all primer pairs and add them to the correct Taq tube: [block:code] { "codes": [ { "code": "for i, primer in enumerate(params.primer_pairs):\n\tprotocol.transfer(primer[0], params.taq_tubes[i], \n params.primer_vol_total)\n protocol.transfer(primer[1], params.taq_tubes[i], \n params.primer_vol_total, mix_after=True,\n mix_vol=params.primer_vol_total, repetitions=5)", "language": "python" } ] } [/block] Using the same approach, we can now implement our final protocol. It is good practice to assert that your protocol is used in the intended way. For example, this script can only take 4 different PCR reactions, so using an assert we can add a message that this script does currently not support `primer_pairs` with more than 4 entries. [block:code] { "codes": [ { "code": "from autoprotocol.util import make_dottable_dict\n\n\ndef myqPCR(protocol, params):\n params = make_dottable_dict(params)\n\n dest_plate = protocol.ref('dest_plate', cont_type='384-pcr',\n storage='cold_4')\n\n primer_plates = []\n for primers in params.primer_pairs:\n for primer in primers:\n primer_plates.append(primer.container)\n unique_primer_plates = set(primer_plates)\n\n assert len(params.taq_tubes) == len(params.primer_pairs), ('You are \tusing more primer pairs then you supply taq tubes.')\n \n assert len(params.taq_tubes) < 5, ('Currently this script only '\n 'supports up to 4 reactions as '\n 'defined by primer pairs and Taq '\n 'tubes')\n\n for i, primer in enumerate(params.primer_pairs):\n protocol.transfer(primer[0], params.taq_tubes[i],\n params.primer_vol_total)\n protocol.transfer(primer[1], params.taq_tubes[i],\n params.primer_vol_total, mix_after=True,\n mix_vol=params.primer_vol_total, repetitions=5)\n\n for i, tube in enumerate(params.taq_tubes):\n protocol.distribute(tube, dest_plate.quadrant(i), params.mm_vol,\n allow_carryover=True, mix_before=True,\n mix_vol=params.primer_vol_total,\n repetitions=4)\n\n for i in xrange(0, 3):\n protocol.stamp(params.dna_plate, dest_plate, params.dna_vol, i,\n mix_after=True, mix_vol=params.dna_vol,\n repetitions=3)\n\n protocol.seal(dest_plate)\n\n protocol.thermocycle(dest_plate, [{\n \"cycles\": 1, \"steps\": [{\n \"temperature\": \"95:celsius\",\n \"duration\": \"3:minute\"}]\n }, {\n \"cycles\": 40, \"steps\": [{\n \"temperature\": \"95:celsius\",\n \"duration\": \"5:second\"}, {\n \"temperature\": params.annealing_temp,\n \"duration\": \"30:second\", \"read\": True}]\n }],\n volume=\"20:microliter\",\n dataref=\"myqPCR_data\",\n dyes={\"SYBR\": dest_plate.all_wells().indices()},\n melting_start=\"65:celsius\",\n melting_end=\"95:celsius\",\n melting_increment=\"0.5:celsius\",\n melting_rate=\"5:second\")\n protocol.seal(params.dna_plate)\n for primer_plate in unique_primer_plates:\n protocol.seal(primer_plate)\n\nif __name__ == '__main__':\n from autoprotocol.harness import run\n run(myqPCR, 'MyqPCR')", "language": "python" } ] } [/block] Finally, we add our manifest.json with the information we defined first: [block:code] { "codes": [ { "code": "{\n \"version\": \"1.0.0\",\n \"format\": \"python\",\n \"license\": \"MIT\",\n \"protocols\": [\n {\n \"name\": \"MyqPCR\",\n \"description\": \"This is my first qPCR script\",\n \"command_string\": \"python -m myqPCR\",\n \"inputs\": {\n \"dna_plate\":\"container\",\n \"taq_tubes\":\"aliquot+\",\n \"primer_vol_total\":\"volume\",\n \"mm_vol\":\"volume\",\n \"dna_vol\":\"volume\",\n \"primer_pairs\":\"aliquot++\",\n \"annealing_temp\":\"temperature\"\n },\n \"preview\": {\n \"refs\":{\n \"primer_plate\": {\n \"type\": \"96-deep\",\n \"aliquots\": {\n \"0\": {\"volume\": \"500:microliter\"},\n \"1\": {\"volume\": \"500:microliter\"},\n \"2\": {\"volume\": \"500:microliter\"},\n \"3\": {\"volume\": \"500:microliter\"},\n \"4\": {\"volume\": \"500:microliter\"},\n \"5\": {\"volume\": \"500:microliter\"},\n \"6\": {\"volume\": \"500:microliter\"},\n \"7\": {\"volume\": \"500:microliter\"}\n },\n \"store\":\"cold_20\"\n },\n \"taq1\": {\n \"type\": \"micro-2.0\", \n \"aliquots\": {\n \"0\": {\"volume\": \"1804:microliter\"}\n },\n \"discard\": true\n },\n \"taq2\": {\n \"type\": \"micro-2.0\",\n \"aliquots\": {\n \"0\": {\"volume\": \"1804:microliter\"}\n },\n \"discard\": true\n },\n \"taq3\": {\n \"type\": \"micro-2.0\",\n \"aliquots\": {\n \"0\": {\"volume\": \"1804:microliter\"}\n },\n \"discard\": true\n },\n \"taq4\": {\n \"type\": \"micro-2.0\",\n \"aliquots\": {\n \"0\": {\"volume\": \"1804:microliter\"}\n },\n \"discard\": true\n },\n \"dna_plate\": {\n \"type\": \"96-pcr\",\n \"aliquots\": {\n \"0\": {\"volume\": \"50:microliter\"},\n \"1\": {\"volume\": \"50:microliter\"},\n \"2\": {\"volume\": \"50:microliter\"},\n \"3\": {\"volume\": \"50:microliter\"},\n \"4\": {\"volume\": \"50:microliter\"},\n \"5\": {\"volume\": \"50:microliter\"},\n \"6\": {\"volume\": \"50:microliter\"},\n \"7\": {\"volume\": \"50:microliter\"}\n },\n \"store\":\"cold_20\"\n }\n },\n \"parameters\": {\n \"dna_plate\":\"dna_plate\",\n \"taq_tubes\":[\"taq1/0\", \"taq2/0\", \"taq3/0\", \"taq4/0\"],\n \"primer_vol_total\":\"88:microliter\",\n \"mm_vol\":\"18:microliter\",\n \"dna_vol\":\"2:microliter\",\n \"primer_pairs\": [\n [\"primer_plate/0\",\"primer_plate/1\"],\n [\"primer_plate/2\",\"primer_plate/3\"],\n [\"primer_plate/4\",\"primer_plate/5\"],\n [\"primer_plate/6\",\"primer_plate/7\"]\n ],\n \"annealing_temp\":\"60:celsius\"\n }\n },\n \"dependencies\": []\n }\n ]\n}\n", "language": "json" } ] } [/block] In the folder containing those two files, you can now use the runner to see the JSON output of your protocol by executing `transcriptic preview MyqPCR`. Congratulations, you have written your first custom protocol! You are now all set to follow the package upload direction in the package creation [quick-start guide](doc:package-creation-quickstart) to make this protocol available to all members of your organization. [block:api-header] { "type": "basic", "title": "Submitting and testing your protocol" } [/block] To start writing your own protocol, please refer to the Autoprotocol specifications on [autoprotocol.org](http://www.autoprotocol.org) and the [autoprotocol-python library](https://github.com/autoprotocol/autoprotocol-python). To access autoprotocol examples, you can fork the autoprotocol-core library. Another good place to start is to follow [the package creation quickstart](doc:package-creation-quickstart). It is good practice to test the simplest case of each protocol first. If a protocol can be broken down into self-contained units, these should be tested separately first. For example for a cloning workflow (fragment generation, assembly, transformation, verification and final extraction) you can test each step separately before combining it in one workflow. Similarly, it is good practice to test the script with a small number of samples first. This reduces your turn-around times and costs. You can submit a protocol of a package without uploading the entire package with the following command: `transcriptic preview MyProtocol | transcriptic submit --project MyProject` This will use the preview parameters you specified in your `manifest.json` to create the run. Note that for Transcriptic runner to work you need to run `transcriptic login` first. When all individual parts of your protocol are optimized, you can combine them and run them together. Once you have completed this basic troubleshooting process you are ready to upload your package to your organization for easy use through the UI as illustrated [here](doc:package-creation-quickstart).