Browse Source

Working on fixing caching issue with fields

Stephen Ficklin 7 years ago
parent
commit
8cbdee9a06

+ 2 - 87
legacy/tripal_feature/theme/tripal_feature.theme.inc

@@ -53,7 +53,7 @@ function tripal_feature_load_featureloc_sequences($feature_id, $featurelocs) {
 
   // 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);
+  $relationships = _tripal_feature_get_aggregate_relationships($feature_id);
   if (!$relationships) {
     return array();
   }
@@ -243,7 +243,7 @@ function tripal_feature_load_featurelocs($feature_id, $side = 'as_parent', $aggr
   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);
+    $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);
@@ -274,91 +274,6 @@ 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
  *

+ 67 - 43
tripal/includes/TripalEntityController.inc

@@ -349,7 +349,7 @@ class TripalEntityController extends EntityAPIController {
    * @param $conditions
    *  The list of key/value filters for querying the entity.
    * @param $field_ids
-   *  The list of numeric field IDs for fields that should be included.
+   *  The list of numeric field IDs for fields that should be attached.
    */
   public function load($ids = array(), $conditions = array(), $field_ids = array()) {
 
@@ -474,25 +474,13 @@ class TripalEntityController extends EntityAPIController {
    * @param $queried_entities
    *   The list of queried
    * @param $revision_id
+   *   ID of the revision that was loaded, or FALSE if the most current
+   *   revision was loaded.
    * @param $field_ids
    */
   protected function attachLoad(&$queried_entities, $revision_id = FALSE,
       $field_ids = array()) {
 
-    // Get the list of fields for later user.
-    $fields = field_info_fields();
-    // A temporary holding place for field instances (so we don't have
-    // to keep looking them up in our loop below).
-    $instances = array();
-
-    // Add in the content_type field by default. It should always be attached.
-    $ids = array();
-    $ct = field_info_field('content_type');
-    $ids[] = $ct['id'];
-    $field_ids += $ids;
-    $unattached = array();
-
-
     // Attach fields.
     if ($this->entityInfo['fieldable']) {
       if ($revision_id) {
@@ -501,40 +489,76 @@ class TripalEntityController extends EntityAPIController {
       else {
         $function = 'field_attach_load';
       }
-      foreach ($queried_entities as $entity) {
-        // Iterate through the fields and find those that are set to
-        // 'auto_attach' and which are attached to this bundle.
-        foreach ($fields as $field) {
-          $field_name =  $field['field_name'];
-          if (array_key_exists('TripalEntity', $field['bundles'])) {
-            foreach ($field['bundles']['TripalEntity'] as $bundle_name) {
-              if ($bundle_name == $entity->bundle) {
-                // Get the instance of this field for this bundle.
-                if (!array_key_exists($field_name . '-' . $bundle_name, $instances)) {
-                  $instance = field_info_instance('TripalEntity', $field['field_name'], $bundle_name);
-                  $instances[$field_name . '-' . $bundle_name] = $instance;
+      foreach ($queried_entities as $id => $entity) {
+        $info = entity_get_info($entity->type);
+        $field_cache = array_key_exists('field cache', $info) ? $info['field cache'] : FALSE;
+        $bundle = $entity->bundle;
+
+        // Iterate through the field instances and find those that are set to
+        // 'auto_attach' and which are attached to this bundle. Add all
+        // fields that don't need auto attach to the field_ids array.
+        $instances = field_info_instances('TripalEntity', $bundle);
+        foreach ($instances as $instance) {
+          $field_name =  $instance['field_name'];
+          $field = field_info_field($field_name);
+          $field_id = $field['id'];
+
+          // Options used for the field_attach_load function.
+          $options = array();
+          $options['field_id'] = $field['id'];
+
+          // The cache ID for the entity.  We must manually set the cache
+          // because the field_attach_load won't do it for us.
+          $cfid = "field:TripalEntity:$id:$field_name";
+
+          // If a list of field_ids is provided then we specifically want
+          // to only load the  fields specified.
+          if (count($field_ids) > 0) {
+            if (in_array($field_id, $field_ids)) {
+              // Check if the field is cached. if so, then don't reload.
+              if ($field_cache) {
+                $cache_data = cache_get($cfid, 'cache_field');
+                if (!empty($cache_data)) {
+                  $queried_entities[$id]->$field_name = $cache_data->data;
+                  continue;
                 }
-                else {
-                  $instance = $instances[$field_name . '-' . $bundle_name];
-                }
-                // If the 'auto_attach' is set to FALSE then we don't want
-                // to add this field to our list of IDs to auto attach.
-                if (array_key_exists('settings', $instance) and
-                    array_key_exists('auto_attach', $instance['settings']) and
-                    $instance['settings']['auto_attach'] == FALSE) {
-                  // Skip this field.
-                }
-                else {
-                  $field_ids[] = $field['id'];
+              }
+              $function($this->entityType, array($entity->id => $queried_entities[$id]),
+                  FIELD_LOAD_CURRENT, $options);
+              // Cache the field.
+              if ($field_cache) {
+                cache_set($cfid, $entity->$field_name, 'cache_field');
+              }
+            }
+          }
+          // If we don't have a list of fields then load them all, but only
+          // if the instance is a TripalField and it is set to not auto
+          // attach then we will ignore it. It can only be set by providing
+          // the id in the $field_id array handled previously.
+          else {
+            if (array_key_exists('settings', $instance) and
+                array_key_exists('auto_attach', $instance['settings']) and
+                $instance['settings']['auto_attach'] == FALSE) {
+               continue;
+            }
+            else {
+              // Check if the field is cached. if so, then don't reload.
+              if ($field_cache) {
+                $cache_data = cache_get($cfid, 'cache_field');
+                if (!empty($cache_data)) {
+                  $queried_entities[$id]->$field_name = $cache_data->data;
+                  continue;
                 }
               }
+              $function($this->entityType, array($entity->id => $queried_entities[$id]),
+                  FIELD_LOAD_CURRENT, $options);
+              // Cache the field.
+              if ($field_cache) {
+                cache_set($cfid, $entity->$field_name, 'cache_field');
+              }
             }
           }
         }
-
-        $options = array();
-        $options['field_id'] = $field_ids;
-        $function($this->entityType, array($entity->id => $entity), FIELD_LOAD_CURRENT, $options);
       }
     }
 

+ 92 - 8
tripal_chado/api/modules/tripal_chado.feature.api.inc

@@ -930,9 +930,9 @@ function chado_get_featureloc_sequences($feature_id, $featurelocs) {
     return array();
   }
 
-  // get the list of relationships (including any aggregators) and iterate
+  // Get the list of relationships (including any aggregators) and iterate
   // through each one to find information needed to color-code the reference sequence
-  $relationships = chado_get_feature_aggregate_relationships($feature_id);
+  $relationships = _tripal_feature_get_aggregate_relationships($feature_id);
   if (!$relationships) {
     return array();
   }
@@ -1203,12 +1203,15 @@ function chado_get_featurelocs($feature_id, $side = 'as_parent', $aggregate = 1)
       'vocabulary' => $sfeature->type_id->dbxref_id->db_id->name,
       'accession' => $sfeature->type_id->dbxref_id->accession,
     ));
-    $fbundle = tripal_load_bundle_entity(array('term_id' => $fterm->id));
-    $sbundle = tripal_load_bundle_entity(array('term_id' => $sterm->id));
-
-    $loc->feid = chado_get_record_entity_by_bundle($fbundle, $loc->feature_id);
-    $loc->seid = chado_get_record_entity_by_bundle($sbundle, $loc->src_feature_id);
 
+    if($fterm) {
+      $fbundle = tripal_load_bundle_entity(array('term_id' => $fterm->id));
+      $loc->feid = chado_get_record_entity_by_bundle($fbundle, $loc->feature_id);
+    }
+    if ($sterm) {
+      $sbundle = tripal_load_bundle_entity(array('term_id' => $sterm->id));
+      $loc->seid = chado_get_record_entity_by_bundle($sbundle, $loc->src_feature_id);
+    }
     // add the result to the array
     $featurelocs[$i++] = $loc;
   }
@@ -1217,7 +1220,7 @@ function chado_get_featurelocs($feature_id, $side = 'as_parent', $aggregate = 1)
   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);
+  $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);
@@ -1231,6 +1234,87 @@ function chado_get_featurelocs($feature_id, $side = 'as_parent', $aggregate = 1)
   return $featurelocs;
 }
 
+/**
+ * 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
+ *
+ */
+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')
+ *
+ */
+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;
+}
 /**
   * Used to sort the list of relationship parts by start position
   *

+ 1 - 1
tripal_chado/includes/TripalFields/chado_linker__prop/chado_linker__prop.inc

@@ -103,7 +103,7 @@ class chado_linker__prop extends ChadoField {
     $match = array(
       $fkey_lcolumn => $chado_record->{$fkey_lcolumn},
       'type_id' => $cvterm_id,
-      );
+    );
     $options = array(
       'return_array' => TRUE,
       'order_by' => array('rank' => 'ASC')

+ 5 - 0
tripal_chado/includes/TripalFields/data__protein_sequence/data__protein_sequence.inc

@@ -52,6 +52,11 @@ class data__protein_sequence extends ChadoField {
     $feature = $entity->chado_record;
     $num_seqs = 0;
 
+    // Set some defauls for the empty record
+    $entity->{$field_name}['und'][0] = array(
+      'value' => '',
+    );
+
     // Look for protein sequences based on the relationship of this field.
     $sql = "
       SELECT F.*

+ 2 - 2
tripal_chado/includes/TripalFields/data__protein_sequence/data__protein_sequence_formatter.inc

@@ -18,8 +18,8 @@ class data__protein_sequence_formatter extends ChadoFieldFormatter {
    * @param unknown $display
    */
   public function view(&$element, $entity_type, $entity, $langcode, $items, $display) {
-    $content = 'There is no sequence.';
-    if ($items[0]['value']) {
+    $content = 'There is no protein sequence.';
+    if (count($items) > 0 and $items[0]['value']) {
       $num_bases = 50;
       $content = '<pre class="protein-residues-formatter">';
       $content .= wordwrap($items[0]['value'], $num_bases, "<br>", TRUE);

+ 1 - 1
tripal_chado/includes/TripalFields/data__sequence/data__sequence_formatter.inc

@@ -13,7 +13,7 @@ class data__sequence_formatter extends ChadoFieldFormatter {
   public function view(&$element, $entity_type, $entity, $langcode, $items, $display) {
 
     $content = 'There is no sequence.';
-    if ($items[0]['value']) {
+    if (count($items) > 0 and $items[0]['value']) {
       $num_bases = 50;
       $content = '<pre class="residues-formatter">';
       $content .= wordwrap($items[0]['value'], $num_bases, "<br>", TRUE);

+ 44 - 0
tripal_chado/includes/TripalFields/data__sequence_coordinates/data__sequence_coordinates.inc

@@ -60,6 +60,50 @@ class data__sequence_coordinates extends ChadoField {
    * @see TripalField::load()
    */
   public function load($entity) {
+    $field_name = $this->field['field_name'];
+    $feature = $entity->chado_record;
+    $num_seqs = 0;
 
+    $options = array(
+      'return_array' => TRUE,
+      'order_by' => array('rank' => 'ASC'),
+    );
+    $feature = chado_expand_var($feature, 'table', 'featureloc', $options);
+
+    // Set some defauls for the empty record
+    $entity->{$field_name}['und'][0] = array(
+      'value' => array(
+        /*
+        // Types of elements that will appear in the value array.
+        // Annotation track
+        'data:3002' => '',
+        'local:fmin' => '',
+        'local:fmax' => '',
+        // phase
+        'data:2336' => '',
+        // strand
+        'data:0853' => '',
+        */
+      ),
+    );
+
+    // Get the featureloc records that this feature is aligned to.
+    $aligned = $feature->featureloc->feature_id;
+    foreach ($aligned as $index => $featureloc) {
+      $srcfeature = $featureloc->srcfeature_id->name;
+      $entity->{$field_name}['und'][0] = array(
+        'value' => array(
+          'data:3002' => $srcfeature,
+          'local:fmin' => $featureloc->fmin + 1,
+          'local:fmax' => $featureloc->fmax,
+          'data:2336' => $featureloc->phase,
+          'data:0853' => $featureloc->strand,
+        ),
+      );
+      $sentity_id = chado_get_record_entity_by_table('feature_id', $featureloc->srcfeature_id->feature_id);
+      if ($sentity_id) {
+        $entity->{$field_name}['und'][0]['value']['entity'] = 'TripalEntity:' . $sentity_id;
+      }
+    }
   }
 }

+ 24 - 0
tripal_chado/includes/TripalFields/data__sequence_coordinates/data__sequence_coordinates_formatter.inc

@@ -21,5 +21,29 @@ class data__sequence_coordinates_formatter extends ChadoFieldFormatter {
    */
   public function view(&$element, $entity_type, $entity, $langcode, $items, $display) {
 
+    $content = '';
+    foreach ($items as $item) {
+      if (!empty($item)) {
+        $srcfeature = $item['value']['data:3002'];
+        $fmin = $item['value']['local:fmin'];
+        $fmax = $item['value']['local:fmax'];
+        $phase = $item['value']['data:2336'];
+        $strand = $item['value']['data:0853'];
+        if ($strand == 1) {
+          $strand = '+';
+        }
+        else {
+          $strand = '-';
+        }
+        $content .= $srcfeature . ':' . $fmin . '..' . $fmax . $strand;
+      }
+    }
+    if (!$content) {
+      $content = 'This feature is not located on any sequence.';
+    }
+    $element[0] = array(
+      '#type' => 'markup',
+      '#markup' => $content,
+    );
   }
 }

+ 15 - 7
tripal_chado/includes/TripalFields/so__cds/so__cds.inc

@@ -51,16 +51,26 @@ class so__cds extends ChadoField {
     $feature = $entity->chado_record;
     $num_seqs = 0;
 
+    // Set some defauls for the empty record
+    $entity->{$field_name}['und'][0] = array(
+      'value' => '',
+    );
+
+    $options = array(
+      'return_array' => TRUE,
+      'order_by' => array('rank' => 'ASC'),
+    );
     $feature = chado_expand_var($feature, 'table', 'featureloc', $options);
-    $featureloc_sequences = chado_get_featureloc_sequences($feature->feature_id, $feature->featureloc->feature_id);
-    foreach($featureloc_sequences as $src => $attrs){
+    $featurelocs = $feature->featureloc->feature_id;
+    return;
+    foreach($featurelocs as $featureloc){
       // Generate a CDS sequence if one exsits for this feature alignment.
       $cds_sequence = tripal_get_feature_sequences(
         array(
           'feature_id' => $feature->feature_id,
-          'parent_id' => $attrs['featureloc']->srcfeature_id->feature_id,
+          'parent_id' => $featureloc->srcfeature_id->feature_id,
           'name' => $feature->name,
-          'featureloc_id' => $attrs['featureloc']->featureloc_id,
+          'featureloc_id' => $featureloc->featureloc_id,
         ),
         array(
           // CDS are in parent-child relationships so we want to use the
@@ -75,14 +85,12 @@ class so__cds extends ChadoField {
       );
 
       if (count($cds_sequence) > 0) {
-        $defline = tripal_get_fasta_defline($feature, '', $attrs['featureloc'], 'CDS', strlen($attrs['residues']));
-
         // the tripal_get_feature_sequences() function can return multiple sequences
         // if a feature is aligned to multiple places. In the case of CDSs we expect
         // that one mRNA is only aligned to a single location on the assembly so we
         // can access the CDS sequence with index 0.
         if ($cds_sequence[0]['residues']) {
-          $entity->{$field_name}['und'][$num_seqs++]['value'] = $defline . "\n" .  $cds_sequence[0]['residues'];
+          $entity->{$field_name}['und'][$num_seqs++]['value'] = $cds_sequence[0]['residues'];
         }
       }
     }

+ 8 - 22
tripal_chado/includes/TripalFields/so__cds/so__cds_formatter.inc

@@ -11,31 +11,17 @@ class so__cds_formatter extends ChadoFieldFormatter {
    * @see TripalFieldFormatter::view()
    */
   public function view(&$element, $entity_type, $entity, $langcode, $items, $display) {
+    $content = 'There is no coding sequence.';
+    if (count($items) > 0 and $items[0]['value']) {
+      $num_bases = 50;
+      $content = '<pre class="residues-formatter">';
+      $content .= wordwrap($items[0]['value'], $num_bases, "<br>", TRUE);
+      $content .= '</pre>';
+    }
     $element[0] = array(
       // We create a render array to produce the desired markup,
       '#type' => 'markup',
-      '#markup' => '',
+      '#markup' => $content,
     );
-
-    $num_bases = 50;
-    foreach ($items as $delta => $item) {
-      // If there are no residues then skip this one.
-      if (!is_array($item['value']) or !array_key_exists('residues', $item['value'])) {
-        continue;
-      }
-
-      $residues = $item['value']['residues'];
-
-      $content .= '<pre class="residues-formatter">';
-      $content .= '>' . $defline . "<br>";
-      $content .= wordwrap($residues, $num_bases, "<br>", TRUE);
-      $content .= '</pre>';
-
-      $element[$delta] = array(
-        // We create a render array to produce the desired markup,
-        '#type' => 'markup',
-        '#markup' => $content,
-      );
-    }
   }
 }

+ 45 - 4
tripal_chado/includes/tripal_chado.fields.inc

@@ -294,9 +294,9 @@ function tripal_chado_bundle_fields_info_custom(&$info, $details, $entity_type,
     );
   }
 
-  // PROTEIN SEQUENCE
+  // PROTEIN & CDS SEQUENCE
   if ($table_name == 'feature' and
-      ($bundle->label == 'mRNA' or $bundle->label == 'transcript' or $bundle->label == 'gene'))  {
+      ($bundle->label == 'mRNA' or $bundle->label == 'transcript'))  {
     $field_name = 'data__protein_sequence';
     $field_type = 'data__protein_sequence';
     $info[$field_name] = array(
@@ -308,6 +308,18 @@ function tripal_chado_bundle_fields_info_custom(&$info, $details, $entity_type,
         'type' => 'field_chado_storage',
       ),
     );
+
+    $field_name = 'so__cds';
+    $field_type = 'so__cds';
+    $info[$field_name] = array(
+      'field_name' => $field_name,
+      'type' => $field_type,
+      'cardinality' => 1,
+      'locked' => FALSE,
+      'storage' => array(
+        'type' => 'field_chado_storage',
+      ),
+    );
   }
 
   // GENE TRANSCRIPTS
@@ -1118,9 +1130,9 @@ function tripal_chado_bundle_instances_info_custom(&$info, $entity_type, $bundle
     );
   }
 
-  // PROTEIN SEQUENCES.
+  // PROTEIN & CDS SEQUENCES.
   if ($table_name == 'feature' and
-      ($bundle->label == 'mRNA' or $bundle->label == 'transcript' or $bundle->label == 'gene'))  {
+      ($bundle->label == 'mRNA' or $bundle->label == 'transcript'))  {
     $field_name = 'data__protein_sequence';
     $info[$field_name] = array(
       'field_name' => $field_name,
@@ -1149,6 +1161,35 @@ function tripal_chado_bundle_instances_info_custom(&$info, $entity_type, $bundle
         ),
       ),
     );
+
+    $field_name = 'so__cds';
+    $info[$field_name] = array(
+      'field_name' => $field_name,
+      'entity_type' => $entity_type,
+      'bundle' => $bundle->name,
+      'label' => 'Coding Sequence',
+      'description' => 'Coding sequences.',
+      'required' => FALSE,
+      'settings' => array(
+        'auto_attach' => FALSE,
+        'chado_table' => 'featureloc',
+        'chado_column' => '',
+        'base_table' => 'featureloc',
+      ),
+      'widget' => array(
+        'type' => 'so__cds_widget',
+        'settings' => array(
+          'display_label' => 1,
+        ),
+      ),
+      'display' => array(
+        'default' => array(
+          'label' => 'above',
+          'type' => 'so__cds_formatter',
+          'settings' => array(),
+        ),
+      ),
+    );
   }
 
 

+ 60 - 0
tripal_chado/includes/tripal_chado.semweb.inc

@@ -365,6 +365,31 @@ function tripal_chado_populate_vocab_EDAM() {
     'definition' => 'The name of a biological or bioinformatics database.',
   ));
   tripal_associate_chado_semweb_term('analysis', 'sourceuri', $term);
+
+  $term = tripal_insert_cvterm(array(
+    'id' => 'data:2336',
+    'name' => 'Translation phase specification',
+    'cv_name' => 'EDAM',
+    'definition' => 'Phase for translation of DNA (0, 1 or 2) relative to a fragment of the coding sequence.',
+  ));
+  tripal_associate_chado_semweb_term('featureloc', 'phase', $term);
+
+  $term = tripal_insert_cvterm(array(
+    'id' => 'data:0853',
+    'name' => 'DNA sense specification',
+    'cv_name' => 'EDAM',
+    'definition' => 'The strand of a DNA sequence (forward or reverse).',
+  ));
+  tripal_associate_chado_semweb_term('featureloc', 'strand', $term);
+  $term = tripal_insert_cvterm(array(
+    'id' => 'data:3002',
+    'name' => 'Annotation track',
+    'cv_name' => 'EDAM',
+    'definition' => 'Annotation of one particular positional feature on a ' .
+    'biomolecular (typically genome) sequence, suitable for import and ' .
+    'display in a genome browser. Synonym: Sequence annotation track.',
+  ));
+  tripal_associate_chado_semweb_term('featureloc', 'srcfeature_id', $term);
 }
 
 /**
@@ -1045,6 +1070,41 @@ function tripal_chado_populate_vocab_LOCAL() {
     'db_name' => 'local'
   ));
 
+  //--------------
+  // Featureloc Terms
+  //--------------
+  $term = tripal_insert_cvterm(array(
+    'id' => 'local:fmin',
+    'name' => 'minimal boundary',
+    'definition' => 'The leftmost, minimal boundary in the linear range ' .
+      'represented by the feature location. Sometimes this is called ' .
+      'start although this is confusing because it does not necessarily ' .
+      'represent the 5-prime coordinate.',
+    'cv_name' => 'local',
+  ));
+  tripal_associate_chado_semweb_term('featureloc', 'fmin', $term);
+  $term = tripal_insert_cvterm(array(
+    'id' => 'local:fmax',
+    'name' => 'maximal boundary',
+    'definition' => 'The rightmost, maximal boundary in the linear range ' .
+      'represented by the featureloc. Sometimes this is called end although ' .
+      'this is confusing because it does not necessarily represent the ' .
+      '3-prime coordinate',
+    'cv_name' => 'local',
+  ));
+  tripal_associate_chado_semweb_term('featureloc', 'fmax', $term);
+
+  $term = tripal_insert_cvterm(array(
+    'id' => 'local:unknown_fmin',
+    'name' => ' minimal boundary',
+    'definition' => 'The leftmost, minimal boundary in the linear range ' .
+    'represented by the feature location. Sometimes this is called ' .
+    'start although this is confusing because it does not necessarily ' .
+    'represent the 5-prime coordinate.',
+    'cv_name' => 'local',
+  ));
+  tripal_associate_chado_semweb_term('featureloc', 'fmin', $term);
+
 
   //--------------
   // Analysis Terms

+ 16 - 14
tripal_chado/theme/css/tripal_chado.css

@@ -23,23 +23,25 @@
 }
 
 .protein-residues-formatter {
-   border: 1px solid #dddddd;
-   color: #000000;
-   height: 100px;
-   max-width: 500px;
-   overflow: scroll;
-   white-space: normal;
-   background-color: white;
+  color: black;
+  height: 100px;
+  max-width: 500px;
+  overflow: scroll;
+  white-space: normal;
+  background-color: transparent;
+  margin: 0px;
+  padding: 0px;
 }
 
 .residues-formatter {
-   border: 1px solid #dddddd;
-   color: #000000;
-   height: 300px;
-   max-width: 500px;
-   overflow: scroll;
-   white-space: normal;
-   background-color: white;
+  color: black;
+  height: 300px;
+  max-width: 500px;
+  overflow: scroll;
+  white-space: normal;
+  background-color: transparent;
+  margin: 0px;
+  padding: 0px;
 }
 
 .form-field-ui-field-overview-storage-logo {

+ 63 - 1
tripal_chado/tripal_chado.install

@@ -388,7 +388,7 @@ function tripal_chado_upgrade_v2_v3_enable() {
     db_query($sql);
     if (db_query("SELECT 1 FROM pg_indexes WHERE indexname = 'tripal_cv_obo_pkey2'")->fetchField()) {
       $sql = "ALTER INDEX tripal_cv_obo_pkey2 RENAME TO tripal_cv_obo_pkey";
-    } 
+    }
     else {
       $sql = "ALTER INDEX tripal_cv_obo_tripal_cv_obo_idx1_idx2 RENAME TO tripal_cv_obo_tripal_cv_obo_idx1_idx";
     }
@@ -811,4 +811,66 @@ function tripal_chado_update_7303() {
     $error = $e->getMessage();
     throw new DrupalUpdateException('Could not perform update: '. $error);
   }
+}
+
+/**
+ * Add some new controlled vocabulary terms.
+ */
+function tripal_chado_update_7304() {
+  try {
+    $term = tripal_insert_cvterm(array(
+      'id' => 'SIO:001080',
+      'name' => 'vocabulary',
+      'cv_name' => 'SIO',
+      'definition' => 'A vocabulary is a collection of terms.',
+    ));
+    tripal_associate_chado_semweb_term('cvterm', 'cv_id', $term);
+    $term = tripal_insert_cvterm(array(
+      'id' => 'data:2976',
+      'name' => 'Protein sequence',
+      'cv_name' => 'EDAM',
+      'definition' => 'One or more protein sequences, possibly with associated annotation.',
+    ));
+    $term = tripal_insert_cvterm(array(
+      'id' => 'local:fmin',
+      'name' => 'minimal boundary',
+      'definition' => 'The leftmost, minimal boundary in the linear range ' .
+      'represented by the feature location. Sometimes this is called ' .
+      'start although this is confusing because it does not necessarily ' .
+      'represent the 5-prime coordinate.',
+      'cv_name' => 'local',
+    ));
+    tripal_associate_chado_semweb_term('featureloc', 'fmin', $term);
+    $term = tripal_insert_cvterm(array(
+      'id' => 'local:fmax',
+      'name' => 'maximal boundary',
+      'definition' => 'The rightmost, maximal boundary in the linear range ' .
+      'represented by the featureloc. Sometimes this is called end although ' .
+      'this is confusing because it does not necessarily represent the ' .
+      '3-prime coordinate',
+      'cv_name' => 'local',
+    ));
+    tripal_associate_chado_semweb_term('featureloc', 'fmax', $term);
+    $term = tripal_insert_cvterm(array(
+      'id' => 'data:2336',
+      'name' => 'Translation phase specification',
+      'cv_name' => 'EDAM',
+      'definition' => 'Phase for translation of DNA (0, 1 or 2) relative to a fragment of the coding sequence.',
+    ));
+    tripal_associate_chado_semweb_term('featureloc', 'phase', $term);
+    $term = tripal_insert_cvterm(array(
+      'id' => 'data:3002',
+      'name' => 'Annotation track',
+      'cv_name' => 'EDAM',
+      'definition' => 'Annotation of one particular positional feature on a ' .
+        'biomolecular (typically genome) sequence, suitable for import and ' .
+        'display in a genome browser. Synonym: Sequence annotation track.',
+    ));
+    tripal_associate_chado_semweb_term('featureloc', 'srcfeature_id', $term);
+  }
+  catch (\PDOException $e) {
+    $transaction->rollback();
+    $error = $e->getMessage();
+    throw new DrupalUpdateException('Could not perform update: '. $error);
+  }
 }