|
|
(18 intermediate revisions not shown) |
Line 1: |
Line 1: |
- | {{:Team:EPF-Lausanne/Template/Header}} | + | {{:Team:EPF-Lausanne/Template/Header|human}} |
| + | |
| + | {{:Team:EPF-Lausanne/Template/SetTitle|Primer Design Helper}} |
| + | |
| + | Tired of designing primers manually? Fiddling with primer lengths to get the Tm just right? So were we! Use our (revolutionary, and wheel-reinventing) tool to design the primers for you. Simply put your sequence in the "DNA" field and select which kind of primers you want. Scroll down to see the results! The Tm is specially tailored for use with the NEBPhusion polymerase (which is, totally coincidentally, the one we use), but should be comparable to most others. |
| + | |
| + | The code is open-source, by the way. |
| | | |
| <html> | | <html> |
Line 5: |
Line 11: |
| <script type="text/javascript" src="http://ajax.googleapis.com/ajax/libs/jquery/1.7.2/jquery.min.js"></script> | | <script type="text/javascript" src="http://ajax.googleapis.com/ajax/libs/jquery/1.7.2/jquery.min.js"></script> |
| <script type="text/javascript" src="/Team:EPF-Lausanne/PrimerDesignHelper.js?action=raw&ctype=text/javascript"></script> | | <script type="text/javascript" src="/Team:EPF-Lausanne/PrimerDesignHelper.js?action=raw&ctype=text/javascript"></script> |
- | <script type="text/javascript"> | + | |
- | var tails = [ | + | <div id="formAttach"> <!-- style="width: 400px; float: left; padding-right: 15px; border-right: 1px solid #DDD"> --> |
- | {
| + | </div> |
- | name: "Biobrick (gene)",
| + | <div> <!-- style="width: 450px; float: right"> --> |
- | value: "biobrickGene",
| + | <fieldset> |
- | primer1Tail: "GTT TCT TCG AAT TCG CGG CCG CTT CTA G",
| + | <legend>Results</legend> |
- | primer2Tail: "GTT TCT TCC TGC AGC GGC CGC TAC TAG TA TTA TTA",
| + | <div id="outputAttach"> </div> |
- | messages: [
| + | </fieldset> |
- | "Don't forget to include the first ATG and to exclude the stop codon!",
| + | |
- | "The recommended minimum length of a BioBrick primer is 20bp",
| + | |
- | "The recommended Tm of a BioBrick primer is between 55 and 65 °C",
| + | |
- | "Check that the following restriction sites are absent: EcoRI, SpeI, XbaI, PstI, NotI",
| + | |
- | "Check out <a href='http://openwetware.org/wiki/Synthetic_Biology:BioBricks/Part_fabrication'>OpenWetWare's reference page</a>"
| + | |
- | ],
| + | |
- | validate: function(primer1, primer2){
| + | |
- | var end = primer2.substr(0, 3).toUpperCase();
| + | |
- | // TAA TGA TAG
| + | |
- | if(end == "TTA" || end == "TCA" || end == "CTA"){
| + | |
- | return "<b>Remove the stop codons from the sequence!</b>"
| + | |
- | }
| + | |
- | }
| + | |
- | },
| + | |
- | {
| + | |
- | name: "Biobrick (other)",
| + | |
- | value: "biobrickOther",
| + | |
- | primer1Tail: "GTT TCT TCG AAT TCG CGG CCG CTT CTA GAG",
| + | |
- | primer2Tail: "GTT TCT TCC TGC AGC GGC CGC TAC TAG TA",
| + | |
- | messages: [
| + | |
- | "The recommended minimum length of a BioBrick primer is 20bp",
| + | |
- | "The recommended Tm of a BioBrick primer is between 55 and 65 °C",
| + | |
- | "Check that the following restriction sites are absent: EcoRI, SpeI, XbaI, PstI, NotI",
| + | |
- | "Check out <a href='http://openwetware.org/wiki/Synthetic_Biology:BioBricks/Part_fabrication'>OpenWetWare's reference page</a>"
| + | |
- | ]
| + | |
- | }
| + | |
- | ];
| + | |
- | window.calc = function(){
| + | |
- | var data = document.getElementById("data").value;
| + | |
- | var isNormal = document.getElementById("primerTypeNormal").checked;
| + | |
- | var isRS = document.getElementById("primerTypeRestrictionSites").checked;
| + | |
- | var isKnown = document.getElementById("primerTypeKnownTail").checked;
| + | |
- | var goalTm = document.getElementById("goalTm").value;
| + | |
- |
| + | |
- | try{
| + | |
- | var p = new Primer(data);
| + | |
- | var validate = function(primer1, primer2){};
| + | |
- |
| + | |
- | if(isRS){
| + | |
- | p.setTails(Sequence.fromString(document.getElementById("primer1Tail").value), Sequence.fromString(document.getElementById("primer2Tail").value));
| + | |
- | }
| + | |
- |
| + | |
- | var messages = [];
| + | |
- | if(isKnown){
| + | |
- | var selected = $("#knownTailSelect").val();
| + | |
- |
| + | |
- | var tail1 = "";
| + | |
- | var tail2 = "";
| + | |
- |
| + | |
- | for(var i = 0; i < tails.length; i++){
| + | |
- | if(tails[i].value == selected){
| + | |
- | tail1 = tails[i].primer1Tail;
| + | |
- | tail2 = tails[i].primer2Tail;
| + | |
- | if(tails[i].messages)
| + | |
- | messages = [].concat(tails[i].messages);
| + | |
- | if(tails[i].validate)
| + | |
- | validate = tails[i].validate;
| + | |
- | }
| + | |
- | }
| + | |
- |
| + | |
- | p.setTails(Sequence.fromString(tail1), Sequence.fromString(tail2));
| + | |
- | }
| + | |
- |
| + | |
- | var primers = p.generate(goalTm);
| + | |
- |
| + | |
- | /*if(isRS){
| + | |
- | var rand1 = Sequence.fromRandom($("#primerRandBases").val());
| + | |
- | var rand2 = Sequence.fromRandom($("#primerRandBases").val());
| + | |
- | primers.primer1 = rand1.toString()+" "+primers.primer1;
| + | |
- | primers.primer2 = rand2.toString()+" "+primers.primer2;
| + | |
- | primers.primer1Tailbp += rand1.length();
| + | |
- | primers.primer2Tailbp += rand2.length();
| + | |
- | }*/
| + | |
- |
| + | |
- | var result = validate(primers.primer1NoTail, primers.primer2NoTail);
| + | |
- |
| + | |
- | if(result)
| + | |
- | messages.push(result);
| + | |
- |
| + | |
- | if(messages.length > 0){
| + | |
- | window.output({
| + | |
- | primers: primers,
| + | |
- | messages: messages
| + | |
- | });
| + | |
- | }else{
| + | |
- | window.output({
| + | |
- | primers: primers
| + | |
- | });
| + | |
- | }
| + | |
- | }catch(e){
| + | |
- | window.output({
| + | |
- | error: e.message
| + | |
- | });
| + | |
- | }
| + | |
- | };
| + | |
- | window.output = function(options){
| + | |
- | var output = {
| + | |
- | message: [],
| + | |
- | primer1: "No data",
| + | |
- | primer1Temp: "NaN",
| + | |
- | primer1bp: "NaN",
| + | |
- | primer1Tailbp: "NaN",
| + | |
- | primer2: "No data",
| + | |
- | primer2Temp: "NaN",
| + | |
- | primer2bp: "NaN",
| + | |
- | primer2Tailbp: "NaN"
| + | |
- | };
| + | |
- | if(options.error){
| + | |
- | output.message.push(options.error);
| + | |
- | }
| + | |
- | if(options.messages){
| + | |
- | output.message = output.message.concat(options.messages);
| + | |
- | }
| + | |
- | if(options.primers){
| + | |
- | for(var key in options.primers){
| + | |
- | if(key == "message"){
| + | |
- | output[key].push(options.primers[key]);
| + | |
- | }else{
| + | |
- | output[key] = options.primers[key];
| + | |
- | }
| + | |
- | }
| + | |
- | }
| + | |
- |
| + | |
- | if(Math.abs(output.primer1Temp - output.primer2Temp) > 5){
| + | |
- | output.message.push("The difference is more than 5 °C");
| + | |
- | }
| + | |
- |
| + | |
- | if(Math.min(output.primer1Temp, output.primer2Temp) > 72){
| + | |
- | output.message.push("Consider using the two-step PCR protocol");
| + | |
- | }
| + | |
- |
| + | |
- | if(Math.min(output.primer1Temp, output.primer2Temp) < 45){
| + | |
- | output.message.push("The annealing temperature should be more than 45 °C");
| + | |
- | }
| + | |
- |
| + | |
- | document.getElementById("messages").innerHTML = output.message.length > 0 ? "<ul><li>"+output.message.join("</li><li>")+"</li></ul>" : "";
| + | |
- | document.getElementById("primer1").innerHTML = output.primer1;
| + | |
- | document.getElementById("primer1Temp").innerHTML = output.primer1Temp;
| + | |
- | document.getElementById("primer1bp").innerHTML = output.primer1Tailbp != 0 && output.primer1Tailbp != "NaN" ? output.primer1Tailbp+" + "+output.primer1bp : output.primer1bp;
| + | |
- | document.getElementById("primer2").innerHTML = output.primer2;
| + | |
- | document.getElementById("primer2Temp").innerHTML = output.primer2Temp;
| + | |
- | document.getElementById("primer2bp").innerHTML = output.primer2Tailbp != 0 && output.primer2Tailbp != "NaN" ? output.primer2Tailbp+" + "+output.primer2bp : output.primer2bp;
| + | |
- | document.getElementById("annealingTemp").innerHTML = Math.min(output.primer1Temp, output.primer2Temp);
| + | |
- | };
| + | |
- |
| + | |
- | window.updateRadioElements = function(){
| + | |
- | if(document.getElementById('primerTypeRestrictionSites').checked){
| + | |
- | $('#restrictionSiteRow').show();
| + | |
- | }else{
| + | |
- | $('#restrictionSiteRow').hide();
| + | |
- | }
| + | |
- | if(document.getElementById('primerTypeKnownTail').checked){
| + | |
- | $('#knownTailRow').show();
| + | |
- | }else{
| + | |
- | $('#knownTailRow').hide();
| + | |
- | }
| + | |
- | };
| + | |
- | </script>
| + | |
- | <h1>Primer design helper</h1>
| + | |
- | <p>
| + | |
- | Warning: This is a very basic tool and should not be seen as a replacement for your brain. This is in no way a complete
| + | |
- | tool for primer design and shouldn't be trusted! Always check the results yourself. The Tm calculation is based on
| + | |
- | Belsauer et al. 1986 (with some small modifications, inspired by <a href="http://www.basic.northwestern.edu/biotools/oligocalc.html">http://www.basic.northwestern.edu/biotools/oligocalc.html</a>)
| + | |
- | and has as a goal to stay close (this means within 3-6 °C) to the results found by the <a href="http://www.neb.com/nebecomm/tech_reference/TmCalc/Default.asp">NEB Phusion HF-PCR reference</a>.
| + | |
- | The tail is ignored in the Tm calculation. | + | |
- | Also take a look at <a href="http://partsregistry.org/Help:Primers/Design">iGEM's primer design page</a>.
| + | |
- | </p>
| + | |
- | <p>
| + | |
- | Known limitations are: only A, C, G and T are accepted as input, the concentration of salts(30mM of Na+), | + | |
- | and the primer concentration (500nM) can't be set.
| + | |
- | </p>
| + | |
- | <p>
| + | |
- | Paste the sequence you want to PCR out in the following textarea:<br/>
| + | |
- | <textarea id="data" cols="50" rows="10" onkeyup="window.calc()" onchange="window.calc()"></textarea>
| + | |
- | </p>
| + | |
- | <p>
| + | |
- | Give some more info about what you want to do:<br/>
| + | |
- | <table>
| + | |
- | <tr>
| + | |
- | <td>Primer type</td>
| + | |
- | <td>
| + | |
- | <input type="radio" name="primerType" value="normal" id="primerTypeNormal" onchange="window.updateRadioElements();window.calc();" />
| + | |
- | <label for="primerTypeNormal">Standard PCR primer (extract the whole sequence)</label>
| + | |
- | <br />
| + | |
- | <input type="radio" name="primerType" value="restrictionSites" id="primerTypeRestrictionSites" onchange="window.updateRadioElements();window.calc();" />
| + | |
- | <label for="primerTypeRestrictionSites">Add custom tails on both ends</label>
| + | |
- | <br />
| + | |
- | <input type="radio" name="primerType" value="knownTail" id="primerTypeKnownTail" onchange="window.updateRadioElements();window.calc();" />
| + | |
- | <label for="primerTypeKnownTail">Add "known" tails on both ends</label>
| + | |
- | </td>
| + | |
- | </tr>
| + | |
- | <tr style="display: none" id="restrictionSiteRow">
| + | |
- | <td>Tails</td>
| + | |
- | <td>
| + | |
- | <!-- Random bases: <input type="input" id="primerRandBases" value="4" onkeyup="window.calc()" onchange="window.calc()" /><br />-->
| + | |
- | Primer 1 tail: 5'<input type="input" id="primer1Tail" onkeyup="window.calc()" onchange="window.calc()" />3'<br />
| + | |
- | Primer 2 tail: 5'<input type="input" id="primer2Tail" onkeyup="window.calc()" onchange="window.calc()" />3'
| + | |
- | </td>
| + | |
- | </tr>
| + | |
- | <tr style="display: none" id="knownTailRow">
| + | |
- | <td>Tail</td>
| + | |
- | <td>
| + | |
- | <select id="knownTailSelect" onkeyup="window.calc()" onchange="window.calc()">
| + | |
- | </select>
| + | |
- | <script type="text/javascript">
| + | |
- | for(var i = 0; i < tails.length; i++){
| + | |
- | $("#knownTailSelect").append(
| + | |
- | $("<option>")
| + | |
- | .val(tails[i].value)
| + | |
- | .text(tails[i].name)
| + | |
- | );
| + | |
- | }
| + | |
- | </script>
| + | |
- | </td>
| + | |
- | </tr>
| + | |
- | <tr> | + | |
- | <td>Goal Tm</td> | + | |
- | <td> | + | |
- | <input type="text" id="goalTm" onkeyup="window.calc()" onchange="window.calc()" value="55" /> °C
| + | |
- | </td>
| + | |
- | </tr> | + | |
- | <tr>
| + | |
- | <td> </td>
| + | |
- | <td>
| + | |
- | <input type="button" onclick="window.calc()" value="Calculate" />
| + | |
- | </td>
| + | |
- | </tr>
| + | |
- | </table>
| + | |
- | <script type="text/javascript">window.onload = function(){ window.updateRadioElements(); }</script>
| + | |
- | </p>
| + | |
- | <p>
| + | |
- | <h2>Result:</h2>
| + | |
- | <div id="messages">
| + | |
- |
| + | |
| </div> | | </div> |
- | <br /> | + | <div style="clear: both"> </div> |
- | <b>Primer 1 (<span id="primer1Temp">NaN</span> °C, <span id="primer1bp">NaN</span>bp):</b> 5' - <span id="primer1">No data</span> → 3'<br />
| + | <h2>Comments</h2> |
- | <b>Primer 2 (<span id="primer2Temp">NaN</span> °C, <span id="primer2bp">NaN</span>bp):</b> 5' - <span id="primer2">No data</span> → 3'<br />
| + | <p> |
- | <b>Annealing temp:</b> <span id="annealingTemp">NaN</span> °C
| + | Warning: This is a very basic tool and should not be seen as a replacement for your brain. This is in no way a complete |
- | </p>
| + | tool for primer design and shouldn't be trusted! Always check the results yourself. The Tm calculation is based on |
- | <script type="text/javascript">
| + | Belsauer et al. 1986 (with some small modifications, inspired by <a href="http://www.basic.northwestern.edu/biotools/oligocalc.html">http://www.basic.northwestern.edu/biotools/oligocalc.html</a>) |
- | window.calc();
| + | and has as a goal to stay close (in principle it should be the same) to the results found by the <a href="http://www.neb.com/nebecomm/tech_reference/TmCalc/Default.asp">NEB Phusion HF-PCR reference</a> (the kit we're using). |
- | </script>
| + | The tail is ignored in the Tm calculation. |
| + | Also take a look at <a href="http://partsregistry.org/Help:Primers/Design">iGEM's primer design page</a>. |
| + | </p> |
| + | <p> |
| + | Known limitations are: only A, C, G and T are accepted as input, the concentration of salts(50mM of Na+), |
| + | and the primer concentration (500nM) can't be set. |
| + | </p> |
| </html> | | </html> |
| | | |
| {{:Team:EPF-Lausanne/Template/Footer}} | | {{:Team:EPF-Lausanne/Template/Footer}} |