Tripal v1.0 (6.x-1.0)
|
00001 <?php 00002 00010 class tripal_views_handler_field_sequence extends chado_views_handler_field { 00011 00012 function init(&$view, $options) { 00013 parent::init($view, $options); 00014 00015 } 00016 00020 function options_form(&$form, &$form_state) { 00021 parent::options_form($form, $form_state); 00022 00023 $form['display'] = array( 00024 '#type' => 'fieldset', 00025 '#title' => 'Format Output', 00026 '#description' => t('Alter the way a sequence is displayed') 00027 ); 00028 $default_num_bases_per_line = '50'; 00029 if ($this->options['display']['num_bases_per_line']) { 00030 $default_num_bases_per_line = $this->options['display']['num_bases_per_line']; 00031 } 00032 $default_output_format = 'raw'; 00033 if ($this->options['display']['output_format']) { 00034 $default_ouput_format = $this->options['display']['output_format']; 00035 } 00036 00037 $form['display']['num_bases_per_line'] = array( 00038 '#type' => 'textfield', 00039 '#title' => t('Number of bases per line'), 00040 '#description' => t('Specify the number of bases per line. An HTML <br> tag ' . 00041 'will be inserted after the number of bases indicated. If no value is ' . 00042 'provided. The sequence will be one long string (default)'), 00043 '#default_value' => $default_num_bases_per_line, 00044 ); 00045 $form['display']['derive_from_parent'] = array( 00046 '#type' => 'checkbox', 00047 '#title' => t('Derive sequence from parent'), 00048 '#description' => t('Rather than use the sequence from the \'residues\' of this feature, you may ' . 00049 'derive the sequence from the parent features to which it is aligned. This is useful in the case that the feature ' . 00050 'does not have sequence associated with it and we need to get it through it\'s alignment. ' . 00051 'Note: this will slow queries with large numbers of results on the page.'), 00052 '#default_value' => $this->options['display']['derive_from_parent'], 00053 ); 00054 $form['display']['aggregate'] = array( 00055 '#type' => 'checkbox', 00056 '#title' => t('Aggregate sub features'), 00057 '#description' => t('If the feature has sub features (e.g. CDS of an mRNA) then check this '. 00058 'box to filter the sequence to only include the sub features. Gaps between sub features will be '. 00059 'excluded from the sequence. This is useful for obtaining a complete CDS from an mRNA '. 00060 'without intronic sequence'), 00061 '#default_value' => $this->options['display']['aggregate'], 00062 ); 00063 $form['display']['output_format'] = array( 00064 '#type' => 'radios', 00065 '#title' => t('Output format'), 00066 '#options' => array( 00067 'raw' => 'Raw sequence data (no formatting)', 00068 'fasta_html' => 'FASTA in HTML format', 00069 'fasta_txt' => 'FASTA in text format', 00070 ), 00071 '#description' => t('Select an output format. Raw output cannot be used when the sequence is derived from the parent.'), 00072 '#default_value' => $default_ouput_format, 00073 ); 00074 } 00075 00079 function query() { 00080 parent::query(); 00081 00082 // if we are going to get the sequence from the parent then 00083 // we will need to do more queries in the render function 00084 // and we must have the feature_id to do those 00085 if ($this->options['display']['derive_from_parent']) { 00086 $this->ensure_my_table(); 00087 $this->query->add_field($this->table, 'feature_id'); 00088 $this->query->add_field($this->table, 'name'); 00089 } 00090 } 00091 00095 function render($values) { 00096 $residues = ''; 00097 00098 // get the number of bases to show per line 00099 $num_bases_per_line = $this->options['display']['num_bases_per_line']; 00100 $output_format = $this->options['display']['output_format']; 00101 00102 // get the residues from the feature.residues column 00103 $field = $this->field_alias; 00104 00105 // get the feature id 00106 $feature_id = $values->feature_feature_id; 00107 $feature_name = $values->feature_name; 00108 00109 // the upstream and downstream values get set by the 00110 // tripal_views_handlers_filter_sequence.inc 00111 $upstream = $_SESSION['upstream']; 00112 $downstream = $_SESSION['downstream']; 00113 if (!$upstream) { 00114 $upstream = 0; 00115 } 00116 if (!$downstream) { 00117 $downstream = 0; 00118 } 00119 00120 $derive_from_parent = $this->options['display']['derive_from_parent']; 00121 $aggregate = $this->options['display']['aggregate']; 00122 00123 $residues = tripal_feature_get_formatted_sequence($feature_id, $feature_name, 00124 $num_bases_per_line, $derive_from_parent, $aggregate, $output_format, 00125 $upstream, $downstream); 00126 /* 00127 // if we need to get the sequence from the parent but there is no aggregation 00128 // then do so now. 00129 if ($this->options['display']['derive_from_parent']) { 00130 00131 // execute our prepared statement 00132 if (tripal_core_is_sql_prepared('sequence_by_parent')) { 00133 $sql = "EXECUTE sequence_by_parent (%d, %d, %d)"; 00134 $parents = chado_query($sql, $upstream, $downstream, $feature_id); 00135 } 00136 00137 while ($parent = db_fetch_object($parents)) { 00138 $seq = ''; // initialize the sequence for each parent 00139 00140 // if we are to aggregate then we will ignore the feature returned 00141 // by the query above and rebuild it using the sub features 00142 if ($this->options['display']['aggregate']){ 00143 00144 // now get the sub features that are located on the parent. 00145 $sql = "EXECUTE sub_features (%d, %d)"; 00146 $children = chado_query($sql, $feature_id, $parent->srcfeature_id); 00147 $sql = "EXECUTE count_sub_features (%d, %d)"; 00148 $num_children = db_fetch_object(chado_query($sql, $feature_id, $parent->srcfeature_id)); 00149 00150 // iterate through the sub features and concat their sequences. They 00151 // should already be in order. 00152 $types = array(); 00153 $i = 0; 00154 while($child = db_fetch_object($children)) { 00155 // keep up with the types 00156 if (!in_array($child->type_name,$types)) { 00157 $types[] = $child->type_name; 00158 } 00159 00160 $sql = "EXECUTE sequence_by_parent (%d, %d, %d)"; 00161 00162 // if the first sub feature we need to include the upstream bases 00163 if ($i == 0 and $parent->strand >= 0) { 00164 // -------------------------- ref 00165 // ....----> ----> 00166 // up 1 2 00167 $q = chado_query($sql, $upstream, 0, $child->feature_id); 00168 } 00169 elseif ($i == 0 and $parent->strand < 0) { 00170 // -------------------------- ref 00171 // ....<---- <---- 00172 // down 1 2 00173 $q = chado_query($sql, 0, $downstream, $child->feature_id); 00174 } 00175 // if the last sub feature we need to include the downstream bases 00176 elseif ($i == $num_children->num_children - 1 and $parent->strand >= 0) { 00177 // -------------------------- ref 00178 // ----> ---->.... 00179 // 1 2 down 00180 $q = chado_query($sql, 0, $downstream, $child->feature_id); 00181 } 00182 elseif ($i == $num_children->num_children - 1 and $parent->strand < 0) { 00183 // -------------------------- ref 00184 // <---- <----.... 00185 // 1 2 up 00186 $q = chado_query($sql, $upstream, 0, $child->feature_id); 00187 } 00188 00189 // for internal sub features we don't want upstream or downstream bases 00190 else { 00191 $sql = "EXECUTE sequence_by_parent (%d, %d, %d)"; 00192 $q = chado_query($sql, 0, 0, $child->feature_id); 00193 } 00194 00195 while($subseq = db_fetch_object($q)){ 00196 // concatenate the sequences of all the sub features 00197 if($subseq->srcfeature_id == $parent->srcfeature_id){ 00198 $seq .= $subseq->residues; 00199 } 00200 } 00201 $i++; 00202 } 00203 } 00204 // if this isn't an aggregate then use the parent residues 00205 else { 00206 $seq = $parent->residues; 00207 } 00208 00209 // get the reverse compliment if feature is on the reverse strand 00210 $dir = 'forward'; 00211 if ($parent->strand < 0) { 00212 $seq = trpial_feature_reverse_complement($seq); 00213 $dir = 'reverse'; 00214 } 00215 00216 // now format for display 00217 if ($output_format == 'fasta_html') { 00218 $seq = wordwrap($seq, $num_bases_per_line, "<br>", TRUE); 00219 } 00220 elseif ($output_format == 'fasta_txt') { 00221 $seq = wordwrap($seq, $num_bases_per_line, "\n", TRUE); 00222 } 00223 $residues .= ">$feature_name ($parent->typename) $parent->srcname:" . ($parent->adjfmin + 1) . ".." . $parent->adjfmax ." ($dir). "; 00224 if (count($types) > 0) { 00225 $residues .= "Excludes all bases but those of type(s): " . implode(', ',$types) . ". " ; 00226 } 00227 if ($parent->upstream > 0) { 00228 $residues .= "Includes " . $parent->upstream . " bases upstream. "; 00229 } 00230 if ($parent->downstream > 0) { 00231 $residues .= "Includes " . $parent->downstream . " bases downstream. "; 00232 } 00233 if (!$seq) { 00234 $residues .= "No sequence available\n<br>"; 00235 } 00236 else { 00237 if ($output_format == 'fasta_html') { 00238 $residues .= "<br>"; 00239 } 00240 $residues .= "\n" . $seq . "\n"; 00241 if ($output_format == 'fasta_html') { 00242 $residues .= "<br>"; 00243 } 00244 } 00245 } 00246 } 00247 // if we are not getting the sequence from the parent sequence then 00248 // use what comes through from the feature record 00249 else { 00250 $residues = $values->$field; 00251 if ($output_format == 'fasta_html') { 00252 $residues = wordwrap($residues, $num_bases_per_line, "<br>", TRUE); 00253 } 00254 elseif ($output_format == 'fasta_txt') { 00255 $residues = wordwrap($residues, $num_bases_per_line, "\n", TRUE); 00256 } 00257 } 00258 00259 // format the residues for display 00260 if($residues and $num_bases_per_line){ 00261 if ($output_format == 'fasta_html') { 00262 $residues = '<span style="font-family: monospace;">' . $residues . '</span>'; 00263 } 00264 } */ 00265 return $residues; 00266 } 00267 }