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