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