123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268 |
- <?php
- /**
- * @file
- * Contains tripal_views_handler_field_sequence
- */
- /**
- * Handles display of sequence data. If will aggregate sequences that need
- * to be aggregated (e.g. coding sequences) and provide
- *
- * @ingroup tripal_views
- */
- class tripal_views_handler_field_sequence extends views_handler_field {
- /**
- * {@inheritdoc}
- */
- function options_form(&$form, &$form_state) {
- parent::options_form($form, $form_state);
- $form['display'] = [
- '#type' => 'fieldset',
- '#title' => 'Format Output',
- '#description' => t('Alter the way a sequence is displayed'),
- ];
- $default_num_bases_per_line = '50';
- if ($this->options['display']['num_bases_per_line']) {
- $default_num_bases_per_line = $this->options['display']['num_bases_per_line'];
- }
- $default_output_format = 'raw';
- if ($this->options['display']['output_format']) {
- $default_ouput_format = $this->options['display']['output_format'];
- }
- $form['display']['num_bases_per_line'] = [
- '#type' => 'textfield',
- '#title' => t('Number of bases per line'),
- '#description' => t('Specify the number of bases per line. An HTML <br> tag ' .
- 'will be inserted after the number of bases indicated. If no value is ' .
- 'provided. The sequence will be one long string (default)'),
- '#default_value' => $default_num_bases_per_line,
- ];
- $form['display']['derive_from_parent'] = [
- '#type' => 'checkbox',
- '#title' => t('Derive sequence from parent'),
- '#description' => t('Rather than use the sequence from the \'residues\' of this feature, you may ' .
- 'derive the sequence from the parent features to which it is aligned. This is useful in the case that the feature ' .
- 'does not have sequence associated with it and we need to get it through it\'s alignment. ' .
- 'Note: this will slow queries with large numbers of results on the page.'),
- '#default_value' => $this->options['display']['derive_from_parent'],
- ];
- $form['display']['aggregate'] = [
- '#type' => 'checkbox',
- '#title' => t('Aggregate sub features'),
- '#description' => t('If the feature has sub features (e.g. CDS of an mRNA) then check this ' .
- 'box to filter the sequence to only include the sub features. Gaps between sub features will be ' .
- 'excluded from the sequence. This is useful for obtaining a complete CDS from an mRNA ' .
- 'without intronic sequence'),
- '#default_value' => $this->options['display']['aggregate'],
- ];
- $form['display']['output_format'] = [
- '#type' => 'radios',
- '#title' => t('Output format'),
- '#options' => [
- 'raw' => 'Raw sequence data (no formatting)',
- 'fasta_html' => 'FASTA in HTML format',
- 'fasta_txt' => 'FASTA in text format',
- ],
- '#description' => t('Choose an output format. Raw output cannot be used when the sequence is derived from the parent.'),
- '#default_value' => $default_ouput_format,
- ];
- }
- /**
- * {@inheritdoc}
- */
- function query() {
- parent::query();
- // if we are going to get the sequence from the parent then
- // we will need to do more queries in the render function
- // and we must have the feature_id to do those
- if ($this->options['display']['derive_from_parent']) {
- $this->ensure_my_table();
- $this->query->add_field($this->table, 'feature_id');
- $this->query->add_field($this->table, 'name');
- }
- }
- /**
- * {@inheritdoc}
- *
- * Prior to display of results we want to format the sequence
- */
- function render($values) {
- $residues = '';
- // get the number of bases to show per line
- $num_bases_per_line = $this->options['display']['num_bases_per_line'];
- $output_format = $this->options['display']['output_format'];
- // get the residues from the feature.residues column
- $field = $this->field_alias;
- // get the feature id
- $feature_id = $values->feature_feature_id;
- $feature_name = $values->feature_name;
- // the upstream and downstream values get set by the
- // tripal_views_handlers_filter_sequence.inc
- $upstream = $_SESSION['upstream'];
- $downstream = $_SESSION['downstream'];
- if (!$upstream) {
- $upstream = 0;
- }
- if (!$downstream) {
- $downstream = 0;
- }
- $derive_from_parent = $this->options['display']['derive_from_parent'];
- $aggregate = $this->options['display']['aggregate'];
- $residues = tripal_feature_get_formatted_sequence($feature_id, $feature_name,
- $num_bases_per_line, $derive_from_parent, $aggregate, $output_format,
- $upstream, $downstream);
- /*
- // if we need to get the sequence from the parent but there is no aggregation
- // then do so now.
- if ($this->options['display']['derive_from_parent']) {
-
- // execute our prepared statement
- if (tripal_core_is_sql_prepared('sequence_by_parent')) {
- $sql = "EXECUTE sequence_by_parent (%d, %d, %d)";
- $parents = chado_query($sql, $upstream, $downstream, $feature_id);
- }
-
- while ($parent = d-b_f-etch_object($parents)) {
- $seq = ''; // initialize the sequence for each parent
-
- // if we are to aggregate then we will ignore the feature returned
- // by the query above and rebuild it using the sub features
- if ($this->options['display']['aggregate']){
-
- // now get the sub features that are located on the parent.
- $sql = "EXECUTE sub_features (%d, %d)";
- $children = chado_query($sql, $feature_id, $parent->srcfeature_id);
- $sql = "EXECUTE count_sub_features (%d, %d)";
- $num_children = d-b_f-etch_object(chado_query($sql, $feature_id, $parent->srcfeature_id));
-
- // iterate through the sub features and concat their sequences. They
- // should already be in order.
- $types = array();
- $i = 0;
- while($child = d-b_f-etch_object($children)) {
- // keep up with the types
- if (!in_array($child->type_name,$types)) {
- $types[] = $child->type_name;
- }
-
- $sql = "EXECUTE sequence_by_parent (%d, %d, %d)";
-
- // if the first sub feature we need to include the upstream bases
- if ($i == 0 and $parent->strand >= 0) {
- // -------------------------- ref
- // ....----> ---->
- // up 1 2
- $q = chado_query($sql, $upstream, 0, $child->feature_id);
- }
- elseif ($i == 0 and $parent->strand < 0) {
- // -------------------------- ref
- // ....<---- <----
- // down 1 2
- $q = chado_query($sql, 0, $downstream, $child->feature_id);
- }
- // if the last sub feature we need to include the downstream bases
- elseif ($i == $num_children->num_children - 1 and $parent->strand >= 0) {
- // -------------------------- ref
- // ----> ---->....
- // 1 2 down
- $q = chado_query($sql, 0, $downstream, $child->feature_id);
- }
- elseif ($i == $num_children->num_children - 1 and $parent->strand < 0) {
- // -------------------------- ref
- // <---- <----....
- // 1 2 up
- $q = chado_query($sql, $upstream, 0, $child->feature_id);
- }
-
- // for internal sub features we don't want upstream or downstream bases
- else {
- $sql = "EXECUTE sequence_by_parent (%d, %d, %d)";
- $q = chado_query($sql, 0, 0, $child->feature_id);
- }
-
- while ($subseq = d-b_f-etch_object($q)){
- // concatenate the sequences of all the sub features
- if($subseq->srcfeature_id == $parent->srcfeature_id){
- $seq .= $subseq->residues;
- }
- }
- $i++;
- }
- }
- // if this isn't an aggregate then use the parent residues
- else {
- $seq = $parent->residues;
- }
-
- // get the reverse compliment if feature is on the reverse strand
- $dir = 'forward';
- if ($parent->strand < 0) {
- $seq = trpial_feature_reverse_complement($seq);
- $dir = 'reverse';
- }
-
- // now format for display
- if ($output_format == 'fasta_html') {
- $seq = wordwrap($seq, $num_bases_per_line, "<br>", TRUE);
- }
- elseif ($output_format == 'fasta_txt') {
- $seq = wordwrap($seq, $num_bases_per_line, "\n", TRUE);
- }
- $residues .= ">$feature_name ($parent->typename) $parent->srcname:" . ($parent->adjfmin + 1) . ".." . $parent->adjfmax ." ($dir). ";
- if (count($types) > 0) {
- $residues .= "Excludes all bases but those of type(s): " . implode(', ',$types) . ". " ;
- }
- if ($parent->upstream > 0) {
- $residues .= "Includes " . $parent->upstream . " bases upstream. ";
- }
- if ($parent->downstream > 0) {
- $residues .= "Includes " . $parent->downstream . " bases downstream. ";
- }
- if (!$seq) {
- $residues .= "No sequence available\n<br>";
- }
- else {
- if ($output_format == 'fasta_html') {
- $residues .= "<br>";
- }
- $residues .= "\n" . $seq . "\n";
- if ($output_format == 'fasta_html') {
- $residues .= "<br>";
- }
- }
- }
- }
- // if we are not getting the sequence from the parent sequence then
- // use what comes through from the feature record
- else {
- $residues = $values->$field;
- if ($output_format == 'fasta_html') {
- $residues = wordwrap($residues, $num_bases_per_line, "<br>", TRUE);
- }
- elseif ($output_format == 'fasta_txt') {
- $residues = wordwrap($residues, $num_bases_per_line, "\n", TRUE);
- }
- }
-
- // format the residues for display
- if($residues and $num_bases_per_line){
- if ($output_format == 'fasta_html') {
- $residues = '<span style="font-family: monospace;">' . $residues . '</span>';
- }
- } */
- return $residues;
- }
- }
|