7 Isaak Y Tecle (iyt2@cornell.edu)
16 use CXGN
::People
::PageComment
;
17 use CXGN
::Phenome
::Population
;
18 use CXGN
::Phenome
::UserTrait
;
19 use CXGN
::Phenome
::Qtl
;
22 use CXGN
::DB
::Connection
;
23 use CXGN
::Chado
::Cvterm
;
24 use List
::MoreUtils qw
/ uniq /;
25 use List
::Util qw
/ max min/;
26 use File
::Slurp qw
/ read_file /;
31 use CatalystX
::GlobalContext
qw( $c );
34 my %params = $cgi->Vars();
36 our $pop_id = $params{population_id};
37 our $trait_id = $params{term_id};
38 our $lg = $params{chr};
39 our $p_m = $params{peak_marker};
40 our $lod = $params{lod};
41 our $qtl_image = $params{qtl};
49 die 'QTL detail page error: A required argument is missing';
54 our $dbh = CXGN::DB::Connection->new();
55 our $pop = CXGN::Phenome::Population->new($dbh, $pop_id);
56 our $pop_name = $pop->get_name();
57 our $trait_name = trait_name();
58 our ($ci_table, $marker_details) = confidence_interval();
60 foreach my $k (keys %$marker_details) {
61 $l_m = $k if ($marker_details->{$k}{orientation} eq 'left');
62 $r_m = $k if ($marker_details->{$k}{orientation} eq 'right');
65 my $genetic_link = genetic_map();
66 my $cmv_link = marker_positions();
67 my $markers = markers();
68 my $legend = legend();
69 my $comment = comment();
70 my $download_qtl = download_qtl_region();
71 $ci_table = order_by_position();
73 $c->forward_to_mason_view( '/qtl/qtl/index.mas',
74 qtl_image => $qtl_image,
75 pop_name => $pop_name,
76 trait_name => $trait_name,
77 cmv_link => $cmv_link,
79 marker_link => $ci_table,
80 genetic_map => $genetic_link,
82 download => $download_qtl,
88 =head2 marker_positions
90 Usage: $map_viewer = marker_positions();
91 Desc: generates a link to the comparative map viewer page
92 using the flanking markers and peak marker.
93 Ret: a link to the map viewer page
103 my $mapv_id = $pop->mapversion_id();
104 my $l_m_pos = $marker_details->{$l_m}{position};
105 my $p_m_pos = $marker_details->{$p_m}{position};
106 my $r_m_pos = $marker_details->{$r_m}{position};
109 = qq |<a href="../cview/view_chromosome.pl?map_version_id=$mapv_id&chr_nr=$lg&show_ruler=1&show_IL=&show_offsets=1&comp_map_version_id=&comp_chr=&color_model=&show_physical=&size=&show_zoomed=1&confidence=-2&hilite=$l_m+$p_m+$r_m&marker_type=&cM_start=$l_m_pos&cM_end=$r_m_pos">Chromosome $lg ($l_m, $r_m)</a> |;
116 Usage: $markers = markers();
117 Desc: creates marker objects
118 Ret: array ref of marker objects
128 my @mrs = uniq ($l_m, $p_m, $r_m);
131 foreach my $mr (@mrs)
133 push @markers, CXGN::Marker->new_with_name($dbh, $mr);
142 Usage: $population_map = genetic_map();
143 Desc: generates a link to the genetic map of the
145 Ret: a link to the genetic map
155 my $mapv_id = $pop->mapversion_id();
156 my $map = CXGN::Map->new( $dbh, { map_version_id => $mapv_id } );
157 my $map_name = $map->get_long_name();
158 my $map_sh_name = $map->get_short_name();
160 = qq | <a href=/cview/map.pl?map_version_id=$mapv_id&hilite=$l_m+$p_m+$r_m>$map_name ($map_sh_name)</a>|;
166 =head2 confidence_interval
168 Usage: ($marker_table, $marker_details) = confidence_interval();
169 Desc: reads the confidence interval data for the QTL from a
170 file containing the genome-wide confidence intervals
171 and their lod profile. It calculates the left and right
172 markers, their position values; and some interpretation of
174 Ret: an array ref of marker details table (for the viewer)
175 and a ref to a hash of hash for the marker details
176 (for later access to the data)
185 sub confidence_interval
187 my $ci_lod_file = $pop->ci_lod_file( $c,
188 $pop->cvterm_acronym( $trait_name )
191 my (@marker_lods, @all_lods, @all_positions, @marker_html);
192 my %marker_details_of = ();
194 my @rows = grep { /\t$lg\t/ } read_file( $ci_lod_file );
196 my $rnd = Number::Format->new();
198 foreach my $row (@rows) {
199 my ( $m, $m_chr, $m_pos, $m_lod ) = split (/\t/, $row);
200 push @all_lods, $m_lod;
201 push @all_positions, $m_pos;
203 my $marker = CXGN::Marker->new_with_name( $dbh, $m );
207 push @marker_lods, $m_lod;
211 my $peak_marker_lod = $rnd->round(max( @marker_lods), 2 );
212 my $highest_lod = $rnd->round(max( @all_lods), 2 );
213 my $right_position = $rnd->round(max( @all_positions), 2 );
214 my $left_position = $rnd->round(min( @all_positions), 2 );
216 my ($peak_marker, $linkage_group, $peak_position) = split (/\t/, $rows[1]);
217 $peak_position = $rnd->round($peak_position, 1);
219 foreach my $row ( @rows )
221 my ($m, $m_chr, $m_pos, $m_lod) = split (/\t/, $row);
222 $m_pos = $rnd->round( $m_pos, 1 );
223 $m_lod = $rnd->round( $m_lod, 2 );
225 my $marker = CXGN::Marker->new_with_name( $dbh, $m );
230 $marker_details_of{$m}{name} = $m;
231 $marker_details_of{$m}{linkage_group} = $m_chr;
233 $marker_details_of{$m}{position} = !$m_pos && $m_pos ne '' ? '0.0'
234 : $m_pos eq '' ? 'NA'
238 $marker_details_of{$m}{lod_score} = $m_lod;
240 if ($m eq $p_m) { $marker_details_of{$m}{orientation} = 'peak'; }
241 if ($m_pos == $right_position) { $marker_details_of{$m}{orientation} = 'right'; }
242 if ($m_pos == $left_position) { $marker_details_of{$m}{orientation} = 'left'; }
244 my $m_id = $marker->marker_id();
245 my $remark1 = "<i>Highest LOD score is $highest_lod at $peak_position cM</i>." if $m_lod == $peak_marker_lod;
246 my $remark2 = "<i>The closest marker to the peak position ($peak_position cM)</i>." if $m eq $p_m;
251 qq | <a href="/search/markers/markerinfo.pl?marker_id=$m_id">$m</a>|,
252 $marker_details_of{$m}{position},
261 return \@marker_html, \%marker_details_of;
267 Usage: $trait_name = trait_name()
268 Desc: returns the name of the QTL trait
279 my ( $term_obj, $term_name, $term_id );
280 if ( $pop->get_web_uploaded() )
282 $term_obj = CXGN::Phenome::UserTrait->new( $dbh, $trait_id );
283 $term_name = $term_obj->get_name();
284 $term_id = $term_obj->get_user_trait_id();
288 $term_obj = CXGN::Chado::Cvterm->new( $dbh, $trait_id );
289 $term_name = $term_obj->get_cvterm_name();
290 $term_id = $term_obj->get_cvterm_id();
298 Usage: $legend = legend();
299 Desc: generates the appropriate legend describing the
300 statistical methods and parameters used for the
314 $user_id = $c->user->get_object->get_sp_person_id;
316 $user_id = $pop->get_sp_person_id();
319 my $qtl = CXGN::Phenome::Qtl->new( $user_id );
320 my $user_stat_file = $qtl->get_stat_file( $c, $pop_id );
324 open my $uf, "<", $user_stat_file or die "$! reading $user_stat_file";
325 while ( my $row = <$uf> )
328 my ( $parameter, $value ) = split( /\t/, $row );
330 if ( $parameter =~ /qtl_method/ )
332 $parameter = 'Mapping method';
334 if ( $parameter =~ /qtl_model/ )
336 $parameter = 'Mapping model';
338 if ( $parameter =~ /prob_method/ )
340 $parameter = 'QTL genotype probability method';
342 if ( $parameter =~ /step_size/ )
344 $parameter = 'Genome scan size (cM)';
346 if ( $parameter =~ /permu_level/ )
348 $parameter = 'Permutation significance level';
350 if ( $parameter =~ /permu_test/ ) {
351 $parameter = 'No. of permutations';
353 if ( $parameter =~ /prob_level/ )
355 $parameter = 'QTL genotype significance level';
357 if ( $parameter =~ /stat_no_draws/ )
359 $parameter = 'No. of imputations';
361 if ( $value eq 'zero' || $value eq 'Marker Regression' )
366 unless ( ( $parameter =~ /No. of imputations/ && !$value )
367 || ( $parameter =~ /QTL genotype probability/ && !$value )
368 || ( $parameter =~ /Permutation significance level/ && !$value ) )
371 push @stat, [ $parameter, $value ];
376 foreach my $st ( @stat )
378 foreach my $i ( @$st )
382 foreach my $s ( @stat )
386 $j =~ s/Maximum Likelihood/Marker Regression/;
396 $lod = qq |<i>Not calculated</i>|;
399 push @stat, [ map {$_} ( 'LOD threshold', $lod ) ];
404 [ map {$_} ( 'Confidence interval',
405 'Based on 95% Bayesian Credible Interval'
415 sub download_qtl_region
417 my $link = qq | <a href="https://www.eu-sol.wur.nl/marker2seq/marker2seq.do?marker1=$l_m&marker2=$r_m">View/download</a> genetic markers in the tomato F2.2000 reference map region (+5cM) matching the QTL region and gene models from the ITAG annotated tomato genome. |;
419 $link .= qq | <p><i>Courtesy of</i> <a href="http://www.eu-sol.wur.nl"><img src ="/img/eusol_logo_small.jpg"/></a></p> |;
428 Usage: $comment = comment();
429 Desc: generates the comment section html
430 Ret: the comment html
443 my $page_comment_obj =
444 CXGN::People::PageComment->new( $dbh, "population", $pop_id,
445 "/phenome/qtl.pl?population_id=$pop_id" );
446 $comment = $page_comment_obj->get_html();
453 sub order_by_position {
454 my ($marker_html, $markers_details) = confidence_interval();
455 my @marker_html = sort { $a->[1] <=> $b->[1] } @$marker_html;
456 return \@marker_html;