1 package SGN
::View
::Feature
;
7 use CXGN
::Tools
::Text qw
/commify_number/;
8 use CXGN
::Tools
::Identifiers
;
12 related_stats feature_table
14 infer_residue cvterm_link
15 organism_link feature_length
16 mrna_and_protein_sequence
17 description_featureprop_types
21 location_string_with_strand
26 cvterm_name
( shift->type, @_ );
30 my ($cvt, $caps) = @_;
31 ( my $n = $cvt->name ) =~ s/_/ /g;
33 $n =~ s/(\S+)/lc($1) eq $1 ? ucfirst($1) : $1/e;
38 sub description_featureprop_types
{
39 shift->result_source->schema
40 ->resultset('Cv::Cvterm')
43 'functional_description',
54 description_featureprop_types
( $feature )
55 ->get_column('cvterm_id')
59 $feature->search_related('featureprops', {
60 type_id
=> { -in => $desc_types },
61 })->get_column('value')
64 return unless $description;
66 $description =~ s/(\S+)/my $id = $1; CXGN::Tools::Identifiers::link_identifier($id) || $id/ge;
72 my ($feature, $featurelocs) = @_;
73 my @locations = $featurelocs ?
$featurelocs->all : $feature->featureloc_features->all;
74 my $locations = scalar @locations;
76 for my $l (@locations) {
77 $length += $l->fmax - $l->fmin;
79 # Reference features don't have featureloc's, calculate the length
82 $length = $feature->seqlen,
84 return ($length,$locations);
88 my ( $id, $start, $end, $strand ) = @_;
91 $id = feature_link
($loc->srcfeature);
92 $start = $loc->fmin+1;
94 $strand = $loc->strand;
96 ( $start, $end ) = ( $end, $start ) if $strand && $strand == -1;
97 return "$id:$start..$end";
100 sub location_string_with_strand
{
101 location_string
( @_ )
104 sub location_list_html
{
105 my ($feature, $featurelocs) = @_;
106 my @coords = map { location_string
($_) }
107 ( $featurelocs ?
$featurelocs->all
108 : $feature->featureloc_features->all)
109 or return '<span class="ghosted">none</span>';
113 my ($feature, $featurelocs) = @_;
114 return map { $_->srcfeature->name . ':' . ($_->fmin+1) . '..' . $_->fmax }
115 ( $featurelocs ?
$featurelocs->all
116 : $feature->featureloc_features->all );
122 my $total = scalar @
$features;
123 for my $f (@
$features) {
124 $stats->{cvterm_link
($f->type)}++;
127 for my $k (sort keys %$stats) {
128 push @
$data, [ $stats->{$k}, $k ];
130 if( 1 < scalar keys %$stats ) {
131 push @
$data, [ $total, "<b>Total</b>" ];
139 for my $f (@
$features) {
140 my @locations = $f->featureloc_features->all;
142 # Add a row for every featureloc
143 for my $loc (@locations) {
144 my ($start,$end) = ($loc->fmin+1, $loc->fmax);
146 cvterm_link
($f->type),
149 commify_number
( $end-$start+1 ) . " bp",
150 $loc->strand == 1 ?
'+' : '-',
151 $loc->phase || '<span class="ghosted">n/a</span>',
158 sub _feature_search_string
{
160 my ($fl) = $feature->featureloc_features;
161 return '' unless $fl;
162 return $fl->srcfeature->name . ':'. ($fl->fmin+1) . '..' . $fl->fmax;
166 ### XXX TODO: A lot of these _link and sequence functions need to be
167 ### moved to controller code.
171 return '<span class="ghosted">null</span>' unless $feature;
172 my $id = $feature->feature_id;
173 my $name = $feature->name;
174 return qq{<a href
="/feature/view/id/$id">$name</a
>};
179 my $id = $organism->organism_id;
180 my $species = $organism->species;
181 return qq{<a
class="species_binomial" href
="/chado/organism.pl?organism_id=$id">$species</a
>};
185 my ( $cvt, $caps ) = @_;
186 my $name = cvterm_name
( $cvt, $caps );
188 return qq{<a href
="/chado/cvterm.pl?cvterm_id=$id">$name</a
>};
191 sub mrna_and_protein_sequence
{
192 my ($mrna_feature) = @_;
193 my @exon_locations = _exon_rs
( $mrna_feature )->all
196 my $mrna_seq = Bio
::PrimarySeq
->new(
197 -id
=> $mrna_feature->name,
198 -desc
=> 'spliced cDNA sequence',
199 -seq
=> join( '', map {
200 $_->srcfeature->subseq( $_->fmin+1, $_->fmax ),
205 my $peptide_loc = _peptides_rs
( $mrna_feature )->first
206 or return ( $mrna_seq, undef );
208 my $trim_fmin = $peptide_loc->fmin - $exon_locations[0]->fmin;
209 my $trim_fmax = $exon_locations[-1]->fmax - $peptide_loc->fmax;
210 if( $trim_fmin || $trim_fmax ) {
211 $mrna_seq = $mrna_seq->trunc( 1+$trim_fmin, $mrna_seq->length - $trim_fmax );
214 $mrna_seq = $mrna_seq->revcom if $exon_locations[0]->strand == -1;
216 my $protein_seq = Bio
::PrimarySeq
->new(
217 -id
=> $mrna_feature->name,
218 -desc
=> 'protein sequence',
219 -seq
=> $mrna_seq->seq,
221 $protein_seq = $protein_seq->translate;
223 return ( $mrna_seq, $protein_seq );
227 my ( $mrna_feature ) = @_;
230 ->feature_relationship_objects({
232 -in => _cvterm_rs
( $mrna_feature, 'relationship', 'derives_from' )
233 ->get_column('cvterm_id')
237 ->search_related( 'subject', {
238 'subject.type_id' => {
239 -in => _cvterm_rs
( $mrna_feature, 'sequence', 'polypeptide' )
240 ->get_column('cvterm_id')
244 ->search_related( 'featureloc_features', {
245 srcfeature_id
=> { -not => undef },
247 { prefetch
=> 'srcfeature',
254 my ( $mrna_feature ) = @_;
257 ->feature_relationship_objects({
259 -in => _cvterm_rs
( $mrna_feature, 'relationship', 'part_of' )
260 ->get_column('cvterm_id')
267 ->search_related( 'subject', {
268 'subject.type_id' => {
269 -in => _cvterm_rs
( $mrna_feature, 'sequence', 'exon' )
270 ->get_column('cvterm_id')
275 prefetch
=> 'featureloc_features',
277 ->search_related( 'featureloc_features', {
278 srcfeature_id
=> { -not => undef },
281 prefetch
=> 'srcfeature',
288 my ( $row, $cv, $cvt ) = @_;
290 return $row->result_source->schema
291 ->resultset('Cv::Cv')
292 ->search({ 'me.name' => $cv })
293 ->search_related('cvterms', {
294 'cvterms.name' => $cvt,