Browse Source

Merge branch '7.x-3.x' of github.com:tripal/tripal into 7.x-3.x

Stephen Ficklin 8 years ago
parent
commit
9289521815

+ 555 - 0
tripal_chado/includes/TripalFields/data__sequence.inc

@@ -0,0 +1,555 @@
+<?php
+
+class data__sequence extends TripalField {
+
+
+  // --------------------------------------------------------------------------
+  //                     EDITABLE STATIC CONSTANTS
+  //
+  // The following constants SHOULD be set for each descendent class.  They are
+  // used by the static functions to provide information to Drupal about
+  // the field and it's default widget and formatter.
+  // --------------------------------------------------------------------------
+
+  // The term that this field maps to.  The format for the term should be:
+  // [vocab]:[accession] where [vocab] is the short name of the vocabulary
+  // and [acession] is the unique accession number for the term.  This term
+  // must already exist in the vocabulary storage backend. This
+  // value should never be changed once fields exist for this type.
+  public static $term = 'data:2044';
+
+  // The default lable for this field.
+  public static $label = 'Sequence';
+
+  // The default description for this field.
+  public static $description = 'A field for managing nucleotide and protein residues.';
+
+  // Provide a list of global settings. These can be accessed witihn the
+  // globalSettingsForm.  When the globalSettingsForm is submitted then
+  // Drupal will automatically change these settings for all fields.
+  public static $settings = array(
+    'chado_table' => '',
+    'chado_column' => '',
+    'base_table' => '',
+  );
+
+  // Provide a list of instance specific settings. These can be access within
+  // the instanceSettingsForm.  When the instanceSettingsForm is submitted
+  // then Drupal with automatically change these settings for the instnace.
+  // It is recommended to put settings at the instance level whenever possible.
+  public static $instance_settings  = array();
+
+  // Set this to the name of the storage backend that by default will support
+  // this field.
+  public static $storage = 'tripal_no_storage';
+
+  // The default widget for this field.
+  public static $default_widget = 'data__sequence_widget';
+
+  // The default formatter for this field.
+  public static $default_formatter = 'data__sequence_formatter';
+
+  // --------------------------------------------------------------------------
+  //              PROTECTED CLASS MEMBERS -- DO NOT OVERRIDE
+  // --------------------------------------------------------------------------
+  // An array containing details about the field. The format of this array
+  // is the same as that returned by field_info_fields()
+  protected $field;
+  // An array containing details about an instance of the field. A field does
+  // not have to have an instance.  But if dealing with an instance (such as
+  // when using the widgetForm, formatterSettingsForm, etc.) it should be set.
+  protected $instance;
+
+  public function load($entity, $details = array()) {
+    $field_name = $this->field['field_name'];
+    $feature = $details['record'];
+    $num_seqs = 0;
+    
+    // We don't want to get the sequence for traditionally large types. They are
+    // too big,  bog down the web browser, take longer to load and it's not
+    // reasonable to print them on a page.
+    if(strcmp($feature->type_id->name,'scaffold') == 0 or
+        strcmp($feature->type_id->name,'chromosome') == 0 or
+        strcmp($feature->type_id->name,'supercontig') == 0 or
+        strcmp($feature->type_id->name,'pseudomolecule') == 0) {
+          $entity->{$field_name}['und'][$num_seqs]['value'] = array(
+            '@type' => 'SO:0000110',
+            'type' => 'sequence_feature',
+            'label' => 'Residues',
+            'defline' => ">This sequence is too large for this display.",
+            'residues' => '',
+          );
+          $entity->{$field_name}['und'][$num_seqs]['chado-feature__residues'] = '';
+        }
+        else {
+          $feature = chado_expand_var($feature,'field','feature.residues');
+          if ($feature->residues) {
+            $entity->{$field_name}['und'][$num_seqs]['value'] = array(
+              '@type' => 'SO:0000110',
+              'type' => 'sequence_feature',
+              'label' => 'Raw Sequence',
+              'defline' => tripal_get_fasta_defline($feature, '', NULL, '', strlen($feature->residues)),
+              'residues' => $feature->residues,
+            );
+            $entity->{$field_name}['und'][$num_seqs]['chado-feature__residues'] = $feature->residues;
+          }
+          else {
+            $entity->{$field_name}['und'][$num_seqs]['value'] = array();
+            $entity->{$field_name}['und'][$num_seqs]['chado-feature__residues'] = '';
+          }
+        }
+        $num_seqs++;
+    
+        // Add in the protein sequences. It's faster to provide the SQL rather than
+        // to use chado_generate_var based on the type.
+        $sql = "
+      SELECT F.*
+      FROM {feature_relationship} FR
+        INNER JOIN {feature} F on FR.subject_id = F.feature_id
+        INNER JOIN {cvterm} CVT on CVT.cvterm_id = F.type_id
+        INNER JOIN {cvterm} RCVT on RCVT.cvterm_id = FR.type_id
+      WHERE
+        FR.object_id = :feature_id and
+        CVT.name = 'polypeptide' and
+        RCVT.name = 'derives_from'
+      ORDER BY FR.rank ASC
+    ";
+        $results = chado_query($sql, array(':feature_id' => $feature->feature_id));
+        while ($protein = $results->fetchObject()) {
+          if ($protein->residues) {
+            $entity->{$field_name}['und'][$num_seqs++]['value'] = array(
+              '@type' => 'SO:0000104',
+              'type' => 'polypeptide',
+              'label' => 'Protein Sequence',
+              'defline' => tripal_get_fasta_defline($protein, '', NULL, '', strlen($protein->residues)),
+              'residues' => $protein->residues,
+            );
+          }
+        }
+    
+    
+        // Add in sequences from alignments.
+        $options = array(
+          'return_array' => 1,
+          'include_fk' => array(
+            'srcfeature_id' => array(
+              'type_id' => 1
+            ),
+            'feature_id' => array(
+              'type_id' => 1
+            ),
+          ),
+        );
+        $feature = chado_expand_var($feature, 'table', 'featureloc', $options);
+        $featureloc_sequences = $this->get_featureloc_sequences($feature->feature_id, $feature->featureloc->feature_id);
+    
+        // Add in the coding sequences. It's faster to provide the SQL rather than
+        // to use chado_generate_var based on the type.
+        $sql = "
+      SELECT F.*
+      FROM {feature_relationship} FR
+        INNER JOIN {feature} F on FR.subject_id = F.feature_id
+        INNER JOIN {cvterm} CVT on CVT.cvterm_id = F.type_id
+        INNER JOIN {cvterm} RCVT on RCVT.cvterm_id = FR.type_id
+        INNER JOIN {featureloc} FL on FL.feature_id = F.feature_id
+      WHERE
+        FR.object_id = :feature_id and
+        CVT.name = 'CDS' and
+        RCVT.name = 'part_of'
+      ORDER BY FR.rank ASC
+    ";
+        $results = chado_query($sql, array(':feature_id' => $feature->feature_id));
+        $coding_seq = '';
+        while ($CDS = $results->fetchObject()) {
+          if ($CDS->residues) {
+            $coding_seq .= $CDS->residues;
+          }
+        }
+        if ($coding_seq) {
+          $entity->{$field_name}['und'][$num_seqs++]['value'] = array(
+            '@type' => 'SO:0000316',
+            'type' => 'coding_sequence',
+            'label' => 'Coding sequence (CDS)',
+            'defline' => tripal_get_fasta_defline($feature, 'CDS', NULL, '', strlen($coding_seq)),
+            'residues' => $coding_seq,
+          );
+        }
+    
+        foreach($featureloc_sequences as $src => $attrs){
+          // the $attrs array has the following keys
+          //   * id:  a unique identifier combining the feature id with the cvterm id
+          //   * type: the type of sequence (e.g. mRNA, etc)
+          //   * location:  the alignment location
+          //   * defline: the definition line
+          //   * formatted_seq: the formatted sequences
+          //   * featureloc:  the feature object aligned to
+          $entity->{$field_name}['und'][$num_seqs++]['value'] = array(
+            'residues' => $attrs['residues'],
+            '@type' => 'SO:0000110',
+            'type' => 'sequence_feature',
+            'defline' => tripal_get_fasta_defline($feature, '', $attrs['featureloc'], 'CDS', strlen($attrs['residues'])),
+            'label' => 'Sequence from alignment at ' . $attrs['location'],
+          );
+    
+    
+          // check to see if this alignment has any CDS. If so, generate a CDS sequence
+          $cds_sequence = tripal_get_feature_sequences(
+              array(
+                'feature_id' => $feature->feature_id,
+                'parent_id' => $attrs['featureloc']->srcfeature_id->feature_id,
+                'name' => $feature->name,
+                'featureloc_id' => $attrs['featureloc']->featureloc_id,
+              ),
+              array(
+                '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
+                'sub_feature_types' => array('CDS'), // we're looking for CDS features
+                'is_html' => 0
+              )
+              );
+    
+          if (count($cds_sequence) > 0) {
+            // 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'] = array(
+                'residues' => $cds_sequence[0]['residues'],
+                '@type' => 'SO:0000316',
+                'type' => 'coding_sequence',
+                'defline' => tripal_get_fasta_defline($feature, '', $attrs['featureloc'], 'CDS', $cds_sequence[0]['length']),
+                'label' => 'Coding sequence (CDS) from alignment at  ' . $attrs['location'],
+              );
+            }
+          }
+        }
+  }
+  
+  /**
+   *
+   * @param unknown $feature_id
+   * @param unknown $featurelocs
+   * @return multitype:|Ambigous <multitype:, an>
+   */
+  private function get_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 = $this->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 = $this->get_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, 'chado_feature__residues_sort_rel_parts_by_start');
+        }
+        else {
+          usort($rparts, 'chado_feature__residues_sort_rel_parts_by_start');
+          $parts = $rparts;
+        }
+  
+        $floc_sequences[$src]['id'] = $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_reverse_compliment_sequence($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, '', strlen($residues));
+        $floc_sequences[$src]['featureloc'] = $featureloc;
+        $floc_sequences[$src]['residues'] = $residues;
+        //$floc_sequences[$src]['formatted_seq'] =  tripal_feature_color_sequence($residues, $parts, $floc_sequences[$src]['defline']);
+      }
+    }
+    return $floc_sequences;
+  }
+  
+  /**
+   * 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
+   */
+  private function 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 $this->get_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
+   */
+  private function get_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;
+    $esql = "
+        SELECT entity_id
+        FROM {chado_entity}
+        WHERE data_table = 'feature' AND record_id = :feature_id";
+    $relationships = array();
+    while ($rel = $results->fetchObject()) {
+      $entity = db_query($esql, array(':feature_id' => $rel->subject_id))->fetchObject();
+      if ($entity) {
+        $rel->subject_entity_id = $entity->entity_id;
+      }
+      $entity = db_query($esql, array(':feature_id' => $rel->object_id))->fetchObject();
+      if ($entity) {
+        $rel->object_entity_id = $entity->entity_id;
+      }
+      $relationships[$i++] = $rel;
+    }
+    return $relationships;
+  }
+  
+  /**
+   * 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
+   */
+  private function get_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->feid = tripal_get_chado_entity_id('feature', $loc->feature_id);
+      $loc->seid = tripal_get_chado_entity_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, 'chado_feature__residues_sort_locations');
+    return $featurelocs;
+  }
+}
+
+/**
+ * Used to sort the list of relationship parts by start position
+ *
+ * @ingroup tripal_feature
+ */
+function chado_feature__residues_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 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 chado_feature__residues_sort_locations($a, $b) {
+  return strnatcmp($a->fmin, $b->fmin);
+}

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

@@ -19,7 +19,7 @@ class data__sequence_checksum extends TripalField {
   public static $term = 'data:2190';
 
   // The default lable for this field.
-  public static $label = 'Sequence MD5 checksum';
+  public static $label = 'Sequence checksum';
 
   // The default description for this field.
   public static $description = 'A field for generating MD5 checksum for a sequence.';

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

@@ -2,7 +2,7 @@
 
 class data__sequence_checksum_formatter extends TripalFieldFormatter {
   // The default lable for this field.
-  public static $label = 'Sequence MD5 checksum';
+  public static $label = 'Sequence checksum';
 
   // The list of field types for which this formatter is appropriate.
   public static $field_types = array('data__sequence_checksum');

+ 3 - 14
tripal_chado/includes/TripalFields/data__sequence_checksum_widget.inc

@@ -2,28 +2,17 @@
 
 class data__sequence_checksum_widget extends TripalFieldWidget {
   // The default lable for this field.
-  public static $label = 'Sequence MD5 checksum';
+  public static $label = 'Sequence checksum';
 
   // The list of field types for which this formatter is appropriate.
-  public static $field_types = array('no_widget');
-
-
-  /**
-   * 
-   * @param unknown $field
-   * @param unknown $instance
-   */
-  public function __construct($field, $instance = NULL) {
-    $this->field = $field;
-    $this->instance = $instance;
-  }
+  public static $field_types = array('data__sequence_checksum');
 
   /**
    * 
    * @see TripalFieldWidget::form()
    */
   public function form(&$widget, &$form, &$form_state, $langcode, $items, $delta, $element) {
-    parent::widgetForm($widget, $form, $form_state, $langcode, $items, $delta, $element);
+    parent::form($widget, $form, $form_state, $langcode, $items, $delta, $element);
     
     $settings = $this->field['settings'];
     $field_name = $this->field['field_name'];

+ 53 - 0
tripal_chado/includes/TripalFields/data__sequence_formatter.inc

@@ -0,0 +1,53 @@
+<?php
+
+class data__sequence_formatter extends TripalFieldFormatter {
+  // The default lable for this field.
+  public static $label = 'Sequence';
+
+  // The list of field types for which this formatter is appropriate.
+  public static $field_types = array('data__sequence');
+
+  // The list of default settings for this formatter.
+  public static $settings = array();
+
+  /**
+   * 
+   * @param unknown $element
+   * @param unknown $entity_type
+   * @param unknown $entity
+   * @param unknown $langcode
+   * @param unknown $items
+   * @param unknown $display
+   */
+  public function view(&$element, $entity_type, $entity, $langcode, $items, $display) {
+    $element[0] = array(
+      // We create a render array to produce the desired markup,
+      '#type' => 'markup',
+      '#markup' => '',
+    );
+    
+    $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'];
+      $label = $item['value']['label'];
+      $defline = $item['value']['defline'];
+    
+      $content = '<p>' . $label . '<p>';
+      $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,
+      );
+    }
+  }
+}

+ 70 - 0
tripal_chado/includes/TripalFields/data__sequence_length.inc

@@ -0,0 +1,70 @@
+<?php
+
+class data__sequence_length extends TripalField {
+
+
+  // --------------------------------------------------------------------------
+  //                     EDITABLE STATIC CONSTANTS
+  //
+  // The following constants SHOULD be set for each descendent class.  They are
+  // used by the static functions to provide information to Drupal about
+  // the field and it's default widget and formatter.
+  // --------------------------------------------------------------------------
+
+  // The term that this field maps to.  The format for the term should be:
+  // [vocab]:[accession] where [vocab] is the short name of the vocabulary
+  // and [acession] is the unique accession number for the term.  This term
+  // must already exist in the vocabulary storage backend. This
+  // value should never be changed once fields exist for this type.
+  public static $term = 'data:1249';
+
+  // The default lable for this field.
+  public static $label = 'Sequence length';
+
+  // The default description for this field.
+  public static $description = 'A field for calculating the length of a sequence.';
+
+  // Provide a list of global settings. These can be accessed witihn the
+  // globalSettingsForm.  When the globalSettingsForm is submitted then
+  // Drupal will automatically change these settings for all fields.
+  public static $settings = array(
+    'chado_table' => '',
+    'chado_column' => '',
+    'base_table' => '',
+  );
+
+  // Provide a list of instance specific settings. These can be access within
+  // the instanceSettingsForm.  When the instanceSettingsForm is submitted
+  // then Drupal with automatically change these settings for the instnace.
+  // It is recommended to put settings at the instance level whenever possible.
+  public static $instance_settings  = array();
+
+  // Set this to the name of the storage backend that by default will support
+  // this field.
+  public static $storage = 'tripal_no_storage';
+
+  // The default widget for this field.
+  public static $default_widget = 'data__sequence_length_widget';
+
+  // The default formatter for this field.
+  public static $default_formatter = 'data__sequence_length_formatter';
+
+  // --------------------------------------------------------------------------
+  //              PROTECTED CLASS MEMBERS -- DO NOT OVERRIDE
+  // --------------------------------------------------------------------------
+  // An array containing details about the field. The format of this array
+  // is the same as that returned by field_info_fields()
+  protected $field;
+  // An array containing details about an instance of the field. A field does
+  // not have to have an instance.  But if dealing with an instance (such as
+  // when using the widgetForm, formatterSettingsForm, etc.) it should be set.
+  protected $instance;
+
+  /**
+   * 
+   * @see TripalField::load()
+   */
+  public function load($entity, $details = array()) {
+
+  }
+}

+ 32 - 0
tripal_chado/includes/TripalFields/data__sequence_length_formatter.inc

@@ -0,0 +1,32 @@
+<?php
+
+class data__sequence_length_formatter extends TripalFieldFormatter {
+  // The default lable for this field.
+  public static $label = 'Sequence length';
+
+  // The list of field types for which this formatter is appropriate.
+  public static $field_types = array('data__sequence_length');
+
+  // The list of default settings for this formatter.
+  public static $settings = array();
+  /**
+   * 
+   * @see TripalFieldFormatter::settingsForm()
+   */
+  public function settingsForm($view_mode, $form, &$form_state) {
+
+  }
+
+  /**
+   * 
+   * @see TripalFieldFormatter::view()
+   */
+  public function view(&$element, $entity_type, $entity, $langcode, $items, $display) {
+    foreach ($items as $delta => $item) {
+      $element[$delta] = array(
+        '#type' => 'markup',
+        '#markup' => $item['value'],
+      );
+    }
+  }
+}

+ 73 - 0
tripal_chado/includes/TripalFields/data__sequence_length_widget.inc

@@ -0,0 +1,73 @@
+<?php
+
+class data__sequence_length_widget extends TripalFieldWidget {
+  // The default lable for this field.
+  public static $label = 'Sequence length';
+
+  // The list of field types for which this formatter is appropriate.
+  public static $field_types = array('data__sequence_length');
+
+  /**
+   * 
+   * @see TripalFieldWidget::form()
+   */
+  public function form(&$widget, &$form, &$form_state, $langcode, $items, $delta, $element) {
+    parent::form($widget, $form, $form_state, $langcode, $items, $delta, $element);
+    $field_name = $this->field['field_name'];
+    $field_type = $this->field['type'];
+    $field_table = $this->field['settings']['chado_table'];
+    $field_column = $this->field['settings']['chado_column'];
+    
+    $widget['value'] = array(
+      '#type' => 'value',
+      '#value' => array_key_exists($delta, $items) ? $items[$delta]['value'] : '',
+    );
+    
+    $widget['chado-feature__seqlen'] =  array(
+      '#type' => 'value',
+      '#value' => 0,
+      '#title' => $element['#title'],
+      '#description' => $element['#description'],
+      '#weight' => isset($element['#weight']) ? $element['#weight'] : 0,
+      '#delta' => $delta,
+    );
+  }
+
+  /**
+   * Performs validation of the widgetForm.
+   *
+   * Use this validate to ensure that form values are entered correctly.  Note
+   * this is different from the validate() function which ensures that the
+   * field data meets expectations.
+   *
+   * @param $form
+   * @param $form_state
+   */
+  public function validate($form, &$form_state, $entity_type, $entity, $langcode, $delta) {
+
+  }
+
+
+  /**
+   * 
+   * @see TripalFieldWidget::submit()
+   */
+  public function submit($form, &$form_state, $entity_type, $entity, $langcode, $delta) {
+    $field_name = $this->field['field_name'];
+    $field_type = $this->field['type'];
+    $field_table = $this->field['settings']['chado_table'];
+    $field_column = $this->field['settings']['chado_column'];
+    
+    // Get the residues so we can calculate teh length.
+    $residues = $form_state['values']['feature__residues']['und'][0]['chado-feature__residues'];
+    // Remove any white spaces.
+    if ($residues) {
+      $residues = preg_replace('/\s/', '', $residues);
+      $form_state['values']['feature__residues']['und'][0]['chado-feature__residues'] = $residues;
+      $items[0]['chado-feature__seqlen'] = strlen($residues);
+    }
+    else {
+      $items[0]['chado-feature__seqlen'] = '__NULL__';
+    }
+  }
+}

+ 76 - 0
tripal_chado/includes/TripalFields/data__sequence_widget.inc

@@ -0,0 +1,76 @@
+<?php
+
+class data__sequence_widget extends TripalFieldWidget {
+  // The default lable for this field.
+  public static $label = 'Sequence';
+
+  // The list of field types for which this formatter is appropriate.
+  public static $field_types = array('data__sequence');
+
+  /**
+   * 
+   * @see TripalFieldWidget::form()
+   */
+  public function form(&$widget, &$form, &$form_state, $langcode, $items, $delta, $element) {
+    parent::form($widget, $form, $form_state, $langcode, $items, $delta, $element);
+    
+    $settings = $this->field['settings'];
+    $field_name = $this->field['field_name'];
+    $field_type = $this->field['type'];
+    $field_table = $this->field['settings']['chado_table'];
+    $field_column = $this->field['settings']['chado_column'];
+    
+    // Get the field defaults.
+    $residues = '';
+    if (count($items) > 0 and array_key_exists('chado-feature__residues', $items[0])) {
+      $residues = $items[0]['chado-feature__residues'];
+    }
+    if (array_key_exists('values', $form_state)) {
+      //$residues = tripal_chado_get_field_form_values($field_name, $form_state, 0, 'feature__residues');
+    }
+    
+    $widget['value'] = array(
+      '#type' => 'value',
+      '#value' => array_key_exists($delta, $items) ? $items[$delta]['value'] : '',
+    );
+    $widget['chado-feature__residues'] = array(
+      '#type' => 'textarea',
+      '#title' => $element['#title'],
+      '#description' => $element['#description'],
+      '#weight' => isset($element['#weight']) ? $element['#weight'] : 0,
+      '#default_value' => $residues,
+      '#delta' => $delta,
+      '#cols' => 30,
+    );
+  }
+
+  /**
+   * Performs validation of the widgetForm.
+   *
+   * Use this validate to ensure that form values are entered correctly.  Note
+   * this is different from the validate() function which ensures that the
+   * field data meets expectations.
+   *
+   * @param $form
+   * @param $form_state
+   */
+  public function validate($form, &$form_state, $entity_type, $entity, $langcode, $delta) {
+
+  }
+
+
+  /**
+   * 
+   * @see TripalFieldWidget::submit()
+   */
+  public function submit($form, &$form_state, $entity_type, $entity, $langcode, $delta) {
+    $field_name = $this->field['field_name'];
+    
+    // Remove any white spaces.
+    $residues = isset($form_state['values'][$field_name][$langcode][$delta]['chado-feature__residues']) ? $form_state['values'][$field_name][$langcode][$delta]['chado-feature__residues'] : '';
+    if ($residues) {
+      $residues = preg_replace('/\s/', '', $residues);
+      $form_state['values'][$field_name][$langcode][$delta]['chado-feature__residues'] = $residues;
+    }
+  }
+}

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

@@ -3,7 +3,7 @@
 class obi__organism_formatter extends TripalFieldFormatter {
 
   // The default lable for this field.
-  public static $label = 'Tripal Field.';
+  public static $label = 'Organism';
 
   // The list of field types for which this formatter is appropriate.
   public static $field_types = array('obi__organism');

+ 144 - 0
tripal_chado/includes/TripalFields/so__transcript.inc

@@ -0,0 +1,144 @@
+<?php
+
+class so__transcript extends TripalField {
+
+
+  // --------------------------------------------------------------------------
+  //                     EDITABLE STATIC CONSTANTS
+  //
+  // The following constants SHOULD be set for each descendent class.  They are
+  // used by the static functions to provide information to Drupal about
+  // the field and it's default widget and formatter.
+  // --------------------------------------------------------------------------
+
+  // The term that this field maps to.  The format for the term should be:
+  // [vocab]:[accession] where [vocab] is the short name of the vocabulary
+  // and [acession] is the unique accession number for the term.  This term
+  // must already exist in the vocabulary storage backend. This
+  // value should never be changed once fields exist for this type.
+  public static $term = 'SO:0000673';
+
+  // The default lable for this field.
+  public static $label = 'Transcript';
+
+  // The default description for this field.
+  public static $description = 'An RNA synthesized on a DNA or RNA template by an RNA polymerase.';
+
+  // Provide a list of global settings. These can be accessed witihn the
+  // globalSettingsForm.  When the globalSettingsForm is submitted then
+  // Drupal will automatically change these settings for all fields.
+  public static $settings = array(
+    'chado_table' => '',
+    'chado_column' => '',
+    'base_table' => '',
+  );
+
+  // Provide a list of instance specific settings. These can be access within
+  // the instanceSettingsForm.  When the instanceSettingsForm is submitted
+  // then Drupal with automatically change these settings for the instnace.
+  // It is recommended to put settings at the instance level whenever possible.
+  public static $instance_settings  = array();
+
+  // Set this to the name of the storage backend that by default will support
+  // this field.
+  public static $storage = 'tripal_no_storage';
+
+  // The default widget for this field.
+  public static $default_widget = 'so__transcript_widget';
+
+  // The default formatter for this field.
+  public static $default_formatter = 'so__transcript_formatter';
+
+  // --------------------------------------------------------------------------
+  //              PROTECTED CLASS MEMBERS -- DO NOT OVERRIDE
+  // --------------------------------------------------------------------------
+  // An array containing details about the field. The format of this array
+  // is the same as that returned by field_info_fields()
+  protected $field;
+  // An array containing details about an instance of the field. A field does
+  // not have to have an instance.  But if dealing with an instance (such as
+  // when using the widgetForm, formatterSettingsForm, etc.) it should be set.
+  protected $instance;
+
+
+  /**
+   *
+   * @see TripalField::validate()
+   */
+  public function validate($entity_type, $entity, $field, $items, &$errors) {
+
+  }
+
+
+  /**
+   *
+   * @see TripalField::load()
+   */
+  public function load($entity, $details = array()) {
+
+    $record = $details['record'];
+    
+    $field_name = $this->field['field_name'];
+    
+    // Set some defaults for the empty record.
+    $entity->{$field_name}['und'][0] = array(
+      'value' => array(
+        'type' => '',
+        'name' => '',
+        'identifier' => '',
+        'location' => '',
+      ),
+    );
+    
+    // TODO: If the tripal_get_feature_relationships() slows this down then
+    // we may need to write a custom function to get the data.
+    $rels = tripal_get_feature_relationships($record);
+    
+    // TODO: what if other transcripts names from SO are used. In that
+    // case we should support those too (using cvtermpath table to find them).
+    // mRNA should not be hard-coded below.
+    
+    // Set the value to be a array of "table" rows.
+    $transcripts = array();
+    if (key_exists('part of', $rels['object']) &&
+        key_exists('mRNA', $rels['object']['part of'])) {
+          $transcripts =  $rels['object']['part of']['mRNA'];
+        }
+    
+        $headers = array('Name' ,'Identifier', 'Location');
+        $rows = array();
+        $i = 0;
+        foreach ($transcripts as $transcript) {
+          // link the feature to it's node
+          $feature_name = $transcript->record->subject_id->name;
+    
+          $locations = $transcript->child_featurelocs;
+          $loc = "";
+          foreach ($locations AS $location) {
+            $loc .= $location->srcfeature_name . ":" . $location->fmin . ".." . $location->fmax;
+          }
+          $type = $transcript->record->subject_id->type_id;
+          $entity->{$field_name}['und'][$i]['value'] = array(
+            'type' => $type->name,
+            'name' => $feature_name,
+            'identifier' => $transcript->record->subject_id->uniquename,
+            'location' => $loc,
+    
+          );
+          // Add in the semantic web information that describes each key in the
+          // value array.
+          $entity->{$field_name}['und'][$i]['semantic_web'] = array(
+            'type' => $type->dbxref_id->db_id->name . ":" . $type->dbxref_id->accession,
+            'name' => tripal_get_chado_semweb_term('cvterm', 'name'),
+            'identifier' => tripal_get_chado_semweb_term('feature', 'uniquename'),
+            'location' => '',
+          );
+          if (property_exists($transcript->record->subject_id, 'entity_id')) {
+            $entity_id = $transcript->record->subject_id->entity_id;
+            $entity->{$field_name}['und'][$i]['value']['entity'] = 'TripalEntity:' . $entity_id;
+          }
+          $i++;
+        }
+  }
+
+}

+ 74 - 0
tripal_chado/includes/TripalFields/so__transcript_formatter.inc

@@ -0,0 +1,74 @@
+<?php
+
+class so__transcript_formatter extends TripalFieldFormatter {
+  // The default lable for this field.
+  public static $label = 'Transcript';
+
+  // The list of field types for which this formatter is appropriate.
+  public static $field_types = array('so__transcript');
+
+  // The list of default settings for this formatter.
+  public static $settings = array();
+  /**
+   *
+   * @see TripalFieldFormatter::settingsForm()
+   */
+  public function settingsForm($view_mode, $form, &$form_state) {
+
+  }
+
+  /**
+   *
+   * @see TripalFieldFormatter::view()
+   */
+  public function view(&$element, $entity_type, $entity, $langcode, $items, $display) {
+
+    // Get the settings
+    $settings = $display['settings'];
+    
+    $headers = array('Transcript Name', 'Identifier', 'Type', 'Location');
+    $rows = array();
+    foreach ($items as $delta => $item) {
+    
+      if (!$item['value']) {
+        continue;
+      }
+      $transcript = $item['value'];
+    
+      // Get the field values
+      $feature_name = $transcript['name'];
+      $feature_uname = $transcript['identifier'];
+      $loc = $transcript['location'];
+      $type = $transcript['type'];
+    
+      // Add a link i there is an entity.
+      if (array_key_exists('entity', $item['value']) and $item['value']['entity']) {
+        list($entity_type, $entity_id) = explode(':', $item['value']['entity']);
+        $feature_name = l($feature_name, "bio_data/" . $entity_id, array('attributes' => array('target' => "_blank")));
+      }
+      $rows[] = array($feature_name, $feature_uname, $type, $loc);
+    }
+    $table = array(
+      'header' => $headers,
+      'rows' => $rows,
+      'attributes' => array(
+        'id' => 'tripal_feature-table-transcripts-object',
+        'class' => 'tripal-data-table'
+      ),
+      'sticky' => FALSE,
+      'caption' => "",
+      'colgroups' => array(),
+      'empty' => 'This feature has no transcripts',
+    );
+    $content = theme_table($table);
+    
+    // once we have our table array structure defined, we call Drupal's theme_table()
+    // function to generate the table.
+    if (count($items) > 0) {
+      $element[0] = array(
+        '#type' => 'markup',
+        '#markup' => $content,
+      );
+    }
+  }
+}

+ 40 - 0
tripal_chado/includes/TripalFields/so__transcript_widget.inc

@@ -0,0 +1,40 @@
+<?php
+
+class so__transcript_widget extends TripalFieldWidget {
+  // The default lable for this field.
+  public static $label = 'Transcript';
+
+  // The list of field types for which this formatter is appropriate.
+  public static $field_types = array('so__transcript');
+
+  /**
+   *
+   * @see TripalFieldWidget::form()
+   */
+  public function form(&$widget, &$form, &$form_state, $langcode, $items, $delta, $element) {
+    parent::form($widget, $form, $form_state, $langcode, $items, $delta, $element);
+  }
+
+  /**
+   * Performs validation of the widgetForm.
+   *
+   * Use this validate to ensure that form values are entered correctly.  Note
+   * this is different from the validate() function which ensures that the
+   * field data meets expectations.
+   *
+   * @param $form
+   * @param $form_state
+   */
+  public function validate($form, &$form_state, $entity_type, $entity, $langcode, $delta) {
+
+  }
+
+
+  /**
+   *
+   * @see TripalFieldWidget::submit()
+   */
+  public function submit($form, &$form_state, $entity_type, $entity, $langcode, $delta) {
+
+  }
+}

+ 97 - 0
tripal_chado/includes/TripalFields/taxrank__infraspecific_taxon.inc

@@ -0,0 +1,97 @@
+<?php
+
+class taxrank__infraspecific_taxon extends TripalField {
+
+
+  // --------------------------------------------------------------------------
+  //                     EDITABLE STATIC CONSTANTS
+  //
+  // The following constants SHOULD be set for each descendent class.  They are
+  // used by the static functions to provide information to Drupal about
+  // the field and it's default widget and formatter.
+  // --------------------------------------------------------------------------
+
+  // The term that this field maps to.  The format for the term should be:
+  // [vocab]:[accession] where [vocab] is the short name of the vocabulary
+  // and [acession] is the unique accession number for the term.  This term
+  // must already exist in the vocabulary storage backend. This
+  // value should never be changed once fields exist for this type.
+  public static $term = 'TAXRANK:0000046';
+
+  // The default lable for this field.
+  public static $label = 'Infraspecific Taxon';
+
+  // The default description for this field.
+  public static $description = 'Specifies the infraspecific taxon of an organism.';
+
+  // Provide a list of global settings. These can be accessed witihn the
+  // globalSettingsForm.  When the globalSettingsForm is submitted then
+  // Drupal will automatically change these settings for all fields.
+  public static $settings = array(
+    'chado_table' => '',
+    'chado_column' => '',
+    'base_table' => '',
+  );
+
+  // Provide a list of instance specific settings. These can be access within
+  // the instanceSettingsForm.  When the instanceSettingsForm is submitted
+  // then Drupal with automatically change these settings for the instnace.
+  // It is recommended to put settings at the instance level whenever possible.
+  public static $instance_settings  = array();
+
+  // Set this to the name of the storage backend that by default will support
+  // this field.
+  public static $storage = 'tripal_no_storage';
+
+  // The default widget for this field.
+  public static $default_widget = 'HERE_widget';
+
+  // The default formatter for this field.
+  public static $default_formatter = 'HERE_formatter';
+
+  // --------------------------------------------------------------------------
+  //              PROTECTED CLASS MEMBERS -- DO NOT OVERRIDE
+  // --------------------------------------------------------------------------
+  // An array containing details about the field. The format of this array
+  // is the same as that returned by field_info_fields()
+  protected $field;
+  // An array containing details about an instance of the field. A field does
+  // not have to have an instance.  But if dealing with an instance (such as
+  // when using the widgetForm, formatterSettingsForm, etc.) it should be set.
+  protected $instance;
+
+
+  /**
+   *
+   * @see TripalField::validate()
+   */
+  public function validate($entity_type, $entity, $field, $items, &$errors) {
+
+  }
+
+
+  /**
+   *
+   * @see TripalField::load()
+   */
+  public function load($entity, $details = array()) {
+    $record = $details['record'];
+    $settings = $this->field['settings'];
+    
+    $field_name = $this->field['field_name'];
+    $field_type = $this->field['type'];
+    $field_table = $this->field['settings']['chado_table'];
+    $field_column = $this->field['settings']['chado_column'];
+    
+    // Set some defaults for the empty record.
+    $entity->{$field_name}['und'][0] = array(
+      'value' => '',
+      'organism__type_id' => '',
+    );
+    
+    if ($record->type_id) {
+      $entity->{$field_name}['und'][0]['value'] = $record->type_id->name;
+      $entity->{$field_name}['und'][0]['organism__type_id'] = $record->type_id->cvterm_id;
+    }
+  }
+}

+ 27 - 0
tripal_chado/includes/TripalFields/taxrank__infraspecific_taxon_formatter.inc

@@ -0,0 +1,27 @@
+<?php
+
+class taxrank__infraspecific_taxon_formatter extends TripalFieldFormatter {
+  // The default lable for this field.
+  public static $label = 'Infraspecific Taxon';
+
+  // The list of field types for which this formatter is appropriate.
+  public static $field_types = array('taxrank__infraspecific_taxon');
+
+  // The list of default settings for this formatter.
+  public static $settings = array();
+  /**
+   * 
+   * @see TripalFieldFormatter::settingsForm()
+   */
+  public function settingsForm($view_mode, $form, &$form_state) {
+
+  }
+
+  /**
+   * 
+   * @see TripalFieldFormatter::view()
+   */
+  public function view(&$element, $entity_type, $entity, $langcode, $items, $display) {
+
+  }
+}

+ 71 - 0
tripal_chado/includes/TripalFields/taxrank__infraspecific_taxon_widget.inc

@@ -0,0 +1,71 @@
+<?php
+
+class taxrank__infraspecific_taxon_widget extends TripalFieldWidget {
+  // The default lable for this field.
+  public static $label = 'Infraspecific Taxon';
+
+  // The list of field types for which this formatter is appropriate.
+  public static $field_types = array('taxrank__infraspecific_taxon');
+
+  /**
+   *
+   * @see TripalFieldWidget::form()
+   */
+  public function form(&$widget, &$form, &$form_state, $langcode, $items, $delta, $element) {
+    parent::form($widget, $form, $form_state, $langcode, $items, $delta, $element);
+    $settings = $this->field['settings'];
+    $field_name = $this->field['field_name'];
+    $field_type = $this->field['type'];
+    $field_table = $this->field['settings']['chado_table'];
+    $field_column = $this->field['settings']['chado_column'];
+    
+    $type_id = 0;
+    if (count($items) > 0 and array_key_exists('organism__type_id', $items[0])) {
+      $type_id = $items[0]['organism__type_id'];
+    }
+    
+    $form['value'] = array(
+      '#type' => 'value',
+      '#value' =>  array_key_exists($delta, $items) ? $items[$delta]['value'] : '',
+    );
+    
+    $cv = tripal_get_default_cv($field_table, $field_column);
+    $options = array();
+    if ($cv) {
+      $options = tripal_get_cvterm_select_options($cv->cv_id);
+    }
+    $widget['organism__type_id'] = array(
+      '#type' => 'select',
+      '#title' => $element['#title'],
+      '#description' => $element['#description'],
+      '#options' => $options,
+      '#default_value' => $type_id,
+      '#required' => $element['#required'],
+      '#weight' => isset($element['#weight']) ? $element['#weight'] : 0,
+      '#delta' => $delta,
+    );
+  }
+
+  /**
+   * Performs validation of the widgetForm.
+   *
+   * Use this validate to ensure that form values are entered correctly.  Note
+   * this is different from the validate() function which ensures that the
+   * field data meets expectations.
+   *
+   * @param $form
+   * @param $form_state
+   */
+  public function validate($form, &$form_state, $entity_type, $entity, $langcode, $delta) {
+
+  }
+
+
+  /**
+   *
+   * @see TripalFieldWidget::submit()
+   */
+  public function submit($form, &$form_state, $entity_type, $entity, $langcode, $delta) {
+
+  }
+}

+ 27 - 31
tripal_chado/includes/tripal_chado.fields.inc

@@ -278,12 +278,10 @@ function tripal_chado_bundle_create_fields_custom(&$info, $details, $entity_type
     );
   }
 
-  return;
-
   // FEATURE RESIDUES
   if ($table_name == 'feature') {
-    $field_name = 'feature__residues';
-    $field_type = 'chado_feature__residues';
+    $field_name = 'data__sequence';
+    $field_type = 'data__sequence';
     $info[$field_name] = array(
       'field_name' => $field_name,
       'type' => $field_type,
@@ -299,11 +297,11 @@ function tripal_chado_bundle_create_fields_custom(&$info, $details, $entity_type
       ),
     );
   }
-
+  
   // FEATURE SEQLEN
   if ($table_name == 'feature') {
-    $field_name = 'feature__seqlen';
-    $field_type = 'chado_feature__seqlen';
+    $field_name = 'data__sequence_length';
+    $field_type = 'data__sequence_length';
     $info[$field_name] = array(
       'field_name' => $field_name,
       'type' => $field_type,
@@ -323,8 +321,8 @@ function tripal_chado_bundle_create_fields_custom(&$info, $details, $entity_type
   // GENE TRANSCRIPTS
   $rel_table = $table_name . '_relationship';
   if (chado_table_exists($rel_table) and $bundle->label == 'gene') {
-    $field_name = 'gene_transcripts';
-    $field_type = 'chado_gene__transcripts';
+    $field_name = 'so__transcript';
+    $field_type = 'so__transcript';
     $info[$field_name] = array(
       'field_name' => $field_name,
       'type' => $field_type,
@@ -335,7 +333,7 @@ function tripal_chado_bundle_create_fields_custom(&$info, $details, $entity_type
       ),
       'settings' => array(
         'chado_table' => $rel_table,
-        'chado_column' => 'md5checksum',
+        'chado_column' => '',
         'base_table' => $table_name,
         'semantic_web' => 'SO:0000673',
       ),
@@ -344,8 +342,8 @@ function tripal_chado_bundle_create_fields_custom(&$info, $details, $entity_type
 
   // ORGANISM TYPE_ID
   if ($table_name == 'organism' and array_key_exists('type_id', $schema['fields'])) {
-    $field_name = 'organism__type_id';
-    $field_type = 'chado_organism__type_id';
+    $field_name = 'taxarank__infraspecific_taxon';
+    $field_type = 'taxarank__infraspecific_taxon';
     $info[$field_name] = array(
       'field_name' => $field_name,
       'type' => $field_type,
@@ -357,7 +355,7 @@ function tripal_chado_bundle_create_fields_custom(&$info, $details, $entity_type
       'settings' => array(
         'chado_table' => 'organism',
         'chado_column' => 'type_id',
-        'semantic_web' => tripal_get_chado_semweb_term('organism', 'type_id'),
+        'semantic_web' => 'TAXRANK:0000046',
       ),
     );
   }
@@ -984,11 +982,9 @@ function tripal_chado_bundle_create_instances_custom(&$info, $entity_type, $bund
     );
   }
 
-  return;
-
   // FEATURE RESIDUES
   if ($table_name == 'feature') {
-    $field_name = 'feature__residues';
+    $field_name = 'data__sequence';
     $info[$field_name] = array(
       'field_name' => $field_name,
       'entity_type' => $entity_type,
@@ -1000,7 +996,7 @@ function tripal_chado_bundle_create_instances_custom(&$info, $entity_type, $bund
         'auto_attach' => FALSE,
       ),
       'widget' => array(
-        'type' => 'chado_feature__residues_widget',
+        'type' => 'data__sequence_widget',
         'settings' => array(
           'display_label' => 1,
         ),
@@ -1008,7 +1004,7 @@ function tripal_chado_bundle_create_instances_custom(&$info, $entity_type, $bund
       'display' => array(
         'default' => array(
           'label' => 'above',
-          'type' => 'chado_feature__residues_formatter',
+          'type' => 'data__sequence_formatter',
           'settings' => array(),
         ),
       ),
@@ -1017,12 +1013,12 @@ function tripal_chado_bundle_create_instances_custom(&$info, $entity_type, $bund
 
   // FEATURE SEQLEN
   if ($table_name == 'feature') {
-    $field_name = 'feature__seqlen';
+    $field_name = 'data__sequence_length';
     $info[$field_name] = array(
       'field_name' => $field_name,
       'entity_type' => $entity_type,
       'bundle' => $bundle->name,
-      'label' => 'Raw Sequence Length',
+      'label' => 'Sequence Length',
       'description' => 'The number of residues in the raw sequence.  This length
         is only for the assigned raw sequence and does not represent the length of any
         sequences derived from alignments. If this value is zero but aligned sequences
@@ -1032,7 +1028,7 @@ function tripal_chado_bundle_create_instances_custom(&$info, $entity_type, $bund
         'auto_attach' => TRUE,
       ),
       'widget' => array(
-        'type' => 'chado_feature__seqlen_widget',
+        'type' => 'data__sequence_length_widget',
         'settings' => array(
           'display_label' => 1,
         ),
@@ -1040,7 +1036,7 @@ function tripal_chado_bundle_create_instances_custom(&$info, $entity_type, $bund
       'display' => array(
         'default' => array(
           'label' => 'inline',
-          'type' => 'chado_feature__seqlen_formatter',
+          'type' => 'data__sequence_length_formatter',
           'settings' => array(),
         ),
       ),
@@ -1050,19 +1046,19 @@ function tripal_chado_bundle_create_instances_custom(&$info, $entity_type, $bund
   // GENE TRANSCRIPTS
   $rel_table = $table_name . '_relationship';
   if (chado_table_exists($rel_table) and $bundle->label == 'gene') {
-    $field_name = 'gene_transcripts';
+    $field_name = 'so__transcript';
     $info[$field_name] = array(
       'field_name' => $field_name,
       'entity_type' => $entity_type,
       'bundle' => $bundle->name,
-      'label' => 'Transcripts',
+      'label' => 'Transcript',
       'description' => 'These transcripts are associated with this gene.',
       'required' => FALSE,
       'settings' => array(
         'auto_attach' => FALSE,
       ),
       'widget' => array(
-        'type' => 'chado_gene__transcripts_widget',
+        'type' => 'so__transcript_widget',
         'settings' => array(
           'display_label' => 1,
         ),
@@ -1070,7 +1066,7 @@ function tripal_chado_bundle_create_instances_custom(&$info, $entity_type, $bund
       'display' => array(
         'default' => array(
           'label' => 'above',
-          'type' => 'chado_gene__transcripts_formatter',
+          'type' => 'so__transcript_formatter',
           'settings' => array(),
         ),
       ),
@@ -1079,19 +1075,19 @@ function tripal_chado_bundle_create_instances_custom(&$info, $entity_type, $bund
 
   // ORGANISM TYPE_ID
   if ($table_name == 'organism' and array_key_exists('type_id', $schema['fields'])) {
-    $field_name = 'organism__type_id';
+    $field_name = 'taxarank__infraspecific_taxon';
     $info[$field_name] = array(
       'field_name' => $field_name,
       'entity_type' => $entity_type,
       'bundle' => $bundle->name,
-      'label' => 'Infraspecific Type',
-      'description' => 'The Infraspecific Type.',
+      'label' => 'Infraspecific Taxon',
+      'description' => 'The Infraspecific Taxon.',
       'required' => FALSE,
       'settings' => array(
         'auto_attach' => TRUE,
       ),
       'widget' => array(
-        'type' => 'chado_organism__type_id_widget',
+        'type' => 'taxarank__infraspecific_taxon_widget',
         'settings' => array(
           'display_label' => 1,
         ),
@@ -1099,7 +1095,7 @@ function tripal_chado_bundle_create_instances_custom(&$info, $entity_type, $bund
       'display' => array(
         'default' => array(
           'label' => 'inline',
-          'type' => 'chado_organism__type_id_formatter',
+          'type' => 'taxarank__infraspecific_taxon_formatter',
           'settings' => array(),
         ),
       ),