{"id":1602,"date":"2017-04-09T12:53:52","date_gmt":"2017-04-09T12:53:52","guid":{"rendered":"http:\/\/www.cellbiol.com\/bioinformatics_web_development\/?page_id=1602"},"modified":"2017-12-17T20:33:51","modified_gmt":"2017-12-17T20:33:51","slug":"the-reverse-complement-sequence-web-application","status":"publish","type":"page","link":"http:\/\/www.cellbiol.com\/bioinformatics_web_development\/chapter-5-developing-web-applications-for-bioinformatics\/the-reverse-complement-sequence-web-application\/","title":{"rendered":"5-2: The reverse-complement sequence web application"},"content":{"rendered":"<p>In this section we will write a web application able to <a href=\"http:\/\/www.cellbiol.com\/scripts\/complement\/dna_sequence_reverse_complement.php\">reverse, complement, or reverse-complement a DNA sequence<\/a>. Starting from a DNA sequence, the reverse-complement operation enables to compute the sequence of the complementary strand, as already discussed in <a href=\"http:\/\/www.cellbiol.com\/bioinformatics_web_development\/chapter-4-adding-a-dynamic-layer-introducing-the-php-programming-language\/php-programming-language-basics-more-on-strings-and-biological-sequences-manipulation-with-predefined-functions\/#reverse-complement\">section 4-7 of this book<\/a> where we have also provided a simple code able to achieve this operation. Building up on this code, <a href=\"http:\/\/www.cellbiol.com\/bioinformatics_web_development\/chapter-4-adding-a-dynamic-layer-introducing-the-php-programming-language\/php-programming-language-basics-writing-and-using-your-own-functions\/#reverse-complement\">in section 4-12 we have written a PHP function<\/a> able to perform the task. <\/p>\n<h2>Single sequence version<\/h2>\n<p>We will now leverage on a slightly improved version of this function, which supports IUPAC characters, to build a web application that can compute the reverse, complement, or reverse-complement of sequences provided by users, in a web context.<\/p>\n<p>We will also use the <a href=\"http:\/\/www.cellbiol.com\/bioinformatics_web_development\/chapter-4-adding-a-dynamic-layer-introducing-the-php-programming-language\/php-programming-language-basics-writing-and-using-your-own-functions\/#seqbreak\">sequence breaker function seqbreak()<\/a> to introduce a break every 80 nucleotides, to format the output sequence.<\/p>\n<p>Using the previously written functions, stored in a functions.php file that is then imported in the script file with an &#8220;include&#8221; statement, will allow the script.php code to be extremely compact.<\/p>\n<p>The application will support the FASTA format, the IUPAC code for degenerate sequences, and will have options to select the kind of transformation (reverse, complement or reverse-complement) to be applied on the input sequence.<\/p>\n<figure id=\"attachment_1651\" aria-describedby=\"caption-attachment-1651\" style=\"width: 1616px\" class=\"wp-caption alignnone\"><img loading=\"lazy\" decoding=\"async\" src=\"http:\/\/www.cellbiol.com\/bioinformatics_web_development\/wp-content\/uploads\/2017\/04\/reverse-complement-web-form.png\" alt=\"The reverse-complement application web form\" width=\"1616\" height=\"1362\" class=\"size-full wp-image-1651\" srcset=\"http:\/\/www.cellbiol.com\/bioinformatics_web_development\/wp-content\/uploads\/2017\/04\/reverse-complement-web-form.png 1616w, http:\/\/www.cellbiol.com\/bioinformatics_web_development\/wp-content\/uploads\/2017\/04\/reverse-complement-web-form-300x253.png 300w, http:\/\/www.cellbiol.com\/bioinformatics_web_development\/wp-content\/uploads\/2017\/04\/reverse-complement-web-form-768x647.png 768w, http:\/\/www.cellbiol.com\/bioinformatics_web_development\/wp-content\/uploads\/2017\/04\/reverse-complement-web-form-1024x863.png 1024w, http:\/\/www.cellbiol.com\/bioinformatics_web_development\/wp-content\/uploads\/2017\/04\/reverse-complement-web-form-1200x1011.png 1200w\" sizes=\"auto, (max-width: 709px) 85vw, (max-width: 909px) 67vw, (max-width: 1362px) 62vw, 840px\" \/><figcaption id=\"caption-attachment-1651\" class=\"wp-caption-text\">The reverse-complement application web form<\/figcaption><\/figure>\n<figure id=\"attachment_1653\" aria-describedby=\"caption-attachment-1653\" style=\"width: 1612px\" class=\"wp-caption alignnone\"><img loading=\"lazy\" decoding=\"async\" src=\"http:\/\/www.cellbiol.com\/bioinformatics_web_development\/wp-content\/uploads\/2017\/04\/reverse-complement-application-output.png\" alt=\"The output of the reverse-complement web application\" width=\"1612\" height=\"732\" class=\"size-full wp-image-1653\" srcset=\"http:\/\/www.cellbiol.com\/bioinformatics_web_development\/wp-content\/uploads\/2017\/04\/reverse-complement-application-output.png 1612w, http:\/\/www.cellbiol.com\/bioinformatics_web_development\/wp-content\/uploads\/2017\/04\/reverse-complement-application-output-300x136.png 300w, http:\/\/www.cellbiol.com\/bioinformatics_web_development\/wp-content\/uploads\/2017\/04\/reverse-complement-application-output-768x349.png 768w, http:\/\/www.cellbiol.com\/bioinformatics_web_development\/wp-content\/uploads\/2017\/04\/reverse-complement-application-output-1024x465.png 1024w, http:\/\/www.cellbiol.com\/bioinformatics_web_development\/wp-content\/uploads\/2017\/04\/reverse-complement-application-output-1200x545.png 1200w\" sizes=\"auto, (max-width: 709px) 85vw, (max-width: 909px) 67vw, (max-width: 1362px) 62vw, 840px\" \/><figcaption id=\"caption-attachment-1653\" class=\"wp-caption-text\">The output of the reverse-complement web application<\/figcaption><\/figure>\n<p>In this first version of the application we will accept as input a single DNA sequence. At the end of this section we propose a version able to handle several sequences.<\/p>\n<h3>The code<\/h3>\n<p>As usual, the code for the web application will be distributed across several files. The general structure is the same as the one of the application developed in the previous section. Directories names are in bold.<\/p>\n<p><strong>reverse-complement<\/strong><br \/>\n&nbsp;&nbsp;&nbsp;&nbsp;index.php<br \/>\n&nbsp;&nbsp;&nbsp;&nbsp;script.php<br \/>\n&nbsp;&nbsp;&nbsp;&nbsp;<strong>html<\/strong><br \/>\n&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;header.html<br \/>\n&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;footer.html<br \/>\n&nbsp;&nbsp;&nbsp;&nbsp;<strong>css<\/strong><br \/>\n&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;style.css<br \/>\n&nbsp;&nbsp;&nbsp;&nbsp;<strong>include<\/strong><br \/>\n&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;functions.php<\/p>\n<p>header.html<\/p>\n<pre lang=\"html\"><code>\r\n<!DOCTYPE html>\r\n<html lang=\"en\">\r\n    <head>\r\n        <meta charset=\"UTF-8\">\r\n        <title>A script to reverse-complement a DNA sequence<\/title>\r\n        <link rel=\"stylesheet\" href=\"css\/style.css\" type=\"text\/css\">\r\n    <\/head>\r\n    <body>\r\n        <div id=\"main-contents\">\r\n            <h1>Reverse, complement or reverse-complement a DNA sequence<\/h1>\r\n<\/code><\/pre>\n<p>footer.html<\/p>\n<pre lang=\"html\"><code>\r\n        <\/div>\r\n        <footer>\r\n            Contact us at webmaster@mywebsite.com\r\n        <\/footer>\r\n    <\/body>\r\n<\/html>\r\n<\/code><\/pre>\n<p>index.php<\/p>\n<pre lang=\"html\"><code>\r\n        <?php echo file_get_contents(\"html\/header.html\"); ?>\r\n        <form action=\"script.php\" method=\"POST\" enctype=\"multipart\/form-data\" id=\"revcomp_form\">\r\n            <fieldset id=\"data\">\r\n                <legend>Data<\/legend>\r\n                <p>\r\n                    <label for=\"fasta_sequence\">Your DNA sequence<\/label><br>\r\n                <\/p>\r\n                <p>\r\n                    <textarea name=\"fasta_sequence\" id=\"fasta_sequence\"><\/textarea>\r\n                <\/p>\r\n            <\/fieldset>\r\n            <fieldset id=\"options\">\r\n                <legend>Options<\/legend>\r\n                <p>\r\n                    <span class=\"field-title\" style=\"margin-bottom:10px;\">Select transformation<\/span>\r\n                <\/p>\r\n                <p>\r\n                    <input type=\"radio\" name=\"transformation\" value=\"rev\" id=\"rev\"> <label for=\"rev\" class=\"radio\">Reverse<\/label><br>\r\n                    <input type=\"radio\" name=\"transformation\" value=\"comp\" id=\"comp\"> <label for=\"comp\" class=\"radio\">Complement<\/label><br>\r\n                    <input type=\"radio\" name=\"transformation\" value=\"revcomp\" id=\"revcomp\" checked> <label for=\"revcomp\" class=\"radio\">Reverse-complement<\/label>\r\n                <\/p>\r\n            <\/fieldset>\r\n            <input type=\"submit\" value=\"Go!\">\r\n        <\/form>\r\n        <?php echo file_get_contents(\"html\/footer.html\"); ?>\r\n<\/code><\/pre>\n<p>functions.php<\/p>\n<p>The reverse-complement function &#8211; revcomp() &#8211; used in this section is modified with respect to the one proposed in section 4-12 so as to support all IUPAC characters for nucleotides (A, C, G, T, U, R, Y, S, W, K, M, B, D, H, V, N, ., -). More specifically, the complement dictionary associative array was extended.<\/p>\n<pre lang=\"php\"><code>\r\n<?php\r\nfunction process_fasta($fasta_sequence, $mode=\"all\"){\r\n    $fasta_lines = explode(\"\\n\", $fasta_sequence);\r\n    $header = \"> Generic\"; \/\/ We will store the header line here during the next foreach cycle\r\n    $sequence = \"\"; \/\/ We will store the sequence here during the next foreach cycle\r\n    foreach($fasta_lines as $line){\r\n        \/\/ We strip possible whitespace (or other characters) from the beginning and end of the line\r\n        $line = trim($line);\r\n        if(preg_match(\"\/^>\/\", $line)){  \/\/ If the line starts with a > it's the header line\r\n            $header = $line;\r\n        }\r\n        elseif($line != \"\"){\r\n            $sequence = $sequence.$line; \/\/ We concatenate each new sequence line in the $sequence variable\r\n        }\r\n    }\r\n    \r\n    \/\/ At this point we should have the FASTA header in the $header variable \r\n    \/\/ and the whole sequence in the $sequence variable\r\n\r\n    \/\/ And now the return part, that depends on value of $mode\r\n    if($mode == \"all\"){\r\n        return array($header, $sequence);\r\n    }\r\n    elseif($mode == \"seq\"){\r\n        return $sequence;\r\n    }\r\n    elseif($mode == \"header\"){\r\n        return $header;\r\n    }\r\n    else{\r\n        return \"WARNING: process_fasta mode not supported\";\r\n    }\r\n}\r\n\r\nfunction revcomp($sequence, $mode=\"revcomp\"){\r\n    $complement_dict = array(\r\n    \"A\" => \"T\",\r\n    \"T\" => \"A\",\r\n    \"G\" => \"C\",\r\n    \"C\" => \"G\",\r\n    \"U\" => \"A\",\r\n    \"R\" => \"Y\",\r\n    \"Y\" => \"R\",\r\n    \"S\" => \"W\",\r\n    \"W\" => \"S\",\r\n    \"K\" => \"M\",\r\n    \"M\" => \"K\",\r\n    \"B\" => \"D\",\r\n    \"D\" => \"B\",\r\n    \"H\" => \"V\",\r\n    \"V\" => \"H\",\r\n    \"N\" => \"N\",\r\n    \".\" => \".\",\r\n    \"-\" => \"-\"\r\n    );\r\n\r\n    $nucleotides = str_split($sequence,1);\r\n    \/\/ Let's compute the complement sequence first\r\n    $complement_sequence = \"\";\r\n    foreach($nucleotides as $nucleotide){\r\n        $complement_sequence = $complement_sequence.$complement_dict[$nucleotide];\r\n    }\r\n    \/\/ The complement sequence is now stored in the $complement_sequence variable\r\n \r\n    $revcomp_sequence = strrev($complement_sequence); \/\/ This is the reverse complement sequence\r\n    $reverse_sequence = strrev($sequence); \/\/ This is the reverse sequence\r\n\r\n    \/\/ We return different things depending on the $mode (second optional argument of this function)\r\n    \/\/ if we call the function with just one argument, the value of $mode will be the default, \"revcomp\"\r\n    \/\/ additional supported values for the $mode argument are \"comp\" and \"rev\", see below\r\n    \/\/ Note that when a function returns, it also exits, no more code inside the function is executed\r\n\r\n    if($mode == \"revcomp\"){\r\n        return $revcomp_sequence;\r\n    }\r\n    elseif($mode == \"comp\"){\r\n        return $complement_sequence;\r\n    }\r\n    elseif($mode == \"rev\"){\r\n        return $reverse_sequence;\r\n    }\r\n    else{  \/\/ This part may help us in debugging code in which the function is used\r\n        return \"WARNING: revcomp mode not supported\";\r\n    }\r\n}\r\n\r\nfunction seqbreak($sequence, $brlen=80, $brel=\"<br>\\n\"){ \/\/ $brel => breaking element\r\n    $chars = str_split($sequence, 1);\r\n    $i = 1;\r\n    $out = \"\";\r\n    foreach($chars as $char){\r\n        if(is_int($i\/$brlen)){\r\n            $out = $out.$char.$brel;\r\n        }\r\n        else{\r\n            $out = $out.$char;\r\n        }\r\n        $i++;\r\n    }\r\n    return $out;\r\n}\r\n?>\r\n<\/code><\/pre>\n<p>style.css<\/p>\n<pre lang=\"css\"><code>\r\nbody{\r\n    width: 800px;\r\n    margin-right:auto;\r\n    margin-left:auto;\r\n}\r\n\r\n#main-contents{\r\n    border:4px solid tomato;\r\n    margin-right:auto;\r\n    margin-left:auto;\r\n    margin-bottom: 20px;\r\n    padding:20px;\r\n    padding-top:0;\r\n}\r\n\r\nspan.sequence{\r\n    font-family:courier;\r\n    font-size:14px;\r\n}\r\n\r\nspan.header{\r\n    font-size:14px;\r\n}\r\n\r\nlabel{\r\n    cursor:pointer;\r\n    font-weight:bold;\r\n    color:teal;\r\n}\r\n\r\nlabel.radio{\r\n    font-weight:normal;\r\n}\r\n\r\nspan.field-title{\r\n    font-weight:bold;\r\n    color:teal;    \r\n}\r\n\r\nfieldset{\r\n    border:1px solid tomato;\r\n    margin-bottom:20px;    \r\n}\r\n\r\nlegend{\r\n    font-weight:bold;\r\n    color:tomato;\r\n}\r\n\r\ninput[type=submit] {\r\n    background-color: tomato;\r\n    border: none;\r\n    color: white;\r\n    padding: 5px 10px;\r\n    text-decoration: none;\r\n    margin: 4px 2px;\r\n    cursor: pointer;\r\n    text-transform: uppercase;\r\n    font-weight:bold;\r\n}\r\n\r\nh1{\r\n    color:tomato;\r\n    font-size:1.7em;\r\n}\r\n\r\ntextarea{\r\n    width:500px;\r\n    height:200px;\r\n    font-family:courier;\r\n    background:whitesmoke;  \r\n}\r\n\r\ninput[type=\"text\"]{\r\n    background:whitesmoke; \r\n}\r\n\r\nfooter{\r\n    text-align:center;\r\n}\r\n<\/code><\/pre>\n<p>script.php<\/p>\n<pre lang=\"php\"><code>\r\n<?php\r\ninclude(\"include\/functions.php\"); \/\/ We include the functions.php file\r\n$fasta_sequence = $_POST[\"fasta_sequence\"]; \/\/ and grab the sequence submitted by the user through the web form\r\n\/\/ We call it fasta_sequence rather than sequence as it may well be a FASTA sequence. The name of the\r\n\/\/ field in the web form (index.php) was also changed accordingly\r\n\r\n$transformation = $_POST[\"transformation\"]; \/\/ This will be revcomp (web form default), rev or comp\r\n \r\n$sequence = strtoupper(process_fasta($fasta_sequence, \"seq\")); \/\/ We use process_fasta() to extract the \"raw\" sequence \r\n\/\/ from the fasta_sequence and also make sure it is in uppercase characters\r\n$header = process_fasta($fasta_sequence, \"header\"); \/\/ We use process_fasta() to extract the header\r\n\r\n\/\/ We leverage on the revcomp() function to get the transformed sequence\r\n\/\/ Note how things are easy when we have a function to do the job\r\n\r\n$t_sequence = revcomp($sequence, $transformation);\r\n\r\n\/\/ We create the sequence ready for output by using the seqbreak() function\r\n\/\/ that introduces a break tag every 80 amino-acids\r\n\r\n$breaked_sequence = seqbreak($t_sequence);\r\n$out_sequence = \"<span class=\\\"sequence\\\">\".$breaked_sequence.\"<\/span>\";\r\n\r\n\/\/ We generate a $t_txt variable (transformation text) that is the complete version of the selected transformation\r\n\/\/ So we will be able to use \"reverse-complement\" instead of \"revcomp\", et-cetera.\r\nif($transformation == \"revcomp\"){\r\n    $t_txt = \"reverse-complement\"; \r\n}\r\nelseif($transformation == \"rev\"){\r\n    $t_txt = \"reverse\";    \r\n}\r\nelseif($transformation == \"comp\"){\r\n    $t_txt = \"complement\";    \r\n}\r\n\r\n\/\/ We create a new header for the transformed sequence by appending \"reverse-complement\", \"reverse\" or \"complement\"\r\n\/\/ to the original header, as appropriate\r\n$header_new = $header.\" - $t_txt\";\r\n \r\n\/\/ We now have all we need to provide an output to the user\r\n\/\/ We embed the output data within the same header and footer HTML code used in the web form\r\n\/\/ to ensure a consistent navigation experience and provide the feel that\r\n\/\/ everything takes place \"in the same website\"\r\n \r\necho file_get_contents(\"html\/header.html\"); \/\/ Writing the header HTML to the output page\r\n \r\necho \"<h2>Transformed sequence<\/h2>\\n\";\r\necho \"<p><strong>Selected transformation:<\/strong> $t_txt<\/p>\";\r\necho \"<p><span class=\\\"header\\\">$header_new<\/span><br>\\n\";\r\necho \"$out_sequence<\/p>\\n\";\r\n \r\necho file_get_contents(\"html\/footer.html\"); \/\/ Writing the footer HTML to the output page\r\n?>\r\n<\/code><\/pre>\n<p>You may <a href=\"http:\/\/www.cellbiol.com\/bioinformatics_web_development\/uploads\/reverse-complement\/\" target=\"_blank\">test the script live here<\/a>.<\/p>\n<h2>Batch version<\/h2>\n<p>Let&#8217;s now write a version of this application able to process several FASTA sequences at the same time, in batch.<\/p>\n<p>To accept multiple sequences in input, we will switch the FASTA processing function, from <a href=\"http:\/\/www.cellbiol.com\/bioinformatics_web_development\/chapter-4-adding-a-dynamic-layer-introducing-the-php-programming-language\/php-programming-language-basics-writing-and-using-your-own-functions\/#process_fasta\">process_fasta()<\/a> to <a href=\"http:\/\/www.cellbiol.com\/bioinformatics_web_development\/chapter-4-adding-a-dynamic-layer-introducing-the-php-programming-language\/php-programming-language-basics-writing-and-using-your-own-functions\/#fasta_sequences_to_array\">fasta_sequences_to_array()<\/a>. We have already written the code for both functions in <a href=\"http:\/\/www.cellbiol.com\/bioinformatics_web_development\/chapter-4-adding-a-dynamic-layer-introducing-the-php-programming-language\/php-programming-language-basics-writing-and-using-your-own-functions\/\">section 4-12<\/a>.<\/p>\n<p>The header, footer and css files remain unchanged with respect to the single sequence version. In the web form (index.php), the only change will be the name of the text-area, namely &#8220;fasta_sequence&#8221; will be changed to &#8220;fasta_sequences&#8221;. The id of the text-area and the &#8220;for&#8221; attribute of the text-area label will also be adjusted to this new value.<\/p>\n<p>index.php (batch version)<\/p>\n<pre lang=\"html\"><code>\r\n        <?php echo file_get_contents(\"html\/header.html\"); ?>\r\n        <form action=\"script.php\" method=\"POST\" enctype=\"multipart\/form-data\" id=\"revcomp_form\">\r\n            <fieldset id=\"data\">\r\n                <legend>Data<\/legend>\r\n                <p>\r\n                    <label for=\"fasta_sequences\">Your DNA sequence(s). Supports FASTA sequences in batch<\/label><br>\r\n                <\/p>\r\n                <p>\r\n                    <textarea name=\"fasta_sequences\" id=\"fasta_sequences\"><\/textarea>\r\n                <\/p>\r\n            <\/fieldset>\r\n            <fieldset id=\"options\">\r\n                <legend>Options<\/legend>\r\n                <p>\r\n                    <span class=\"field-title\" style=\"margin-bottom:10px;\">Select transformation<\/span>\r\n                <\/p>\r\n                <p>\r\n                    <input type=\"radio\" name=\"transformation\" value=\"rev\" id=\"rev\"> <label for=\"rev\" class=\"radio\">Reverse<\/label><br>\r\n                    <input type=\"radio\" name=\"transformation\" value=\"comp\" id=\"comp\"> <label for=\"comp\" class=\"radio\">Complement<\/label><br>\r\n                    <input type=\"radio\" name=\"transformation\" value=\"revcomp\" id=\"revcomp\" checked> <label for=\"revcomp\" class=\"radio\">Reverse-complement<\/label>\r\n                <\/p>\r\n            <\/fieldset>\r\n            <input type=\"submit\" value=\"Go!\">\r\n        <\/form>\r\n        <?php echo file_get_contents(\"html\/footer.html\"); ?>\r\n<\/code><\/pre>\n<figure id=\"attachment_1728\" aria-describedby=\"caption-attachment-1728\" style=\"width: 1612px\" class=\"wp-caption alignnone\"><img loading=\"lazy\" decoding=\"async\" src=\"http:\/\/www.cellbiol.com\/bioinformatics_web_development\/wp-content\/uploads\/2017\/04\/reverse-complement-form-batch.png\" alt=\"The web form for the reverse-complement application, batch version\" width=\"1612\" height=\"1362\" class=\"size-full wp-image-1728\" srcset=\"http:\/\/www.cellbiol.com\/bioinformatics_web_development\/wp-content\/uploads\/2017\/04\/reverse-complement-form-batch.png 1612w, http:\/\/www.cellbiol.com\/bioinformatics_web_development\/wp-content\/uploads\/2017\/04\/reverse-complement-form-batch-300x253.png 300w, http:\/\/www.cellbiol.com\/bioinformatics_web_development\/wp-content\/uploads\/2017\/04\/reverse-complement-form-batch-768x649.png 768w, http:\/\/www.cellbiol.com\/bioinformatics_web_development\/wp-content\/uploads\/2017\/04\/reverse-complement-form-batch-1024x865.png 1024w, http:\/\/www.cellbiol.com\/bioinformatics_web_development\/wp-content\/uploads\/2017\/04\/reverse-complement-form-batch-1200x1014.png 1200w\" sizes=\"auto, (max-width: 709px) 85vw, (max-width: 909px) 67vw, (max-width: 1362px) 62vw, 840px\" \/><figcaption id=\"caption-attachment-1728\" class=\"wp-caption-text\">The web form for the reverse-complement application, batch version, loaded with some <a href=\"http:\/\/www.cellbiol.com\/bioinformatics_web_development\/uploads\/sequences_src.txt\">test sequences<\/a><\/figcaption><\/figure>\n<p>In the functions file we replace process_fasta() with fasta_sequences_to_array().<\/p>\n<p>functions.php (batch version)<\/p>\n<pre lang=\"php\"><code>\r\n<?php\r\nfunction fasta_sequences_to_array($fasta_sequences){ \/\/ Takes a variable with FASTA sequences as input\r\n    $lines = preg_split(\"\/\\n\/\", $fasta_sequences); \/\/ Individual lines to an array\r\n    $seqs_array = array(); \r\n    $sequence = '';\r\n    $header_line = '';\r\n    $i = 0;\r\n    \r\n    foreach($lines as $line){\r\n        if(preg_match(\"\/^>\/\",$line)){\r\n            if($i != 0){\r\n                $seqs_array[] = array($header_line,$sequence);\r\n                $sequence = '';\r\n            }\r\n            $header_line = trim($line);\r\n            $i++;\r\n        }\r\n        elseif($line != ''){\r\n            $sequence .= strtoupper(trim($line));\r\n        }    \r\n    }\r\n    $seqs_array[] = array($header_line,$sequence);   \r\n    return $seqs_array;\r\n}\r\n\r\nfunction revcomp($sequence, $mode=\"revcomp\"){\r\n    $complement_dict = array(\r\n    \"A\" => \"T\",\r\n    \"T\" => \"A\",\r\n    \"G\" => \"C\",\r\n    \"C\" => \"G\",\r\n    \"U\" => \"A\",\r\n    \"R\" => \"Y\",\r\n    \"Y\" => \"R\",\r\n    \"S\" => \"W\",\r\n    \"W\" => \"S\",\r\n    \"K\" => \"M\",\r\n    \"M\" => \"K\",\r\n    \"B\" => \"D\",\r\n    \"D\" => \"B\",\r\n    \"H\" => \"V\",\r\n    \"V\" => \"H\",\r\n    \"N\" => \"N\",\r\n    \".\" => \".\",\r\n    \"-\" => \"-\"\r\n    );\r\n\r\n    $nucleotides = str_split($sequence,1);\r\n    \/\/ Let's compute the complement sequence first\r\n    $complement_sequence = \"\";\r\n    foreach($nucleotides as $nucleotide){\r\n        $complement_sequence = $complement_sequence.$complement_dict[$nucleotide];\r\n    }\r\n    \/\/ The complement sequence is now stored in the $complement_sequence variable\r\n \r\n    $revcomp_sequence = strrev($complement_sequence); \/\/ This is the reverse complement sequence\r\n    $reverse_sequence = strrev($sequence); \/\/ This is the reverse sequence\r\n\r\n    \/\/ We return different things depending on the $mode (second optional argument of this function)\r\n    \/\/ if we call the function with just one argument, the value of $mode will be the default, \"revcomp\"\r\n    \/\/ additional supported values for the $mode argument are \"comp\" and \"rev\", see below\r\n    \/\/ Note that when a function returns, it also exits, no more code inside the function is executed\r\n\r\n    if($mode == \"revcomp\"){\r\n        return $revcomp_sequence;\r\n    }\r\n    elseif($mode == \"comp\"){\r\n        return $complement_sequence;\r\n    }\r\n    elseif($mode == \"rev\"){\r\n        return $reverse_sequence;\r\n    }\r\n    else{  \/\/ This part may help us in debugging code in which the function is used\r\n        return \"WARNING: revcomp mode not supported\";\r\n    }\r\n}\r\n\r\nfunction seqbreak($sequence, $brlen=80, $brel=\"<br>\\n\"){ \/\/ $brel => breaking element\r\n    $chars = str_split($sequence, 1);\r\n    $i = 1;\r\n    $out = \"\";\r\n    foreach($chars as $char){\r\n        if(is_int($i\/$brlen)){\r\n            $out = $out.$char.$brel;\r\n        }\r\n        else{\r\n            $out = $out.$char;\r\n        }\r\n        $i++;\r\n    }\r\n    return $out;\r\n}\r\n?>\r\n<\/code><\/pre>\n<p>And here is the script. <\/p>\n<p>A line of the code may deserve some explanation.<\/p>\n<p>When we get the sequences from the web form, we convert them in an array ($seqs_array) with this structure:<\/p>\n<p>[(seq1 header, seq1 sequence),(seq2 header, seq2 sequence),(seq3 header, seq3 sequence), etc\u2026]<\/p>\n<p>with the fasta_sequences_to_array() function.<\/p>\n<p>In one line of code, we transfer this information to a second array, in which both the headers and the sequences are modified.<\/p>\n<p>More specifically, we append to each header a text ($t_txt) with &#8221; &#8211; reverse&#8221;, &#8221; &#8211; complement&#8221;, or &#8221; &#8211; reverse-complement&#8221;, depending on the transformation selected by the user.<\/p>\n<p>The sequences themselves are also modified according to the selected transformation. HTML tags are also added to the sequence. In particular a break tag is added every 80 nucleotides with the seqbreak() function and the whole sequence is embedded within a span tag with a &#8220;sequence&#8221; class, which has a font-family:courier in the CSS file.<\/p>\n<p>All of this is done in a single line of code within a foreach cycle:<\/p>\n<pre lang=\"php\"><code>\r\nforeach($seqs_array as $seq_array){\r\n    $seqs_array_t[] = array($seq_array[0].\" - $t_txt\", \"<span class=\\\"sequence\\\">\".seqbreak(revcomp(strtoupper($seq_array[1]), $transformation)).\"<\/span>\");   \r\n}\r\n<\/code><\/pre>\n<p>As it happens, to better understand the code, it should be read from right to left:<\/p>\n<ul>\n<li>The sequence ($seq_array[1]) is converted to uppercase, the only characters set the revcomp() function understands<\/li>\n<li>This uppercase sequence is passed as argument to revcomp() together with the selected transformation type ($transformation)<\/li>\n<li>The sequence transformed by revcomp() is added a break tag every 80 nucleotides with seqbreak()<\/li>\n<li>The sequence is then embedded within a span tag<\/li>\n<li>The header ($seq_array[0]) is added the appropriate text accounting for the transformation<\/li>\n<li>The transformed header and transformed and tagged sequence are the first and second element of an array<\/li>\n<li>This two elements array is added to the transformed sequences array $seqs_array_t<\/li>\n<\/ul>\n<p>Read the comments in the code to better understand the flow.<\/p>\n<p>script.php (batch version)<\/p>\n<pre lang=\"php\"><code>\r\n<?php\r\ninclude(\"include\/functions.php\"); \/\/ We include the functions.php file\r\n$fasta_sequences = $_POST[\"fasta_sequences\"]; \/\/ and grab the sequences submitted by the user through the web form\r\n\r\n$transformation = $_POST[\"transformation\"]; \/\/ This will be revcomp (web form default), rev or comp\r\n\r\n$seqs_array = fasta_sequences_to_array($fasta_sequences);\r\n\r\n$seqs_array_t = array(); \/\/ An empty array where the transformed sequences will be stored. t stays for \"transformed\"\r\n\r\n\/\/ Let's have some proper text values at hand to replace comp, revcomp and rev\r\n\/\/ in the user output\r\nif($transformation == \"revcomp\"){\r\n    $t_txt = \"reverse-complement\"; \r\n}\r\nelseif($transformation == \"rev\"){\r\n    $t_txt = \"reverse\";    \r\n}\r\nelseif($transformation == \"comp\"){\r\n    $t_txt = \"complement\";    \r\n}\r\n\r\nforeach($seqs_array as $seq_array){ \/\/ We transfer the sequences information from the original array to the transformed array.\r\n    \/\/ Since we are at it: we turn each sequence in uppercase, do the transformation, apply a break tag every 80 nucleotides\r\n    \/\/ and embed everything in a span tag with the class \"sequence\" so that the sequences will be in courier monoscpace font\r\n    \/\/ note how all of this is done sequentially in a single line of code\r\n    $seqs_array_t[] = array($seq_array[0].\" - $t_txt\", \"<span class=\\\"sequence\\\">\".seqbreak(revcomp(strtoupper($seq_array[1]), $transformation)).\"<\/span>\");   \r\n}\r\n \r\n \r\necho file_get_contents(\"html\/header.html\"); \/\/ Writing the header HTML to the output page\r\n \r\necho \"<h2>Transformed sequence(s)<\/h2>\\n\";\r\necho \"<p><strong>Selected transformation:<\/strong> $t_txt<\/p>\";\r\n\r\nforeach($seqs_array_t as $seq_array_t){\r\n    $header_t = $seq_array_t[0]; \/\/ Header transformed (_t)\r\n    $seq_t = $seq_array_t[1]; \/\/ Sequence transformed (and also properly HTML tagged, we did that in the previous foreach cycle)\r\n    echo \"<p>$header_t<br>$seq_t<\/p>\";\r\n}\r\n \r\necho file_get_contents(\"html\/footer.html\"); \/\/ Writing the footer HTML to the output page\r\n?>\r\n<\/code><\/pre>\n<figure id=\"attachment_1729\" aria-describedby=\"caption-attachment-1729\" style=\"width: 1614px\" class=\"wp-caption alignnone\"><img loading=\"lazy\" decoding=\"async\" src=\"http:\/\/www.cellbiol.com\/bioinformatics_web_development\/wp-content\/uploads\/2017\/04\/reverse-complement-batch-output.png\" alt=\"The reverse-complement web application output, batch version\" width=\"1614\" height=\"1686\" class=\"size-full wp-image-1729\" srcset=\"http:\/\/www.cellbiol.com\/bioinformatics_web_development\/wp-content\/uploads\/2017\/04\/reverse-complement-batch-output.png 1614w, http:\/\/www.cellbiol.com\/bioinformatics_web_development\/wp-content\/uploads\/2017\/04\/reverse-complement-batch-output-287x300.png 287w, http:\/\/www.cellbiol.com\/bioinformatics_web_development\/wp-content\/uploads\/2017\/04\/reverse-complement-batch-output-768x802.png 768w, http:\/\/www.cellbiol.com\/bioinformatics_web_development\/wp-content\/uploads\/2017\/04\/reverse-complement-batch-output-980x1024.png 980w, http:\/\/www.cellbiol.com\/bioinformatics_web_development\/wp-content\/uploads\/2017\/04\/reverse-complement-batch-output-1200x1254.png 1200w\" sizes=\"auto, (max-width: 709px) 85vw, (max-width: 909px) 67vw, (max-width: 1362px) 62vw, 840px\" \/><figcaption id=\"caption-attachment-1729\" class=\"wp-caption-text\">The reverse-complement web application output, batch version<\/figcaption><\/figure>\n<p>You may <a href=\"http:\/\/www.cellbiol.com\/bioinformatics_web_development\/uploads\/reverse-complement-batch\/\" target=\"_blank\">test the script live here<\/a>.<\/p>\n<div class=\"google-ad\"><script async src=\"\/\/pagead2.googlesyndication.com\/pagead\/js\/adsbygoogle.js\"><\/script><br \/>\n<!-- bioinfo web dev 2 --><br \/>\n<ins class=\"adsbygoogle\" style=\"display: inline-block; width: 728px; height: 90px;\" data-ad-client=\"ca-pub-0159360445983090\" data-ad-slot=\"3442176918\"><\/ins><br \/>\n<script>\n(adsbygoogle = window.adsbygoogle || []).push({});\n<\/script><\/div>\n<h2>Chapter Sections<\/h2>\n<p>[pagelist include=&#8221;1461&#8243;]<\/p>\n<p>[siblings]<\/p>\n<p>WORK IN PROGRESS ON CHAPTER 5!<\/p>\n","protected":false},"excerpt":{"rendered":"<p>In this section we will write a web application able to reverse, complement, or reverse-complement a DNA sequence. Starting from a DNA sequence, the reverse-complement operation enables to compute the sequence of the complementary strand, as already discussed in section 4-7 of this book where we have also provided a simple code able to achieve &hellip; <a href=\"http:\/\/www.cellbiol.com\/bioinformatics_web_development\/chapter-5-developing-web-applications-for-bioinformatics\/the-reverse-complement-sequence-web-application\/\" class=\"more-link\">Continue reading<span class=\"screen-reader-text\"> &#8220;5-2: The reverse-complement sequence web application&#8221;<\/span><\/a><\/p>\n","protected":false},"author":1,"featured_media":0,"parent":1461,"menu_order":2,"comment_status":"open","ping_status":"closed","template":"","meta":{"footnotes":""},"class_list":["post-1602","page","type-page","status-publish","hentry"],"_links":{"self":[{"href":"http:\/\/www.cellbiol.com\/bioinformatics_web_development\/wp-json\/wp\/v2\/pages\/1602","targetHints":{"allow":["GET"]}}],"collection":[{"href":"http:\/\/www.cellbiol.com\/bioinformatics_web_development\/wp-json\/wp\/v2\/pages"}],"about":[{"href":"http:\/\/www.cellbiol.com\/bioinformatics_web_development\/wp-json\/wp\/v2\/types\/page"}],"author":[{"embeddable":true,"href":"http:\/\/www.cellbiol.com\/bioinformatics_web_development\/wp-json\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"http:\/\/www.cellbiol.com\/bioinformatics_web_development\/wp-json\/wp\/v2\/comments?post=1602"}],"version-history":[{"count":74,"href":"http:\/\/www.cellbiol.com\/bioinformatics_web_development\/wp-json\/wp\/v2\/pages\/1602\/revisions"}],"predecessor-version":[{"id":3003,"href":"http:\/\/www.cellbiol.com\/bioinformatics_web_development\/wp-json\/wp\/v2\/pages\/1602\/revisions\/3003"}],"up":[{"embeddable":true,"href":"http:\/\/www.cellbiol.com\/bioinformatics_web_development\/wp-json\/wp\/v2\/pages\/1461"}],"wp:attachment":[{"href":"http:\/\/www.cellbiol.com\/bioinformatics_web_development\/wp-json\/wp\/v2\/media?parent=1602"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}