Browse Source

Nightly checkin .... fixed some issues that caused log entries. working on adding CDS sequences to sequence page

Stephen Ficklin 11 years ago
parent
commit
3b15f3b503

+ 1 - 3
tripal_bulk_loader/tripal_bulk_loader.module

@@ -36,9 +36,7 @@ require_once 'api/tripal_bulk_loader.DEPRECATED.inc';
  * @ingroup tripal_bulk_loader
  */
 function tripal_bulk_loader_init() {
-  // Add javascript and style sheet
-  drupal_add_css(drupal_get_path('theme', 'tripal') . '/css/tripal_bulk_loader.css');
-  drupal_add_js(drupal_get_path('theme', 'tripal') . '/js/tripal_bulk_loader.js');
+
 }
 
 /**

+ 1 - 1
tripal_core/theme/templates/node--chado-generic.tpl.php

@@ -3,7 +3,7 @@
 if($teaser) {
   print render($content);
 }
-else { 
+else {
   $node_type = $node->type; ?>
   
   <script type="text/javascript">

+ 1 - 1
tripal_cv/api/tripal_cv.api.inc

@@ -548,7 +548,7 @@ function tripal_insert_cvterm($term, $options = array()) {
 
   // add the database. The function will just return the DB object if the
   // database already exists.
-  $db = tripal_db_get_db_by_name($dbname);
+  $db = tripal_get_db(array('name' => $dbname));
   if (!$db) {
     $db = tripal_db_add_db($dbname);
   }

+ 0 - 11
tripal_cv/tripal_cv.module

@@ -34,17 +34,6 @@ require_once 'includes/tripal_cv.cvtermpath_form.inc';
  */
 function tripal_cv_init() {
 
-  // add the tripal_cv JS and CSS
-  drupal_add_css(drupal_get_path('module', 'tripal_cv') . '/theme/css/tripal_cv.css');
-  drupal_add_js(drupal_get_path('module', 'tripal_cv') . '/theme/js/tripal_cv.js');
-
-  // add the jgCharts.js
-  drupal_add_js(drupal_get_path('module', 'tripal_cv') . '/theme/js/jgcharts/jgcharts.js');
-
-  // add the jsTree JS and CSS
-  drupal_add_css(drupal_get_path('module', 'tripal_cv') . '/theme/js/jsTree/source/tree_component.css');
-  drupal_add_js(drupal_get_path('module', 'tripal_cv') . '/theme/js/jsTree/source/_lib.js');
-  drupal_add_js(drupal_get_path('module', 'tripal_cv') . '/theme/js/jsTree/source/tree_component.js');
 }
 
 /**

+ 2 - 2
tripal_db/api/tripal_db.api.inc

@@ -37,8 +37,8 @@
  * @param $identifier
  *   An array with the key stating what the identifier is. Supported keys (only on of the
  *   following unique keys is required):
- *    - db_id: the chado cv.cv_id primary key
- *    - name: the chado cv.name field (assume unique)
+ *    - db_id: the chado db.db_id primary key
+ *    - name: the chado db.name field (assume unique)
  * @param $options
  *   An array of options. Supported keys include:
  *     - Any keys supported by chado_generate_var(). See that function definition for

+ 2 - 2
tripal_example/tripal_example.info

@@ -32,13 +32,13 @@ version = 7.x-2.0.1-alpha
 ; Stylesheets containing CSS that should always be available for the
 ; module should be specified here.  
 ;
-stylesheets[all][] = theme/css/tripal_feature.css
+stylesheets[all][] = theme/css/tripal_example.css
 
 ;
 ; Javascript files that should always be available for the
 ; module should be specified here.  
 ;
-scripts[]          = theme/js/tripal_feature.js
+scripts[]          = theme/js/tripal_example.js
 
 ; 
 ; Add additional dependencies for other modules using the module project name.

+ 8 - 8
tripal_feature/api/tripal_feature.DEPRECATED.inc

@@ -376,9 +376,9 @@ function tripal_feature_reverse_complement($sequence) {
 /**
  * @deprecated Restructured API to make naming more readable and consistent.
  * Function was deprecated in Tripal 2.0 and will be removed 2 releases from now.
- * This function has been replaced by tripal_format_sequence().
+ * This function has been replaced by tripal_get_sequence().
  *
- * @see tripal_format_sequence().
+ * @see tripal_get_sequence().
  */
 function tripal_feature_get_formatted_sequence($feature_id, $feature_name, $num_bases_per_line, $derive_from_parent, $aggregate, $output_format, $upstream, $downstream, $sub_features = array(), $relationship = '', $rel_part = '') {
 
@@ -388,11 +388,11 @@ function tripal_feature_get_formatted_sequence($feature_id, $feature_name, $num_
     "DEPRECATED: %old_function has been replaced with %new_function. Please update your code.",
     array(
       '%old_function'=>'tripal_feature_get_formatted_sequence',
-      '%new_function' => 'tripal_format_sequence'
+      '%new_function' => 'tripal_get_sequence'
     )
   );
 
-  return tripal_format_sequence(
+  return tripal_get_sequence(
     // Feature
     array(
       'feature_id' => $feature_id,
@@ -474,9 +474,9 @@ function tripal_feature_add_cvterm($feature_id, $cvname, $cvterm) {
 /**
  * @deprecated Restructured API to make naming more readable and consistent.
  * Function was deprecated in Tripal 2.0 and will be removed 2 releases from now.
- * This function has been replaced by tripal_get_fasta_sequence().
+ * This function has been replaced by tripal_format_fasta_sequence().
  *
- * @see tripal_get_fasta_sequence().
+ * @see tripal_format_fasta_sequence().
  */
 function tripal_feature_return_fasta($feature, $desc) {
 
@@ -486,9 +486,9 @@ function tripal_feature_return_fasta($feature, $desc) {
     "DEPRECATED: %old_function has been replaced with %new_function. Please update your code.",
     array(
       '%old_function'=>'tripal_feature_return_fasta',
-      '%new_function' => 'tripal_get_fasta_sequence'
+      '%new_function' => 'tripal_format_fasta_sequence'
     )
   );
 
-  return tripal_get_fasta_sequence($feature, $desc);
+  return tripal_format_fasta_sequence($feature, $desc);
 }

+ 159 - 187
tripal_feature/api/tripal_feature.api.inc

@@ -54,64 +54,62 @@ function tripal_reverse_compliment_sequence($sequence) {
  * @param $options
  *   An associative array of options. Valid keys include:
  *    - width: Indicate the number of bases to use per line.  A new line will be added
- *      after the specified number of bases on each line.
+ *        after the specified number of bases on each line.
  *    - derive_from_parent: Set to '1' if the sequence should be obtained from the parent
- *      to which this feature is aligned.
+ *        to which this feature is aligned.
  *    - aggregate: Set to '1' if the sequence should only contain sub features, excluding
- *      intro sub feature sequence.  For example, set this option to obtain just
- *      the coding sequence of an mRNA.
+ *        intro sub feature sequence.  For example, set this option to obtain just
+ *        the coding sequence of an mRNA.
  *    - output_format: The type of format.  Valid formats include 'fasta_html', 'fasta_txt' and
- *      'raw'.  The format 'fasta_txt' outputs line breaks as <br> tags and the entire
- *      return value is in a <span> tag with a fixed-width font definition.  'fasta_txt'
- *      outputs line breaks with windows format carriage returns (e.g. \r\n) with no other
- *      formatting. The raw format is simply the sequence with now FASTA formatting and no
- *      line breaks.
+ *        'raw'.  The format 'fasta_txt' outputs line breaks as <br> tags and the entire
+ *        return value is in a <span> tag with a fixed-width font definition.  'fasta_txt'
+ *        outputs line breaks with windows format carriage returns (e.g. \r\n) with no other
+ *        formatting. The raw format is simply the sequence with no FASTA formatting and no
+ *        line breaks.
  *    - num_upstream: An integer specifing the number of upstream bases to include in the output
  *    - num_downstream: An integer specifying the number of downstream bases to include in the
- *      output.
+ *        output.
  *    - sub_feature_types: Only include sub features (or child features) of the types
- *      provided in the array
+ *        provided in the array
  *    - relationship_type: If a relationship name is provided (e.g. sequence_of) then any
- *      sequences that are in relationships of this type with matched sequences are also included
+ *        sequences that are in relationships of this type with matched sequences are also included
  *    - relationship_part: If a relationship is provided in the preceeding argument then
- *      the rel_part must be either 'object' or 'subject' to indicate which side of the
- *      relationship the matched features belong
+ *        the rel_part must be either 'object' or 'subject' to indicate which side of the
+ *        relationship the matched features belong
  *
  * @return
  *   The DNA/protein sequence formated as requested.
  *
  * @ingroup tripal_feature_api
  */
-function tripal_format_sequence($feature, $options) {
-
-  // Default Values
-  $feature_id = $feature['feature_id'];
-  $feature_name = $feature['name'];
-
-  $num_bases_per_line = $options['width'];
-  $derive_from_parent = $options['derive_from_parent'];
-  $aggregate = $options['aggregate'];
-  $output_format = $options['output_format'];
-  $upstream = $options['num_upstream'];
-  $downstream = $options['num_downstream'];
-  $sub_features = $options['sub_feature_types'];
-  $relationship = $options['relationship_type'];
-  $rel_part = $options['relationship_part'];
-
-  // to speed things up we need to make sure we have a persistent connection
-  $connection = tripal_db_persistent_chado();
-
-  if (!$upstream) {
-     $upstream = 0;
-  }
-  if (!$downstream) {
-     $downstream = 0;
+function tripal_get_sequence($feature, $options) {
+
+  // default values for finding the feature
+  $feature_id   = array_key_exists('feature_id', $feature) ? $feature['feature_id'] : 0;
+  $feature_name = array_key_exists('name', $feature)       ? $feature['name']       : '';
+
+  // default values for building the sequence
+  $num_bases_per_line = array_key_exists('width', $options)              ? $options['width']              : 50;
+  $derive_from_parent = array_key_exists('derive_from_parent', $options) ? $options['derive_from_parent'] : 0;
+  $aggregate          = array_key_exists('aggregate', $options)          ? $options['aggregate']          : 0;
+  $output_format      = array_key_exists('output_format', $options)      ? $options['output_format']      : 'fasta_txt';
+  $upstream           = array_key_exists('num_upstream', $options)       ? $options['num_upstream']       : 0;
+  $downstream         = array_key_exists('num_downstream', $options)     ? $options['num_downstream']     : 0;
+  $sub_features       = array_key_exists('sub_feature_types', $options)  ? $options['sub_feature_types']  : array();
+  $relationship       = array_key_exists('relationship_type', $options)  ? $options['relationship_type']  : '';
+  $rel_part           = array_key_exists('relationship_part', $options)  ? $options['relationship_part']  : '';
+  
+  if (!is_array($sub_features)) {
+    tripal_report_error('tripal_deprecated', TRIPAL_ERROR,
+      "'sub_features' option must be an array for function tripal_get_sequence().",
+      array()
+    );
+    return;
   }
 
   if ($rel_part == "object" or $rel_part == "subject") {
     if ($rel_part == "subject") {
-      $psql = '
-        PREPARE feature_rel_get_object (int, text) AS
+      $sql = '
         SELECT FO.feature_id, FO.name, FO.uniquename, CVTO.name as feature_type, O.genus, O.species
         FROM feature FS
           INNER JOIN feature_relationship FR ON FR.subject_id   = FS.feature_id
@@ -120,20 +118,13 @@ function tripal_format_sequence($feature, $options) {
           INNER JOIN cvterm CVTO             ON CVTO.cvterm_id  = FO.type_id
           INNER JOIN organism O              ON O.organism_id   = FO.organism_id
         WHERE
-          FS.feature_id = $1 AND
-          CVTFR.name    = $2
+          FS.feature_id = :feature_id AND
+          CVTFR.name    = :relationship
       ';
-      $status = tripal_core_chado_prepare('feature_rel_get_object', $psql, array('int', 'text'));
-      if (!$status) {
-        tripal_report_error('tripal_feature', TRIPAL_ERROR, "init: not able to prepare SQL statement '%name'",
-          array('%name' => 'feature_by_subject'));
-      }
-      $sql = "EXECUTE feature_rel_get_object(:feature_id, :relationship)";
       $features = chado_query($sql, array(':feature_id' => $feature_id, ':relationship' => $relationship));
     }
     if ($rel_part == "object") {
-      $psql = '
-        PREPARE feature_rel_get_subject (int, text) AS
+      $sql = '
         SELECT FS.feature_id, FS.name, FS.uniquename, CVTO.name as feature_type, O.genus, O.species
         FROM feature FO
           INNER JOIN feature_relationship FR ON FR.object_id    = FO.feature_id
@@ -142,15 +133,9 @@ function tripal_format_sequence($feature, $options) {
           INNER JOIN cvterm CVTO             ON CVTO.cvterm_id  = FS.type_id
           INNER JOIN organism O              ON O.organism_id   = FS.organism_id
         WHERE
-          FO.feature_id = $1 AND
-          CVTFR.name    = $2
+          FO.feature_id = :feature_id AND
+          CVTFR.name    = :relationship
       ';
-      $status = tripal_core_chado_prepare('feature_rel_get_subject', $psql, array('int', 'text'));
-      if (!$status) {
-        tripal_report_error('tripal_feature', TRIPAL_ERROR, "init: not able to prepare SQL statement '%name'",
-          array('%name' => 'feature_by_object'));
-      }
-      $sql = "EXECUTE feature_rel_get_subject(:feature_id, :relationship)";
       $features = chado_query($sql, array(':feature_id' => $feature_id, ':relationship' => $relationship));
     }
     $sequences = '';
@@ -163,135 +148,128 @@ function tripal_format_sequence($feature, $options) {
       if ($rel_part == "object") {
         $defline = "$feature->uniquename $feature->feature_type ($feature->genus $feature->species), $relationship, $feature_name";
       }
-      $sequences .= tripal_feature_get_formatted_sequence($feature->feature_id, $defline,
-        $num_bases_per_line, $derive_from_parent, $aggregate, $output_format,
-        $upstream, $downstream, $sub_features, '', '');
+      $sequences .= tripal_get_sequence(
+        array(
+          'feature_id' => $feature->feature_id, 
+          'name' => $defline
+        ),
+        array(
+          'width' => $num_bases_per_line, 
+          'derive_from_pareht' => $derive_from_parent, 
+          'aggregate' => $aggregate, 
+          'output_format' => $output_format,
+          'upstream' => $upstream, 
+          'downstream' => $downstream, 
+          'sub_features' => $sub_features, 
+        )
+      );
     }
     return $sequences;
   }
 
-  // prepare statements we'll need to use later
-  if (!tripal_core_is_sql_prepared('sequence_by_parent')) {
-    // prepare the queries we're going to use later during the render phase
-    // This SQL statement uses conditionals in the select clause to handle
-    // cases cases where the alignment is in the reverse direction and when
-    // the upstream and downstream extensions go beyond the lenght of the
-    // parent sequence.
-    $psql ='
-      PREPARE sequence_by_parent (int, int, int) AS
-      SELECT srcname, srcfeature_id, strand, srctypename, typename,
-        fmin, fmax, upstream, downstream, adjfmin, adjfmax,
-        substring(residues from (adjfmin + 1) for (upstream + (fmax - fmin) + downstream))  as residues,
-        genus, species
-      FROM (
-        SELECT
-          OF.name srcname, FL.srcfeature_id, FL.strand,
-          OCVT.name as srctypename, SCVT.name as typename,
-          FL.fmin, FL.fmax, OO.genus, OO.species,
-          CASE
-            WHEN FL.strand >= 0 THEN
-              CASE
-                 WHEN FL.fmin - $1 <= 0 THEN 0
-                 ELSE FL.fmin - $1
-              END
-            WHEN FL.strand < 0 THEN
-              CASE
-                 WHEN FL.fmin - $2 <= 0 THEN 0
-                 ELSE FL.fmin - $2
-              END
-          END as adjfmin,
-          CASE
-            WHEN FL.strand >= 0 THEN
-              CASE
-                WHEN FL.fmax + $2 > OF.seqlen THEN OF.seqlen
-                ELSE FL.fmax + $2
-              END
-            WHEN FL.strand < 0 THEN
-              CASE
-                WHEN FL.fmax + $1 > OF.seqlen THEN OF.seqlen
-                ELSE FL.fmax + $1
-              END
-          END as adjfmax,
-          CASE
-            WHEN FL.strand >= 0 THEN
-              CASE
-                 WHEN FL.fmin - $1 <= 0 THEN FL.fmin
-                 ELSE $1
-              END
-            ELSE
-              CASE
-                 WHEN FL.fmax + $1 > OF.seqlen THEN OF.seqlen - FL.fmax
-                 ELSE $1
-              END
-          END as upstream,
-          CASE
-            WHEN FL.strand >= 0 THEN
-              CASE
-                 WHEN FL.fmax + $2 > OF.seqlen THEN OF.seqlen - FL.fmax
-                 ELSE $2
-              END
-            ELSE
-              CASE
-                 WHEN FL.fmin - $2 <= 0 THEN FL.fmin
-                 ELSE $2
-              END
-          END as downstream,
-          OF.residues
-        FROM {featureloc} FL
-          INNER JOIN {feature} SF   on FL.feature_id    = SF.feature_id
-          INNER JOIN {cvterm}  SCVT on SF.type_id       = SCVT.cvterm_id
-          INNER JOIN {feature} OF   on FL.srcfeature_id = OF.feature_id
-          INNER JOIN {cvterm}  OCVT on OF.type_id       = OCVT.cvterm_id
-          INNER JOIN {organism} OO  on OF.organism_id   = OO.organism_id
-        WHERE SF.feature_id = $3 and NOT (OF.residues = \'\' or OF.residues IS NULL)) as tbl1
-    ';
-    $status = tripal_core_chado_prepare('sequence_by_parent', $psql, array('int', 'int', 'int'));
-    if (!$status) {
-      tripal_report_error('tripal_feature', TRIPAL_ERROR,
-        "init: not able to prepare SQL statement '%name'",
-        array('%name' => 'sequence_by_parent'));
-    }
-
-    // this query is meant to get all of the sub features of any given
-    // feature (arg #1) and order them as they appear on the reference
-    // feature (arg #2).
-    $psql ='PREPARE sub_features (int, int) AS
-            SELECT SF.feature_id, CVT.name as type_name, SF.type_id
-            FROM {feature_relationship} FR
-              INNER JOIN {feature} SF on SF.feature_id = FR.subject_id
-              INNER JOIN {cvterm} CVT on CVT.cvterm_id = SF.type_id
-              INNER JOIN {featureloc} FL on FL.feature_id = FR.subject_id
-              INNER JOIN {feature} PF on PF.feature_id = FL.srcfeature_id
-            WHERE FR.object_id = $1 and PF.feature_id = $2
-            ORDER BY FL.fmin ASC';
-    $status = tripal_core_chado_prepare('sub_features', $psql, array('int', 'int'));
-    if (!$status) {
-      tripal_report_error('tripal_feature', TRIPAL_ERROR,
-        "init: not able to prepare SQL statement '%name'",
-        array('%name' => 'ssub_features'));
-    }
-    $psql ='PREPARE count_sub_features (int, int) AS
-            SELECT count(*) as num_children
-            FROM {feature_relationship} FR
-              INNER JOIN {feature} SF on SF.feature_id = FR.subject_id
-              INNER JOIN {cvterm} CVT on CVT.cvterm_id = SF.type_id
-              INNER JOIN {featureloc} FL on FL.feature_id = FR.subject_id
-              INNER JOIN {feature} PF on PF.feature_id = FL.srcfeature_id
-            WHERE FR.object_id = $1 and PF.feature_id = $2';
-    $status = tripal_core_chado_prepare('count_sub_features', $psql, array('int', 'int'));
-    if (!$status) {
-      tripal_report_error('tripal_feature', TRIPAL_ERROR,
-        "init: not able to prepare SQL statement '%name'",
-        array('%name' => 'count_sub_features'));
-    }
-  }
+  // prepare the queries we're going to use later during the render phase
+  // This SQL statement uses conditionals in the select clause to handle
+  // cases cases where the alignment is in the reverse direction and when
+  // the upstream and downstream extensions go beyond the lenght of the
+  // parent sequence.
+  $sql ='
+    SELECT srcname, srcfeature_id, strand, srctypename, typename,
+      fmin, fmax, upstream, downstream, adjfmin, adjfmax,
+      substring(residues from (adjfmin + 1) for (upstream + (fmax - fmin) + downstream))  as residues,
+      genus, species
+    FROM (
+      SELECT
+        OF.name srcname, FL.srcfeature_id, FL.strand,
+        OCVT.name as srctypename, SCVT.name as typename,
+        FL.fmin, FL.fmax, OO.genus, OO.species,
+        CASE
+          WHEN FL.strand >= 0 THEN
+            CASE
+               WHEN FL.fmin - :upstream <= 0 THEN 0
+               ELSE FL.fmin - :upstream
+            END
+          WHEN FL.strand < 0 THEN
+            CASE
+               WHEN FL.fmin - :downstream <= 0 THEN 0
+               ELSE FL.fmin - :downstream
+            END
+        END as adjfmin,
+        CASE
+          WHEN FL.strand >= 0 THEN
+            CASE
+              WHEN FL.fmax + :downstream > OF.seqlen THEN OF.seqlen
+              ELSE FL.fmax + :downstream
+            END
+          WHEN FL.strand < 0 THEN
+            CASE
+              WHEN FL.fmax + :upstream > OF.seqlen THEN OF.seqlen
+              ELSE FL.fmax + :upstream
+            END
+        END as adjfmax,
+        CASE
+          WHEN FL.strand >= 0 THEN
+            CASE
+               WHEN FL.fmin - :upstream <= 0 THEN FL.fmin
+               ELSE :upstream
+            END
+          ELSE
+            CASE
+               WHEN FL.fmax + :upstream > OF.seqlen THEN OF.seqlen - FL.fmax
+               ELSE :upstream
+            END
+        END as upstream,
+        CASE
+          WHEN FL.strand >= 0 THEN
+            CASE
+               WHEN FL.fmax + :downstream > OF.seqlen THEN OF.seqlen - FL.fmax
+               ELSE :downstream
+            END
+          ELSE
+            CASE
+               WHEN FL.fmin - :downstream <= 0 THEN FL.fmin
+               ELSE :downstream
+            END
+        END as downstream,
+        OF.residues
+      FROM {featureloc} FL
+        INNER JOIN {feature} SF   on FL.feature_id    = SF.feature_id
+        INNER JOIN {cvterm}  SCVT on SF.type_id       = SCVT.cvterm_id
+        INNER JOIN {feature} OF   on FL.srcfeature_id = OF.feature_id
+        INNER JOIN {cvterm}  OCVT on OF.type_id       = OCVT.cvterm_id
+        INNER JOIN {organism} OO  on OF.organism_id   = OO.organism_id
+      WHERE SF.feature_id = :feature_id and NOT (OF.residues = \'\' or OF.residues IS NULL)) as tbl1
+  ';
+  // this query is meant to get all of the sub features of any given
+  // feature (arg #1) and order them as they appear on the reference
+  // feature (arg #2).
+  $sfsql = '
+    SELECT SF.feature_id, CVT.name as type_name, SF.type_id
+    FROM {feature_relationship} FR
+      INNER JOIN {feature} SF on SF.feature_id = FR.subject_id
+      INNER JOIN {cvterm} CVT on CVT.cvterm_id = SF.type_id
+      INNER JOIN {featureloc} FL on FL.feature_id = FR.subject_id
+      INNER JOIN {feature} PF on PF.feature_id = FL.srcfeature_id
+    WHERE FR.object_id = :feature_id and PF.feature_id = :srcfeature_id
+    ORDER BY FL.fmin ASC
+  ';
+  // for counting the number of children
+  $fsql ='
+    SELECT count(*) as num_children
+    FROM {feature_relationship} FR
+      INNER JOIN {feature} SF on SF.feature_id = FR.subject_id
+      INNER JOIN {cvterm} CVT on CVT.cvterm_id = SF.type_id
+      INNER JOIN {featureloc} FL on FL.feature_id = FR.subject_id
+      INNER JOIN {feature} PF on PF.feature_id = FL.srcfeature_id
+    WHERE FR.object_id = :feature_id and PF.feature_id = :srcfeature_id
+  ';
 
   // if we need to get the sequence from the parent then do so now.
   if ($derive_from_parent) {
+    
+    $residues = '';
 
     // execute the query to get the sequence from the parent
-    $sql = "EXECUTE sequence_by_parent (:upstream, :downstream, :feature_id)";
-    $parents = chado_query($sql, array(':uptream' => $upstream, ':downstream' => $downstream, ':feature_id' => $feature_id));
+    $parents = chado_query($sql, array(':upstream' => $upstream, ':downstream' => $downstream, ':feature_id' => $feature_id));
 
     while ($parent = $parents->fetchObject()) {
       $seq = '';  // initialize the sequence for each parent
@@ -301,11 +279,8 @@ function tripal_format_sequence($feature, $options) {
       if ($aggregate) {
 
         // now get the sub features that are located on the parent.
-        $sql = "EXECUTE sub_features (:feature_id, :srcfeature_id)";
-        $children = chado_query($sql, array(':feature_id' => $feature_id, ':srcfeature_id' => $parent->srcfeature_id));
-        $sql = "EXECUTE count_sub_features (:feature_id, :srcfeature_id)";
-        $sub_features = chado_query($sql, array(':feature_id' => $feature_id, ':srcfeature_id' => $parent->srcfeature_id));
-        $num_children = $sub_features->fetchObject();
+        $children = chado_query($sfsql, array(':feature_id' => $feature_id, ':srcfeature_id' => $parent->srcfeature_id));
+        $num_children = chado_query($fsql, array(':feature_id' => $feature_id, ':srcfeature_id' => $parent->srcfeature_id))->fetchObject();
 
         // iterate through the sub features and concat their sequences. They
         // should already be in order.
@@ -324,8 +299,6 @@ function tripal_format_sequence($feature, $options) {
             $types[] = $child->type_name;
           }
 
-          $sql = "EXECUTE sequence_by_parent (:upstream, %d, :feature_id)";
-
           // if the first sub feature we need to include the upstream bases. first check if
           // the feature is in the foward direction or the reverse.
           if ($i == 0 and $parent->strand >= 0) {  // forward direction
@@ -358,7 +331,6 @@ function tripal_format_sequence($feature, $options) {
 
           // 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, array(':upstream' => 0, ':downstream' => 0, ':feature_id' => $child->feature_id));
           }
 
@@ -458,7 +430,7 @@ function tripal_format_sequence($feature, $options) {
  *
  * @ingroup tripal_feature_api
  */
-function tripal_get_fasta_sequence($feature, $desc) {
+function tripal_format_fasta_sequence($feature, $desc) {
 
   $fasta  = ">" . variable_get('chado_feature_accession_prefix', 'FID') . "$feature->feature_id|$feature->name";
   $fasta .= " $desc\n";

+ 2 - 0
tripal_feature/theme/css/tripal_feature.css

@@ -13,6 +13,8 @@ pre.tripal_feature-sequence {
   height: 300px;
   overflow: scroll; 
   border: 1px solid #DDDDDD;
+  max-width: 500px;
+  white-space: normal;
 }
 
 div#tripal_feature-featureloc_sequence-legend {

+ 1 - 1
tripal_feature/theme/templates/tripal_feature_properties.tpl.php

@@ -6,7 +6,7 @@ $feature = chado_expand_var($feature, 'table', 'featureprop', $options);
 $properties = $feature->featureprop;
 
 if(count($properties) > 0){ 
-    
+  
   // the $headers array is an array of fields to use as the colum headers.
   // additional documentation can be found here
   // https://api.drupal.org/api/drupal/includes%21theme.inc/function/theme_table/7

+ 76 - 31
tripal_feature/theme/templates/tripal_feature_sequence.tpl.php

@@ -1,22 +1,11 @@
 <?php
 /*
- * There are two ways that sequences can be displayed.  They can come from the 
- * feature.residues column or they can come from an alignment with another feature.  
- * This template will show both or one or the other depending on the data available.
- * 
- * For retreiving the sequence from an alignment we would typically make a call to
- * chado_expand_var function.  For example, to retrieve all
- * of the featurelocs in order to get the sequences needed for this template, the
- * following function call would be made:
- *
- *   $feature = chado_expand_var($feature,'table','featureloc');
- *
- * Then all of the sequences would need to be retreived from the alignments and
- * formatted for display below.  However, to simplify this template, this has already
- * been done by the tripal_feature module and the sequences are made available in
- * the variable:
- *
- *   $feature->featureloc_sequences
+ * There are several ways that sequences can be displayed.  They can come from the 
+ * feature.residues column,  they can come from an alignment with another feature,
+ * they can come from a protein sequence that has relationship with this sequence,
+ * or they can come from sub children (e.g. CDS coding sequences).
+ *   
+ * This template will show all types depending on the data available.
  *
  */
 
@@ -69,31 +58,58 @@ if ($residues or count($featureloc_sequences) > 0) {
   // variable that we use to get the proteins.
   $all_relationships = $feature->all_relationships;
   $object_rels = $all_relationships['object'];
+  $has_coding_seq = 0;
   foreach ($object_rels as $rel_type => $rels){
     foreach ($rels as $subject_type => $subjects){
       foreach ($subjects as $subject){
+        
+        // add in protein sequence if it has residues
         if ($rel_type == 'derives from' and $subject_type == 'polypeptide') {
           $protein = $subject->record->subject_id;
           $protein = chado_expand_var($protein, 'field', 'feature.residues');
           
-          $list_items[] = '<a href="#residues">Protein sequence of ' . $protein->name . '</a>';
-          $sequences_html .= '<a name="protein-' . $protein->feature_id . '"></a>';
-          $sequences_html .= '<div id="protein-' . $protein->feature_id . '" class="tripal_feature-sequence-item">';
-          $sequences_html .= '<p><b>Protein sequence of ' . $protein->name . '</b></p>';
-          $sequences_html .= '<pre class="tripal_feature-sequence">';
-          $sequences_html .= '>' . tripal_get_fasta_defline($protein) . "\n";
-          $sequences_html .= preg_replace("/(.{50})/","\\1<br>", $protein->residues);
-          $sequences_html .= '</pre>';
-          $sequences_html .= '<a href="#sequences-top">back to top</a>';
-          $sequences_html .= '</div>';
+          if ($protein->residues) {
+            $list_items[] = '<a href="#residues">Protein sequence of ' . $protein->name . '</a>';
+            $sequences_html .= '<a name="protein-' . $protein->feature_id . '"></a>';
+            $sequences_html .= '<div id="protein-' . $protein->feature_id . '" class="tripal_feature-sequence-item">';
+            $sequences_html .= '<p><b>Protein sequence of ' . $protein->name . '</b></p>';
+            $sequences_html .= '<pre class="tripal_feature-sequence">';
+            $sequences_html .= '>' . tripal_get_fasta_defline($protein) . "\n";
+            $sequences_html .= preg_replace("/(.{50})/","\\1<br>", $protein->residues);
+            $sequences_html .= '</pre>';
+            $sequences_html .= '<a href="#sequences-top">back to top</a>';
+            $sequences_html .= '</div>';
+          }
         }
-        // add any other sequences by by relationship in a similar way
+        
+        // we want to know if there are any coding sequences associated with this feature
+        // if so we will use some code a bit later on to get those sequences
+        if ($rel_type == 'part of' and $subject_type == 'CDS') {
+          $has_coding_seq = 1;
+        }
+        
+        // add any other sequences that are related through a relationship
+        // and that have values in the 'residues' column
       }
     }
   }
   
-  // ADD IN ALIGNMENT SEQUENCES FOR THIS FEATURE
-  // show the alignment sequences first as they are colored with child features
+  
+  /* ADD IN ALIGNMENT SEQUENCES FOR THIS FEATURE
+   * For retreiving the sequence from an alignment we would typically make a call to
+   * chado_expand_var function.  For example, to retrieve all
+   * of the featurelocs in order to get the sequences needed for this template, the
+   * following function call would be made:
+   *
+   *   $feature = chado_expand_var($feature,'table','featureloc');
+   *
+   * Then all of the sequences would need to be retreived from the alignments and
+   * formatted for display below.  However, to simplify this template, this has already
+   * been done by the tripal_feature module and the sequences are made available in
+   * the variable: 
+   *
+   *   $feature->featureloc_sequences
+   */
   if(count($featureloc_sequences) > 0){
     foreach($featureloc_sequences as $src => $attrs){
       // the $attrs array has the following keys
@@ -102,7 +118,7 @@ if ($residues or count($featureloc_sequences) > 0) {
       //   * location:  the alignment location
       //   * defline: the definition line
       //   * formatted_seq: the formatted sequences
-      $list_items[] = '<a href="#' . $attrs['src'] . '">Alignment at  ' . $attrs['location'];
+      $list_items[] = '<a href="#' . $attrs['src'] . '">Alignment at  ' . $attrs['location'] . "</a>";
       $sequences_html .= '<a name="' . $attrs['src'] . '"></a>';
       $sequences_html .= '<div id="' . $attrs['src'] . '" class="tripal_feature-sequence-item">';
       $sequences_html .= '<p><b>Alignment at  ' . $attrs['location'] .'</b></p>';
@@ -112,6 +128,35 @@ if ($residues or count($featureloc_sequences) > 0) {
     }
   }
   
+  // CODING SEQUENCES
+  // add in any CDS sequences. 
+  if ($has_coding_seq) {
+    // use the tripal_get_sequence() API function to retreive the CDS sequences
+    $cds_sequence = tripal_get_sequence(
+      array(
+        'feature_id' => $feature->feature_id,
+        'name' => $feature->name, 
+      ),
+      array(
+        'width' => 50,  // FASTA sequence should have 50 chars per line
+        'derive_from_parent' => 1, // CDS are in parent-child relationships so we want to use the sequence from the parent
+        'aggregate' => 1, // we want to combine all CDS for this feature into a single sequence
+        'output_format' => 'fasta_txt', // we just want plain text, we'll format it here.
+        'sub_feature_types' => array('CDS'), // we're looking for CDS features
+        ''
+      )
+    );
+    $list_items[] = '<a href="#coding_sequence">Coding sequence </a>';
+    $sequences_html .= '<a name="coding_sequence"></a>';
+    $sequences_html .= '<div id="coding_sequence" class="tripal_feature-sequence-item">';
+    $sequences_html .= '<p><b>Coding sequence</b></p>';
+    $sequences_html .= '<pre class="tripal_feature-sequence">';
+    $sequences_html .= $cds_sequence;
+    $sequences_html .= '</pre>';
+    $sequences_html .= '<a href="#sequences-top">back to top</a>';
+    $sequences_html .= '</div>';
+  }
+  
   // first add a list at the top of the page that can be formatted as the
   // user desires.  We use the theme_item_list function of Drupal to create 
   // the list rather than hard-code the HTML here.  Instructions for how

+ 575 - 0
tripal_feature/theme/tripal_feature.theme.inc

@@ -35,6 +35,428 @@ function tripal_feature_preprocess_tripal_feature_sequence(&$variables) {
     $feature->all_relationships = tripal_feature_get_feature_relationships($feature);
   }
 }
+
+/**
+ * Get the sequence this feature is located on
+ *
+ * @param $feature_id
+ * @param $featurelocs
+ *
+ * @ingroup tripal_feature
+ */
+function tripal_feature_load_featureloc_sequences($feature_id, $featurelocs) {
+
+  // if we don't have any featurelocs then no point in continuing
+  if (!$featurelocs) {
+    return array();
+  }
+
+  // get the list of relationships (including any aggregators) and iterate
+  // through each one to find information needed to color-code the reference sequence
+  $relationships = tripal_feature_get_aggregate_relationships($feature_id);
+  if (!$relationships) {
+    return array();
+  }
+
+
+  // iterate through each of the realtionships features and get their
+  // locations
+  foreach ($relationships as $rindex => $rel) {
+    // get the featurelocs for each of the relationship features
+    $rel_featurelocs = tripal_feature_load_featurelocs($rel->subject_id, 'as_child', 0);
+    foreach ($rel_featurelocs as $rfindex => $rel_featureloc) {
+      // keep track of this unique source feature
+      $src = $rel_featureloc->src_feature_id . "-" . $rel_featureloc->src_cvterm_id;
+
+      // copy over the results to the relationship object.  Since there can
+      // be more than one feature location for each relationship feature we
+      // use the '$src' variable to keep track of these.
+      $rel->featurelocs = new stdClass();
+      $rel->featurelocs->$src = new stdClass();
+      $rel->featurelocs->$src->src_uniquename = $rel_featureloc->src_uniquename;
+      $rel->featurelocs->$src->src_cvterm_id  = $rel_featureloc->src_cvterm_id;
+      $rel->featurelocs->$src->src_cvname     = $rel_featureloc->src_cvname;
+      $rel->featurelocs->$src->fmin           = $rel_featureloc->fmin;
+      $rel->featurelocs->$src->fmax           = $rel_featureloc->fmax;
+      $rel->featurelocs->$src->src_name       = $rel_featureloc->src_name;
+
+      // keep track of the individual parts for each relationship
+      $start = $rel->featurelocs->$src->fmin;
+      $end   = $rel->featurelocs->$src->fmax;
+      $type  = $rel->subject_type;
+      $rel_locs[$src]['parts'][$start][$type]['start'] = $start;
+      $rel_locs[$src]['parts'][$start][$type]['end']   = $end;
+      $rel_locs[$src]['parts'][$start][$type]['type']  = $type;
+    }
+  }
+
+  // the featurelocs array provided to the function contains the locations
+  // where this feature is found.   We want to get the sequence for each
+  // location and then annotate it with the parts found from the relationships
+  // locations determiend above.
+  $floc_sequences = array();
+  foreach ($featurelocs as $featureloc) {
+
+    // build the src name so we can keep track of the different parts for each feature
+    $src = $featureloc->srcfeature_id->feature_id . "-" . $featureloc->srcfeature_id->type_id->cvterm_id;
+
+    // orient the parts to the beginning of the feature sequence
+    if (!empty($rel_locs[$src]['parts'])) {
+      $parts = $rel_locs[$src]['parts'];
+      $rparts = array();  // we will fill this up if we're on the reverse strand
+
+      foreach ($parts as $start => $types) {
+        foreach ($types as $type_name => $type) {
+          if ($featureloc->strand >= 0) {
+            // this is on the forward strand.  We need to convert the start on the src feature to the
+            // start on this feature's sequence
+            $parts[$start][$type_name]['start'] = $parts[$start][$type_name]['start'] - $featureloc->fmin;
+            $parts[$start][$type_name]['end']   = $parts[$start][$type_name]['end'] - $featureloc->fmin;
+            $parts[$start][$type_name]['type']  = $type_name;
+          }
+          else {
+            // this is on the reverse strand.  We need to swap the start and stop and calculate from the
+            // begining of the reverse sequence
+            $size = ($featureloc->fmax - $featureloc->fmin);
+            $start_orig = $parts[$start][$type_name]['start'];
+            $end_orig = $parts[$start][$type_name]['end'];
+            $new_start = $size - ($end_orig - $featureloc->fmin);
+            $new_end = $size - ($start_orig - $featureloc->fmin);
+
+            $rparts[$new_start][$type_name]['start'] = $new_start;
+            $rparts[$new_start][$type_name]['end']   = $new_end;
+            $rparts[$new_start][$type_name]['type']  = $type_name;
+          }
+        }
+      }
+
+      // now sort the parts
+      // if we're on the reverse strand we need to resort
+      if ($featureloc->strand >= 0) {
+        usort($parts, 'tripal_feature_sort_rel_parts_by_start');
+      }
+      else {
+        usort($rparts, 'tripal_feature_sort_rel_parts_by_start');
+        $parts = $rparts;
+      }
+
+      $floc_sequences[$src]['src'] = $src;
+      $floc_sequences[$src]['type'] = $featureloc->feature_id->type_id->name;
+      $args = array(':feature_id' => $featureloc->srcfeature_id->feature_id);
+      $start = $featureloc->fmin + 1;
+      $size = $featureloc->fmax - $featureloc->fmin;
+      
+      // TODO: fix the hard coded $start and $size
+      // the $start and $size variables are hard-coded in the SQL statement
+      // because the db_query function places quotes around all placeholders
+      // (e.g. :start & :size) and screws up the substring function
+      $sql = "
+        SELECT substring(residues from $start for $size) as residues
+        FROM {feature}
+        WHERE feature_id = :feature_id
+      ";
+      $sequence = chado_query($sql, $args)->fetchObject();
+      $residues = $sequence->residues;
+      if ($featureloc->strand < 0) {
+        $residues = tripal_feature_reverse_complement($residues);
+      }
+      $strand = '.';
+      if ($featureloc->strand == 1) {
+        $strand = '+';
+      }
+      elseif ($featureloc->strand == -1) {
+        $strand = '-';
+      }
+      $floc_sequences[$src]['location'] = tripal_get_location_string($featureloc);
+      $floc_sequences[$src]['defline'] = tripal_get_fasta_defline($featureloc->feature_id, $featureloc);
+      $floc_sequences[$src]['formatted_seq'] =  tripal_feature_color_sequence($residues, $parts, $floc_sequences[$src]['defline']);
+    }
+  }
+  return $floc_sequences;
+}
+/**
+ * Used to sort the list of relationship parts by start position
+ *
+ * @ingroup tripal_feature
+ */
+function tripal_feature_sort_rel_parts_by_start($a, $b) {
+  foreach ($a as $type_name => $details) {
+    $astart = $a[$type_name]['start'];
+    break;
+  }
+  foreach ($b as $type_name => $details) {
+    $bstart = $b[$type_name]['start'];
+    break;
+  }
+  return strnatcmp($astart, $bstart);
+}
+/**
+ * Load the locations for a given feature
+ *
+ * @param $feature_id
+ *   The feature to look up locations for
+ * @param $side
+ *   Whether the feature is the scrfeature, 'as_parent', or feature, 'as_child'
+ * @param $aggregate
+ *   Whether or not to get the locations for related features
+ *
+ * @ingroup tripal_feature
+ */
+function tripal_feature_load_featurelocs($feature_id, $side = 'as_parent', $aggregate = 1) {
+
+  $sql = "
+    SELECT
+       F.name, F.feature_id, F.uniquename,
+       FS.name as src_name, FS.feature_id as src_feature_id, FS.uniquename as src_uniquename,
+       CVT.name as cvname, CVT.cvterm_id,
+       CVTS.name as src_cvname, CVTS.cvterm_id as src_cvterm_id,
+       FL.fmin, FL.fmax, FL.is_fmin_partial, FL.is_fmax_partial,FL.strand, FL.phase
+     FROM {featureloc} FL
+       INNER JOIN {feature} F   ON FL.feature_id = F.feature_id
+       INNER JOIN {feature} FS  ON FS.feature_id = FL.srcfeature_id
+       INNER JOIN {cvterm} CVT  ON F.type_id     = CVT.cvterm_id
+       INNER JOIN {cvterm} CVTS ON FS.type_id    = CVTS.cvterm_id
+   ";
+  if (strcmp($side, 'as_parent')==0) {
+    $sql .= "WHERE FL.srcfeature_id = :feature_id ";
+  }
+  if (strcmp($side, 'as_child')==0) {
+    $sql .= "WHERE FL.feature_id = :feature_id ";
+  }
+
+  $flresults = chado_query($sql, array(':feature_id' => $feature_id));
+
+  // copy the results into an array
+  $i=0;
+  $featurelocs = array();
+  while ($loc = $flresults->fetchObject()) {
+    // if a drupal node exists for this feature then add the nid to the
+    // results object
+    $loc->fnid = chado_get_nid_from_id('feature', $loc->feature_id);
+    $loc->snid = chado_get_nid_from_id('feature', $loc->src_feature_id);
+    // add the result to the array
+    $featurelocs[$i++] = $loc;
+  }
+
+  // Add the relationship feature locs if aggregate is turned on
+  if ($aggregate and strcmp($side, 'as_parent')==0) {
+    // get the relationships for this feature without substituting any children
+    // for the parent. We want all relationships
+    $relationships = tripal_feature_get_aggregate_relationships($feature_id, 0);
+    foreach ($relationships as $rindex => $rel) {
+      // get the featurelocs for each of the relationship features
+      $rel_featurelocs = tripal_feature_load_featurelocs($rel->subject_id, 'as_child', 0);
+      foreach ($rel_featurelocs as $findex => $rfloc) {
+        $featurelocs[$i++] = $rfloc;
+      }
+    }
+  }
+
+  usort($featurelocs, 'tripal_feature_sort_locations');
+  return $featurelocs;
+}
+
+/**
+ * Used to sort the feature locs by start position
+ *
+ * @param $a
+ *   One featureloc record (as an object)
+ * @param $b
+ *   The other featureloc record (as an object)
+ *
+ * @return
+ *   Which feature location comes first
+ *
+ * @ingroup tripal_feature
+ */
+function tripal_feature_sort_locations($a, $b) {
+  return strnatcmp($a->fmin, $b->fmin);
+}
+
+
+/**
+ * Get features related to the current feature to a given depth. Recursive function.
+ *
+ * @param $feature_id
+ * @param $substitute
+ * @param $levels
+ * @param $base_type_id
+ * @param $depth
+ *
+ * @ingroup tripal_feature
+ */
+function tripal_feature_get_aggregate_relationships($feature_id, $substitute=1,
+    $levels=0, $base_type_id=NULL, $depth=0) {
+
+  // we only want to recurse to as many levels deep as indicated by the
+  // $levels variable, but only if this variable is > 0. If 0 then we
+  // recurse until we reach the end of the relationships tree.
+  if ($levels > 0 and $levels == $depth) {
+    return NULL;
+  }
+
+  // first get the relationships for this feature
+  return tripal_feature_load_relationships($feature_id, 'as_object');
+
+}
+/**
+ * Get the relationships for a feature.
+ *
+ * @param $feature_id
+ *   The feature to get relationships for
+ * @param $side
+ *   The side of the relationship this feature is (ie: 'as_subject' or 'as_object')
+ *
+ * @ingroup tripal_feature
+ */
+function tripal_feature_load_relationships($feature_id, $side = 'as_subject') {
+  // get the relationships for this feature.  The query below is used for both
+  // querying the object and subject relationships
+  $sql = "
+    SELECT
+      FS.name as subject_name, FS.uniquename as subject_uniquename,
+      CVTS.name as subject_type, CVTS.cvterm_id as subject_type_id,
+      FR.subject_id, FR.type_id as relationship_type_id, FR.object_id, FR.rank,
+      CVT.name as rel_type,
+      FO.name as object_name, FO.uniquename as object_uniquename,
+      CVTO.name as object_type, CVTO.cvterm_id as object_type_id
+    FROM {feature_relationship} FR
+     INNER JOIN {cvterm} CVT  ON FR.type_id    = CVT.cvterm_id
+     INNER JOIN {feature} FS  ON FS.feature_id = FR.subject_id
+     INNER JOIN {feature} FO  ON FO.feature_id = FR.object_id
+     INNER JOIN {cvterm} CVTO ON FO.type_id    = CVTO.cvterm_id
+     INNER JOIN {cvterm} CVTS ON FS.type_id    = CVTS.cvterm_id
+  ";
+  if (strcmp($side, 'as_object')==0) {
+    $sql .= " WHERE FR.object_id = :feature_id";
+  }
+  if (strcmp($side, 'as_subject')==0) {
+    $sql .= " WHERE FR.subject_id = :feature_id";
+  }
+  $sql .= " ORDER BY FR.rank";
+
+  // get the relationships
+  $results = chado_query($sql, array(':feature_id' => $feature_id));
+
+
+  // iterate through the relationships, put these in an array and add
+  // in the Drupal node id if one exists
+  $i=0;
+  $nodesql = "SELECT nid FROM {chado_feature} WHERE feature_id = :feature_id";
+  $relationships = array();
+  while ($rel = $results->fetchObject()) {
+    $node = db_query($nodesql, array(':feature_id' => $rel->subject_id))->fetchObject();
+    if ($node) {
+      $rel->subject_nid = $node->nid;
+    }
+    $node = db_query($nodesql, array(':feature_id' => $rel->object_id))->fetchObject();
+    if ($node) {
+      $rel->object_nid = $node->nid;
+    }
+    $relationships[$i++] = $rel;
+  }
+  return $relationships;
+}
+
+/**
+ * Returns the marked up fasta sequence for the described feature
+ *
+ * @param $sequence
+ * @param $parts
+ * @param $defline
+ *
+ * @ingroup tripal_feature
+ */
+function tripal_feature_color_sequence($sequence, $parts, $defline) {
+
+
+  $types = array();
+  // first get the list of types so we can create a color legend
+  foreach ($parts as $index => $t) {
+    foreach ($t as $type_name => $details) {
+      $types[$type_name] = 1;
+    }
+  }
+
+  $newseq = "<div id=\"tripal_feature-featureloc_sequence-legend\">Legend: ";
+  foreach ($types as $type_name => $present) {
+    $newseq .= "<span id=\"tripal_feature-legend-$type_name\" class=\"tripal_feature-legend-item tripal_feature-featureloc_sequence-$type_name\" script=\"\">$type_name</span>";
+  }
+  $newseq .= "</div>Hold the cursor over a type above to highlight its positions in the sequence below.";
+
+
+  // set the background color of the rows based on the type
+  $pos = 0;
+  $newseq .= "<pre class=\"tripal_feature-sequence\">";
+  $newseq .= ">$defline\n";
+
+  // iterate through the parts. They should be in order.
+  $starts   = array(); // an array holding all of the children starting locations
+  $ends     = array(); // an array holding all of the children's ending locations
+  $seqcount = 0;
+  foreach ($parts as $index => $types) {
+
+    // get the start for this part.  All types in this part start at the
+    // same position so we only need the first record
+    foreach ($types as $type => $child) {
+      $start = $child['start'];
+      $starts[$start][] = $type;
+    }
+
+    // next, sort the parts by their end. We want the span tag to
+    // to be added in the order the parts end.
+    usort($types, 'tripal_feature_sort_rel_parts_by_end');
+
+    // iterate through the types in order that then end and create a
+    // span for it.
+    foreach ($types as $type) {
+      $end = $type['end'];
+      $ends[$end][] = $type;
+    }
+  }
+
+  // iterate through each nucleotide in the sequence, add a new line very
+  // 50 characters and add the spans as we encounter them
+  for ($i = 0; $i < strlen($sequence); $i++) {
+
+    // if we are at and end of a span then close it
+    if (array_key_exists($i, $ends)) {
+      foreach ($ends[$i] as $index => $type) {
+        $newseq .= "</span>";
+      }
+    }
+
+    // if we are at and end of a span then close it
+    if (array_key_exists($i, $starts)) {
+      foreach ($starts[$i] as $index => $type) {
+        $class = "tripal_feature-featureloc_sequence-" . $type;
+        $newseq .= "<span class=\"$class\">";
+      }
+    }
+
+    $newseq .= $sequence{$i};
+    $seqcount++;
+    if ($seqcount % 50 == 0) {
+      $newseq .= "\n";
+    }
+  }
+
+  $newseq .= "</pre>";
+  return $newseq;
+}
+
+/**
+ * Used to sort the list of relationship parts by start position
+ *
+ * @ingroup tripal_feature
+ */
+function tripal_feature_sort_rel_parts_by_end($a, $b) {
+  $val = strnatcmp($b['end'], $a['end']);
+  if ($val == 0) {
+    return strcmp($a['type'], $b['type']);
+  }
+  return $val;
+}
 /**
  *
  *
@@ -171,6 +593,77 @@ function tripal_feature_preprocess_tripal_feature_alignments(&$variables) {
   }
   $feature->all_featurelocs = $alignments;
 }
+/**
+ * This function is for features that align through an intermediate such
+ * as 'EST_match' or 'match'.  This occurs in the case where two sequences
+ * align but where one does not align perfectly.  Some ESTs may be in a contig
+ * but not all of the EST.  Portions may overhang and not be included in the
+ * consensus if quality is bad.
+ * For example:
+ *    Feature 1: Contig --------------------
+ *    Feature 2: EST_match           -------
+ *    Feature 3: EST                 ---------
+ *
+ * The feature provided to the function will always be the feature 1.  The
+ * featureloc columns prefixed with 'right' (e.g. right_fmin) belong to the
+ * alignment of feature 3 with feature 2
+ *
+ * Features may align to more than one feature and are not matches. We do
+   * not want to include these, so we have to filter on the SO terms:
+ * match, or %_match
+ *
+ * @ingroup tripal_feature
+ */
+function tripal_feature_get_matched_alignments($feature) {
+
+  $sql = "
+     SELECT
+       FL1.featureloc_id    as left_featureloc_id,
+       FL1.srcfeature_id    as left_srcfeature_id,
+       FL1.feature_id       as left_feature_id,
+       FL1.fmin             as left_fmin,
+       FL1.is_fmin_partial  as left_is_fmin_partial,
+       FL1.fmax             as left_fmax,
+       FL1.is_fmax_partial  as left_is_fmax_partial,
+       FL1.strand           as left_strand,
+       FL1.phase            as left_phase,
+       FL1.locgroup         as left_locgroup,
+       FL1.rank             as left_rank,
+       FL2.featureloc_id    as right_featureloc_id,
+       FL2.srcfeature_id    as right_srcfeature_id,
+       FL2.feature_id       as right_feature_id,
+       FL2.fmin             as right_fmin,
+       FL2.is_fmin_partial  as right_is_fmin_partial,
+       FL2.fmax             as right_fmax,
+       FL2.is_fmax_partial  as right_is_fmax_partial,
+       FL2.strand           as right_strand,
+       FL2.phase            as right_phase,
+       FL2.locgroup         as right_locgroup,
+       FL2.rank             as right_rank
+     FROM {feature} F1
+       INNER JOIN {featureloc} FL1 on FL1.srcfeature_id = F1.feature_id
+       INNER JOIN {feature} F2 on FL1.feature_id = F2.feature_id
+       INNER JOIN {featureloc} FL2 on FL2.feature_id = F2.feature_id
+       INNER JOIN {cvterm} CVT2 on F2.type_id = CVT2.cvterm_id
+     WHERE
+       F1.feature_id = :feature_id  AND
+       (CVT2.name = 'match' or CVT2.name like '%_match')
+     ORDER BY FL1.fmin
+   ";
+
+  $results = chado_query($sql, array(':feature_id' => $feature->feature_id));
+
+  // iterate through the results and add them to our featurelocs array
+  $featurelocs = array();
+  while ($fl = $results->fetchObject()) {
+    // ignore featurelocs where the left and right srcfeature is the same
+    if (strcmp($fl->left_srcfeature_id, $fl->right_srcfeature_id) == 0) {
+      continue;
+    }
+    $featurelocs[] = $fl ;
+  }
+  return $featurelocs;
+}
 /**
  *
  *
@@ -180,6 +673,88 @@ function tripal_feature_preprocess_tripal_organism_feature_counts(&$variables, $
   $organism = $variables['node']->organism;
   $organism->feature_counts = tripal_feature_load_organism_feature_counts($organism);
 }
+/**
+ * Load the arguments for the organism feature counts browser
+ *
+ * @param $organism
+ *  The organism of interest
+ *
+ * @ingroup tripal_feature
+ */
+function tripal_feature_load_organism_feature_counts($organism) {
+
+  $args = array();
+  $order = array();
+  $names = array();
+
+  // build the where clause for the SQL statement if we have a custom term list
+  // we'll also keep track of the names the admin provided (if any) and the
+  // order that the terms should appear.
+  $is_custom = 0;
+  $temp = rtrim(variable_get('tripal_feature_summary_report_mapping', ''));
+  $where = '';
+  if ($temp) {
+    $is_custom = 1;
+    $temp = explode("\n", $temp);
+    $i = 0;
+    foreach ($temp as $value) {
+      // separate the key value pairs
+      $temp2 = explode("=", $value);
+      $feature_type = rtrim($temp2[0]);
+      $order[] = $feature_type;  // save the order of the these terms
+      $where .= " OFC.feature_type = :name$i OR ";
+      $args[":name$i"] = rtrim($temp2[0]);
+
+      // if the admin specified a new name then store that otherwise use the
+      // the default sequence ontology term name
+      if(count($temp2) == 2) {
+        $names[] = rtrim($temp2[1]);
+      }
+      else {
+        $names[] = $feature_type;
+      }
+      $i++;
+    }
+    if ($where) {
+      $where = drupal_substr($where, 0, -4);  # remove OR from the end
+      $where = "($where) AND";
+    }
+  }
+
+  // get the feature counts.  This is dependent on a materialized view
+  // installed with the organism module
+  $sql = "
+  SELECT OFC.num_features,OFC.feature_type,CVT.definition
+  FROM {organism_feature_count} OFC
+  INNER JOIN {cvterm} CVT on OFC.cvterm_id = CVT.cvterm_id
+  WHERE $where organism_id = :organism_id
+  ORDER BY num_features desc
+  ";
+  $args[':organism_id'] = $organism->organism_id;
+  $org_features = chado_query($sql, $args);
+
+  // iterate through the types
+  $types = array();
+  while ($type = $org_features->fetchObject()) {
+  $types[$type->feature_type] = $type;
+  // if we don't have an order this means we didn't go through the loop
+  // above to set the names, so do that now
+  if (!$is_custom) {
+  $names[] = $type->feature_type;
+  $order[] = $type->feature_type;
+  }
+  }
+
+  // now reorder the types
+  $ordered_types = array();
+  foreach ($order as $type) {
+  $ordered_types[] = $types[$type];
+  }
+  return array(
+  'types' => $ordered_types,
+      'names' => $names
+  );
+}
 
 /**
  * Using the chado_expand_var function to retrieve a set

+ 0 - 576
tripal_feature/tripal_feature.module

@@ -336,583 +336,7 @@ function tripal_feature_theme($existing, $type, $theme, $path) {
   return $items;
 }
 
-/**
- * Load the locations for a given feature
- *
- * @param $feature_id
- *   The feature to look up locations for
- * @param $side
- *   Whether the feature is the scrfeature, 'as_parent', or feature, 'as_child'
- * @param $aggregate
- *   Whether or not to get the locations for related features
- *
- * @ingroup tripal_feature
- */
-function tripal_feature_load_featurelocs($feature_id, $side = 'as_parent', $aggregate = 1) {
-
-  $sql = "
-    SELECT
-       F.name, F.feature_id, F.uniquename,
-       FS.name as src_name, FS.feature_id as src_feature_id, FS.uniquename as src_uniquename,
-       CVT.name as cvname, CVT.cvterm_id,
-       CVTS.name as src_cvname, CVTS.cvterm_id as src_cvterm_id,
-       FL.fmin, FL.fmax, FL.is_fmin_partial, FL.is_fmax_partial,FL.strand, FL.phase
-     FROM {featureloc} FL
-       INNER JOIN {feature} F   ON FL.feature_id = F.feature_id
-       INNER JOIN {feature} FS  ON FS.feature_id = FL.srcfeature_id
-       INNER JOIN {cvterm} CVT  ON F.type_id     = CVT.cvterm_id
-       INNER JOIN {cvterm} CVTS ON FS.type_id    = CVTS.cvterm_id
-   ";
-  if (strcmp($side, 'as_parent')==0) {
-    $sql .= "WHERE FL.srcfeature_id = :feature_id ";
-  }
-  if (strcmp($side, 'as_child')==0) {
-    $sql .= "WHERE FL.feature_id = :feature_id ";
-  }
-
-  $flresults = chado_query($sql, array(':feature_id' => $feature_id));
-
-  // copy the results into an array
-  $i=0;
-  $featurelocs = array();
-  while ($loc = $flresults->fetchObject()) {
-    // if a drupal node exists for this feature then add the nid to the
-    // results object
-    $loc->fnid = chado_get_nid_from_id('feature', $loc->feature_id);
-    $loc->snid = chado_get_nid_from_id('feature', $loc->src_feature_id);
-    // add the result to the array
-    $featurelocs[$i++] = $loc;
-  }
-
-  // Add the relationship feature locs if aggregate is turned on
-  if ($aggregate and strcmp($side, 'as_parent')==0) {
-    // get the relationships for this feature without substituting any children
-    // for the parent. We want all relationships
-    $relationships = tripal_feature_get_aggregate_relationships($feature_id, 0);
-    foreach ($relationships as $rindex => $rel) {
-      // get the featurelocs for each of the relationship features
-      $rel_featurelocs = tripal_feature_load_featurelocs($rel->subject_id, 'as_child', 0);
-      foreach ($rel_featurelocs as $findex => $rfloc) {
-        $featurelocs[$i++] = $rfloc;
-      }
-    }
-  }
-
-  usort($featurelocs, 'tripal_feature_sort_locations');
-  return $featurelocs;
-}
-
-/**
- * Used to sort the feature locs by start position
- *
- * @param $a
- *   One featureloc record (as an object)
- * @param $b
- *   The other featureloc record (as an object)
- *
- * @return
- *   Which feature location comes first
- *
- * @ingroup tripal_feature
- */
-function tripal_feature_sort_locations($a, $b) {
-  return strnatcmp($a->fmin, $b->fmin);
-}
-
-/**
- * Get the relationships for a feature.
- *
- * @param $feature_id
- *   The feature to get relationships for
- * @param $side
- *   The side of the relationship this feature is (ie: 'as_subject' or 'as_object')
- *
- * @ingroup tripal_feature
- */
-function tripal_feature_load_relationships($feature_id, $side = 'as_subject') {
-  // get the relationships for this feature.  The query below is used for both
-  // querying the object and subject relationships
-  $sql = "
-    SELECT
-      FS.name as subject_name, FS.uniquename as subject_uniquename,
-      CVTS.name as subject_type, CVTS.cvterm_id as subject_type_id,
-      FR.subject_id, FR.type_id as relationship_type_id, FR.object_id, FR.rank,
-      CVT.name as rel_type,
-      FO.name as object_name, FO.uniquename as object_uniquename,
-      CVTO.name as object_type, CVTO.cvterm_id as object_type_id
-    FROM {feature_relationship} FR
-     INNER JOIN {cvterm} CVT  ON FR.type_id    = CVT.cvterm_id
-     INNER JOIN {feature} FS  ON FS.feature_id = FR.subject_id
-     INNER JOIN {feature} FO  ON FO.feature_id = FR.object_id
-     INNER JOIN {cvterm} CVTO ON FO.type_id    = CVTO.cvterm_id
-     INNER JOIN {cvterm} CVTS ON FS.type_id    = CVTS.cvterm_id
-  ";
-  if (strcmp($side, 'as_object')==0) {
-    $sql .= " WHERE FR.object_id = :feature_id";
-  }
-  if (strcmp($side, 'as_subject')==0) {
-    $sql .= " WHERE FR.subject_id = :feature_id";
-  }
-  $sql .= " ORDER BY FR.rank";
-
-  // get the relationships
-  $results = chado_query($sql, array(':feature_id' => $feature_id));
-
-
-  // iterate through the relationships, put these in an array and add
-  // in the Drupal node id if one exists
-  $i=0;
-  $nodesql = "SELECT nid FROM {chado_feature} WHERE feature_id = :feature_id";
-  $relationships = array();
-  while ($rel = $results->fetchObject()) {
-    $node = db_query($nodesql, array(':feature_id' => $rel->subject_id))->fetchObject();
-    if ($node) {
-      $rel->subject_nid = $node->nid;
-    }
-    $node = db_query($nodesql, array(':feature_id' => $rel->object_id))->fetchObject();
-    if ($node) {
-      $rel->object_nid = $node->nid;
-    }
-    $relationships[$i++] = $rel;
-  }
-  return $relationships;
-}
-
-/**
- * Get features related to the current feature to a given depth. Recursive function.
- *
- * @param $feature_id
- * @param $substitute
- * @param $levels
- * @param $base_type_id
- * @param $depth
- *
- * @ingroup tripal_feature
- */
-function tripal_feature_get_aggregate_relationships($feature_id, $substitute=1,
-  $levels=0, $base_type_id=NULL, $depth=0) {
-
-  // we only want to recurse to as many levels deep as indicated by the
-  // $levels variable, but only if this variable is > 0. If 0 then we
-  // recurse until we reach the end of the relationships tree.
-  if ($levels > 0 and $levels == $depth) {
-    return NULL;
-  }
-
-  // first get the relationships for this feature
-  return tripal_feature_load_relationships($feature_id, 'as_object');
-
-}
-
-/**
- * Get the sequence this feature is located on
- *
- * @param $feature_id
- * @param $featurelocs
- *
- * @ingroup tripal_feature
- */
-function tripal_feature_load_featureloc_sequences($feature_id, $featurelocs) {
-
-  // if we don't have any featurelocs then no point in continuing
-  if (!$featurelocs) {
-    return array();
-  }
-
-  // get the list of relationships (including any aggregators) and iterate
-  // through each one to find information needed to color-code the reference sequence
-  $relationships = tripal_feature_get_aggregate_relationships($feature_id);
-  if (!$relationships) {
-    return array();
-  }
-
-
-  // iterate through each of the realtionships features and get their
-  // locations
-  foreach ($relationships as $rindex => $rel) {
-    // get the featurelocs for each of the relationship features
-    $rel_featurelocs = tripal_feature_load_featurelocs($rel->subject_id, 'as_child', 0);
-    foreach ($rel_featurelocs as $rfindex => $rel_featureloc) {
-      // keep track of this unique source feature
-      $src = $rel_featureloc->src_feature_id . "-" . $rel_featureloc->src_cvterm_id;
-
-      // copy over the results to the relationship object.  Since there can
-      // be more than one feature location for each relationship feature we
-      // use the '$src' variable to keep track of these.
-      $rel->featurelocs = new stdClass();
-      $rel->featurelocs->$src = new stdClass();
-      $rel->featurelocs->$src->src_uniquename = $rel_featureloc->src_uniquename;
-      $rel->featurelocs->$src->src_cvterm_id  = $rel_featureloc->src_cvterm_id;
-      $rel->featurelocs->$src->src_cvname     = $rel_featureloc->src_cvname;
-      $rel->featurelocs->$src->fmin           = $rel_featureloc->fmin;
-      $rel->featurelocs->$src->fmax           = $rel_featureloc->fmax;
-      $rel->featurelocs->$src->src_name       = $rel_featureloc->src_name;
-
-      // keep track of the individual parts for each relationship
-      $start = $rel->featurelocs->$src->fmin;
-      $end   = $rel->featurelocs->$src->fmax;
-      $type  = $rel->subject_type;
-      $rel_locs[$src]['parts'][$start][$type]['start'] = $start;
-      $rel_locs[$src]['parts'][$start][$type]['end']   = $end;
-      $rel_locs[$src]['parts'][$start][$type]['type']  = $type;
-    }
-  }
-
-  // the featurelocs array provided to the function contains the locations
-  // where this feature is found.   We want to get the sequence for each
-  // location and then annotate it with the parts found from the relationships
-  // locations determiend above.
-  $floc_sequences = array();
-  foreach ($featurelocs as $featureloc) {
-
-    // build the src name so we can keep track of the different parts for each feature
-    $src = $featureloc->srcfeature_id->feature_id . "-" . $featureloc->srcfeature_id->type_id->cvterm_id;
-
-    // orient the parts to the beginning of the feature sequence
-    if (!empty($rel_locs[$src]['parts'])) {
-      $parts = $rel_locs[$src]['parts'];
-      $rparts = array();  // we will fill this up if we're on the reverse strand
-
-      foreach ($parts as $start => $types) {
-        foreach ($types as $type_name => $type) {
-          if ($featureloc->strand >= 0) {
-             // this is on the forward strand.  We need to convert the start on the src feature to the
-             // start on this feature's sequence
-             $parts[$start][$type_name]['start'] = $parts[$start][$type_name]['start'] - $featureloc->fmin;
-             $parts[$start][$type_name]['end']   = $parts[$start][$type_name]['end'] - $featureloc->fmin;
-             $parts[$start][$type_name]['type']  = $type_name;
-          }
-          else {
-             // this is on the reverse strand.  We need to swap the start and stop and calculate from the
-             // begining of the reverse sequence
-             $size = ($featureloc->fmax - $featureloc->fmin);
-             $start_orig = $parts[$start][$type_name]['start'];
-             $end_orig = $parts[$start][$type_name]['end'];
-             $new_start = $size - ($end_orig - $featureloc->fmin);
-             $new_end = $size - ($start_orig - $featureloc->fmin);
-
-             $rparts[$new_start][$type_name]['start'] = $new_start;
-             $rparts[$new_start][$type_name]['end']   = $new_end;
-             $rparts[$new_start][$type_name]['type']  = $type_name;
-          }
-        }
-      }
-
-      // now sort the parts
-      // if we're on the reverse strand we need to resort
-      if ($featureloc->strand >= 0) {
-        usort($parts, 'tripal_feature_sort_rel_parts_by_start');
-      }
-      else {
-        usort($rparts, 'tripal_feature_sort_rel_parts_by_start');
-        $parts = $rparts;
-      }
-
-      $floc_sequences[$src]['src'] = $src;
-      $floc_sequences[$src]['type'] = $featureloc->feature_id->type_id->name;
-      $args = array(':feature_id' => $featureloc->srcfeature_id->feature_id);
-      $start = $featureloc->fmin + 1;
-      $size = $featureloc->fmax - $featureloc->fmin;
-      // TODO: fix the hard coded $start and $size
-      // the $start and $size variables are hard-coded in the SQL statement
-      // because the db_query function places quotes around all placeholders
-      // (e.g. :start & :size) and screws up the substring function
-      $sql = "
-        SELECT substring(residues from $start for $size) as residues
-        FROM {feature}
-        WHERE feature_id = :feature_id
-      ";
-      $sequence = chado_query($sql, $args)->fetchObject();
-      $residues = $sequence->residues;
-      if ($featureloc->strand < 0) {
-         $residues = tripal_feature_reverse_complement($residues);
-      }
-      $strand = '.';
-      if ($featureloc->strand == 1) {
-        $strand = '+';
-      }
-      elseif ($featureloc->strand == -1) {
-        $strand = '-';
-      }
-      $floc_sequences[$src]['location'] = tripal_get_location_string($featureloc);
-      $floc_sequences[$src]['defline'] = tripal_get_fasta_defline($featureloc->feature_id, $featureloc);
-      $floc_sequences[$src]['formatted_seq'] =  tripal_feature_color_sequence($residues, $parts, $floc_sequences[$src]['defline']);
-    }
-  }
-  return $floc_sequences;
-}
-
-/**
- * This function is for features that align through an intermediate such
- * as 'EST_match' or 'match'.  This occurs in the case where two sequences
- * align but where one does not align perfectly.  Some ESTs may be in a contig
- * but not all of the EST.  Portions may overhang and not be included in the
- * consensus if quality is bad.
- * For example:
- *    Feature 1: Contig --------------------
- *    Feature 2: EST_match           -------
- *    Feature 3: EST                 ---------
- *
- * The feature provided to the function will always be the feature 1.  The
- * featureloc columns prefixed with 'right' (e.g. right_fmin) belong to the
- * alignment of feature 3 with feature 2
- *
- * Features may align to more than one feature and are not matches. We do
- * not want to include these, so we have to filter on the SO terms:
- * match, or %_match
- *
- * @ingroup tripal_feature
- */
-function tripal_feature_get_matched_alignments($feature) {
-
-   $sql = "
-     SELECT
-       FL1.featureloc_id    as left_featureloc_id,
-       FL1.srcfeature_id    as left_srcfeature_id,
-       FL1.feature_id       as left_feature_id,
-       FL1.fmin             as left_fmin,
-       FL1.is_fmin_partial  as left_is_fmin_partial,
-       FL1.fmax             as left_fmax,
-       FL1.is_fmax_partial  as left_is_fmax_partial,
-       FL1.strand           as left_strand,
-       FL1.phase            as left_phase,
-       FL1.locgroup         as left_locgroup,
-       FL1.rank             as left_rank,
-       FL2.featureloc_id    as right_featureloc_id,
-       FL2.srcfeature_id    as right_srcfeature_id,
-       FL2.feature_id       as right_feature_id,
-       FL2.fmin             as right_fmin,
-       FL2.is_fmin_partial  as right_is_fmin_partial,
-       FL2.fmax             as right_fmax,
-       FL2.is_fmax_partial  as right_is_fmax_partial,
-       FL2.strand           as right_strand,
-       FL2.phase            as right_phase,
-       FL2.locgroup         as right_locgroup,
-       FL2.rank             as right_rank
-     FROM {feature} F1
-       INNER JOIN {featureloc} FL1 on FL1.srcfeature_id = F1.feature_id
-       INNER JOIN {feature} F2 on FL1.feature_id = F2.feature_id
-       INNER JOIN {featureloc} FL2 on FL2.feature_id = F2.feature_id
-       INNER JOIN {cvterm} CVT2 on F2.type_id = CVT2.cvterm_id
-     WHERE
-       F1.feature_id = :feature_id  AND
-       (CVT2.name = 'match' or CVT2.name like '%_match')
-     ORDER BY FL1.fmin
-   ";
-
-   $results = chado_query($sql, array(':feature_id' => $feature->feature_id));
-
-   // iterate through the results and add them to our featurelocs array
-   $featurelocs = array();
-   while ($fl = $results->fetchObject()) {
-     // ignore featurelocs where the left and right srcfeature is the same
-     if (strcmp($fl->left_srcfeature_id, $fl->right_srcfeature_id) == 0) {
-       continue;
-     }
-     $featurelocs[] = $fl ;
-   }
-   return $featurelocs;
-}
-
-/**
- * Load the arguments for the organism feature counts browser
- *
- * @param $organism
- *  The organism of interest
- *
- * @ingroup tripal_feature
- */
-function tripal_feature_load_organism_feature_counts($organism) {
-
-  $args = array();
-  $order = array();
-  $names = array();
-
-  // build the where clause for the SQL statement if we have a custom term list
-  // we'll also keep track of the names the admin provided (if any) and the
-  // order that the terms should appear.
-  $is_custom = 0;
-  $temp = rtrim(variable_get('tripal_feature_summary_report_mapping', ''));
-  $where = '';
-  if ($temp) {
-    $is_custom = 1;
-    $temp = explode("\n", $temp);
-    $i = 0;
-    foreach ($temp as $value) {
-      // separate the key value pairs
-      $temp2 = explode("=", $value);
-      $feature_type = rtrim($temp2[0]);
-      $order[] = $feature_type;  // save the order of the these terms
-      $where .= " OFC.feature_type = :name$i OR ";
-      $args[":name$i"] = rtrim($temp2[0]);
-
-      // if the admin specified a new name then store that otherwise use the
-      // the default sequence ontology term name
-      if(count($temp2) == 2) {
-        $names[] = rtrim($temp2[1]);
-      }
-      else {
-        $names[] = $feature_type;
-      }
-      $i++;
-    }
-    if ($where) {
-      $where = drupal_substr($where, 0, -4);  # remove OR from the end
-      $where = "($where) AND";
-    }
-  }
-
-  // get the feature counts.  This is dependent on a materialized view
-  // installed with the organism module
-  $sql = "
-    SELECT OFC.num_features,OFC.feature_type,CVT.definition
-    FROM {organism_feature_count} OFC
-      INNER JOIN {cvterm} CVT on OFC.cvterm_id = CVT.cvterm_id
-    WHERE $where organism_id = :organism_id
-    ORDER BY num_features desc
-  ";
-  $args[':organism_id'] = $organism->organism_id;
-  $org_features = chado_query($sql, $args);
-
-  // iterate through the types
-  $types = array();
-  while ($type = $org_features->fetchObject()) {
-    $types[$type->feature_type] = $type;
-    // if we don't have an order this means we didn't go through the loop
-    // above to set the names, so do that now
-    if (!$is_custom) {
-      $names[] = $type->feature_type;
-      $order[] = $type->feature_type;
-    }
-  }
-
-  // now reorder the types
-  $ordered_types = array();
-  foreach ($order as $type) {
-    $ordered_types[] = $types[$type];
-  }
-  return array(
-    'types' => $ordered_types,
-    'names' => $names
-  );
-}
-
-/**
- * Used to sort the list of relationship parts by start position
- *
- * @ingroup tripal_feature
- */
-function tripal_feature_sort_rel_parts_by_start($a, $b) {
-  foreach ($a as $type_name => $details) {
-     $astart = $a[$type_name]['start'];
-     break;
-  }
-  foreach ($b as $type_name => $details) {
-     $bstart = $b[$type_name]['start'];
-     break;
-  }
-  return strnatcmp($astart, $bstart);
-}
-
-/**
- * Used to sort the list of relationship parts by start position
- *
- * @ingroup tripal_feature
- */
-function tripal_feature_sort_rel_parts_by_end($a, $b) {
-  $val = strnatcmp($b['end'], $a['end']);
-  if ($val == 0) {
-     return strcmp($a['type'], $b['type']);
-  }
-  return $val;
-}
-
-/**
- * Returns the marked up fasta sequence for the described feature
- *
- * @param $sequence
- * @param $parts
- * @param $defline
- *
- * @ingroup tripal_feature
- */
-function tripal_feature_color_sequence($sequence, $parts, $defline) {
-
-
-  $types = array();
-  // first get the list of types so we can create a color legend
-  foreach ($parts as $index => $t) {
-    foreach ($t as $type_name => $details) {
-       $types[$type_name] = 1;
-    }
-  }
-
-  $newseq = "<div id=\"tripal_feature-featureloc_sequence-legend\">Legend: ";
-  foreach ($types as $type_name => $present) {
-    $newseq .= "<span id=\"tripal_feature-legend-$type_name\" class=\"tripal_feature-legend-item tripal_feature-featureloc_sequence-$type_name\" script=\"\">$type_name</span>";
-  }
-  $newseq .= "</div>Hold the cursor over a type above to highlight its positions in the sequence below.";
-
-
-  // set the background color of the rows based on the type
-  $pos = 0;
-  $newseq .= "<pre class=\"tripal_feature-sequence\">";
-  $newseq .= ">$defline\n";
 
-  // iterate through the parts. They should be in order.
-  $starts   = array(); // an array holding all of the children starting locations
-  $ends     = array(); // an array holding all of the children's ending locations
-  $seqcount = 0;
-  foreach ($parts as $index => $types) {
-
-    // get the start for this part.  All types in this part start at the
-    // same position so we only need the first record
-    foreach ($types as $type => $child) {
-      $start = $child['start'];
-      $starts[$start][] = $type;
-    }
-
-    // next, sort the parts by their end. We want the span tag to
-    // to be added in the order the parts end.
-    usort($types, 'tripal_feature_sort_rel_parts_by_end');
-
-    // iterate through the types in order that then end and create a 
-    // span for it.
-    foreach ($types as $type) {
-      $end = $type['end'];
-      $ends[$end][] = $type;
-    }
-  }
-
-  // iterate through each nucleotide in the sequence, add a new line very
-  // 50 characters and add the spans as we encounter them
-  for ($i = 0; $i < strlen($sequence); $i++) {
-
-    // if we are at and end of a span then close it
-    if (array_key_exists($i, $ends)) {
-      foreach ($ends[$i] as $index => $type) {
-        $newseq .= "</span>";
-      }
-    }
-    
-    // if we are at and end of a span then close it
-    if (array_key_exists($i, $starts)) {
-      foreach ($starts[$i] as $index => $type) {
-        $class = "tripal_feature-featureloc_sequence-" . $type;
-        $newseq .= "<span class=\"$class\">";
-      }
-    }
-
-    $newseq .= $sequence{$i};
-    $seqcount++;
-    if ($seqcount % 50 == 0) {
-      $newseq .= "\n";
-    }
-  }
-
-  $newseq .= "</pre>";
-  return $newseq;
-}
 
 /**
  * The CV module will create the JSON array necessary for buillding a