#!/tools32/bin/perl
#!/usr/local/bin/perl
BEGIN {
push @INC, qw( /net/db/src/SSRCalc/ssrcalc . /tools32/lib/perl5/5.8.0/i386-linux-thread-multi /tools32/lib/perl5/5.8.0 /tools32/lib/perl5/site_perl/5.8.0/i386-linux-thread-multi /tools32/lib/perl5/site_perl/5.8.0 /tools32/lib/perl5/site_perl );
}
###############################################################################
# Program : ShowOneSpectrum.cgi
#
# Description : This CGI program recieves consensus_library_spectrum_id and plots it.
# Has feedback loop for changing plot.
#
# Based upon the ShowSpectrum.cgi in the Proteomics module by
# Kerry & Eric Deutsch
#
###############################################################################
###############################################################################
# Basic SBEAMS setup
###############################################################################
use strict;
use FindBin;
use lib "$FindBin::Bin/../../lib/perl";
use lib '/tools32/lib/perl5/5.8.0/i386-linux-thread-multi';
use lib '/tools32/lib/perl5/5.8.0';
use lib '/tools32/lib/perl5/site_perl/5.8.0/i386-linux-thread-multi';
use lib '/tools32/lib/perl5/site_perl/5.8.0';
use lib '/tools32/lib/perl5/site_perl';
use vars qw ($q $sbeams $sbeamsMOD $PROG_NAME
$current_username $modification_helper );
use SBEAMS::Connection qw($q $log);
use SBEAMS::Connection::Settings;
use SBEAMS::Connection::Tables;
use SBEAMS::PeptideAtlas;
use SBEAMS::PeptideAtlas::Settings;
use SBEAMS::PeptideAtlas::Tables;
use SBEAMS::PeptideAtlas::ModificationHelper;
use SBEAMS::PeptideAtlas::ConsensusSpectrum;
use PGPLOT;
use PDL;
use PDL::Graphics::PGPLOT;
use File::Basename;
my $denormalize = 1;
my $curveType = 'function';
my $error_state = 0;
$sbeams = new SBEAMS::Connection;
$sbeamsMOD = new SBEAMS::PeptideAtlas;
$sbeamsMOD->setSBEAMS($sbeams);
my $consensus = new SBEAMS::PeptideAtlas::ConsensusSpectrum;
$consensus->setSBEAMS($sbeams);
$PROG_NAME="ShowOneSpectrum";
###############################################################################
# Define global variables if any and execute main()
###############################################################################
my $ymax = 10;
main();
###############################################################################
# Main Program:
#
# If $sbeams->Authenticate() succeeds, print header, process the CGI request,
# print the footer, and end.
###############################################################################
sub main {
#### Do the SBEAMS authentication and exit if a username is not returned
exit unless ($current_username = $sbeams->Authenticate(
permitted_work_groups_ref=>['PeptideAtlas_user','PeptideAtlas_admin',
'PeptideAtlas_readonly', 'PeptideAtlas_exec'],
#connect_read_only=>1,
allow_anonymous_access=>1,
));
#### Print the header, figure and do what the user want, and print footer
my %parameters;
$sbeams->parse_input_parameters(q=>$q,parameters_ref=>\%parameters);
$sbeams->processStandardParameters(parameters_ref=>\%parameters);
$denormalize = 0 if $parameters{normalize};
$curveType = $parameters{curveType} if $parameters{curveType};
my %results;
my $ce_vals;
my $has_median = 0;
my $max_intensity = 0;
# First, grab da peaks
use Data::Dumper;
for my $ce ( qw( low mlow medium mhigh high avg ) ) {
my $ce_results = mk_plot( %parameters, ce => $parameters{$ce} );
next unless $ce_results->{max_intensity};
# Going to base peaks to watch on this guy...
$has_median++ if $ce eq 'medium';
$ce_vals ||= $sbeamsMOD->get_Agilent_ce( %{$ce_results} );
$ce_results->{ce} = $ce_vals->{$ce};
$ce_results->{level} = ucfirst($ce);
$parameters{modified_sequence} = $ce_results->{modified_sequence};
$parameters{charge} = $ce_results->{charge};
$max_intensity = $ce_results->{max_intensity} if $ce_results->{max_intensity} > $max_intensity;
$results{spectra} ||= {};
$results{spectra}->{$ce} = $ce_results;
}
# This has to go into the header
my $peak_plot = '';
if ( $has_median ) {
my $num_ions = get_num_ions( $parameters{modified_sequence} );
my $chart_data = get_top_peaks( \%results, $num_ions );
# Trying to get CE and spectra plots on same scale...
$parameters{ymax} = $ymax * 1.075;
$peak_plot = get_chart( data => $chart_data,seq => $parameters{modified_sequence}, chg => $parameters{charge} );
}
# The plot them, now that we know the scale
for my $ce ( qw( low mlow medium mhigh high ) ) {
next unless $results{spectra}->{$ce};
my $plot_results = mk_plot( %parameters, ce => $parameters{$ce}, spectrum => $results{spectra}->{$ce} );
$results{$ce}->{image} = $plot_results->{image};
$results{$ce}->{lib_desc} = $plot_results->{lib_desc};
$results{$ce}->{modified_sequence} = $plot_results->{modified_sequence};
$results{$ce}->{charge} = $plot_results->{charge};
$results{$ce}->{mz} = $plot_results->{precursor_mass};
}
my $content = "
\n";
$content .= " |
\n";
$content .= "Spectra for $parameters{modified_sequence} +$parameters{charge} |
\n";
for my $ce ( qw( low mlow medium mhigh high avg ) ) {
next unless $results{$ce};
$content .= " |
\n";
$content .= "CE: $results{spectra}->{$ce}->{ce}, Level: $results{spectra}->{$ce}->{level}, Library: $results{$ce}->{lib_desc} |
\n";
}
$content .= "
\n";
$sbeamsMOD->display_page_header( header_info => $peak_plot );
print $content;
$sbeamsMOD->display_page_footer();
$sbeams->display_page_footer(close_tables=>'YES',
separator_bar=>'YES',display_footer=>'NO');
} # end main
sub mk_plot {
my %parameters = @_;
$parameters{consensus_library_spectrum_id} = $parameters{ce};
my %results = ( image => '', lib_desc => '' );
return \%results unless $parameters{ce};
#### Define some general variables
my ($i,$element,$key,$value,$sql);
my $apply_action = $q->param('apply_action');
my @charge;
push (@charge, 1);
push (@charge, 2);
push (@charge, 3);
$parameters{'ionlab'} = "Horizontal" unless $parameters{'ionlab'};
my ($labangle,$fjust);
if ($parameters{'ionlab'} eq "Vertical") {
$labangle = 90;
$fjust = 0;
} else {
$labangle = 0;
$fjust = 0.5;
}
my $sql = qq~
SELECT sequence,charge,mz_exact,protein_name,
protein_name_alt,modified_sequence, consensus_library_name, file_path, entry_idx
FROM $TBAT_CONSENSUS_LIBRARY_SPECTRUM CLS
JOIN $TBAT_CONSENSUS_LIBRARY CL ON CL.consensus_library_id = CLS.consensus_library_id
WHERE consensus_library_spectrum_id = '$parameters{consensus_library_spectrum_id}'
~;
my @rows = $sbeams->selectSeveralColumns($sql);
foreach my $row (@rows) {
my ($seq, $chg, $mz, $pn, $pn_alt, $mod_seq, $lib_name, $file_path, $entry_idx ) = @{$row};
$parameters{'peptide'} = $seq;
$parameters{'charge'} = $chg;
$parameters{'precursor_mass'} = $mz;
$parameters{'protein_name'} = $pn;
$parameters{'protein_name_alt'} = $pn_alt;
$parameters{'modified_sequence'} = $mod_seq;
$parameters{'library_name'} = $lib_name;
$parameters{'file_path'} = $file_path;
$parameters{'entry_idx'} = $entry_idx;
}
$results{modified_sequence} = $parameters{modified_sequence};
$results{charge} = $parameters{charge};
$results{mz} = $parameters{'precursor_mass'};
$results{lib_desc} = "$parameters{library_name}";
$results{lib_desc} =~ s/\.sptxt//;
my $peptide = $parameters{peptide};
$peptide =~ s/^.\.//;
$peptide =~ s/\..$//;
my $precursor_mass = $parameters{'precursor_mass'};
my $charge = $parameters{'charge'};
my $protein_name = $parameters{'protein_name'};
my $protein_name_alt = $parameters{'protein_name_alt'};
my $modified_sequence = $parameters{'modified_sequence'};
$parameters{assumed_charge} = $charge;
## if no modified_sequence, use unmodified sequence
unless ($modified_sequence) {
$modified_sequence = $parameters{peptide};
}
#### Calculate peptide mass information
my $masstype = $parameters{masstype} || 0;
$modification_helper = new SBEAMS::PeptideAtlas::ModificationHelper();
if ( !$parameters{spectrum} ) {
my $peaks = $consensus->get_spectrum_peaks( %parameters, denormalize => 1 );
$peaks->{mz} = $results{mz};
$peaks->{modified_sequence} = $results{modified_sequence};
$peaks->{charge} = $results{charge};
return $peaks;
}
my %spectrum = %{$parameters{spectrum}};
unless (%spectrum) {
$error_state++;
return \%results;
}
my ($i,$mass,$intensity,$massmin,$xticks);
my ($massmax,$intenmax)=(0,0);
my @spectrum_array;
for ($i=0; $i<$spectrum{n_peaks}; $i++) {
$mass = $spectrum{masses}->[$i];
$intensity = $spectrum{intensities}->[$i];
push(@spectrum_array,[$mass,$intensity]);
$massmin = $mass if ($i == 0);
$massmax = $mass if ($mass > $massmax);
$intenmax = $intensity if ($intensity > $intenmax);
}
#### Compute data and plot bounds
$parameters{xmin} = int($massmin/100)*100 unless $parameters{xmin};
$parameters{xmax} = int($massmax/100)*100+100 unless $parameters{xmax};
$parameters{ymax} ||= $intenmax + 600;
$ymax = $parameters{ymax};
if ($q->param("reset") eq "ZOOM OUT") {
$parameters{xmin} = int($massmin/100)*100;
$parameters{xmax} = int($massmax/100)*100+100;
}
my $maxval = $intenmax;
my $interval = $parameters{ymax} / 20;
my $interval_power = int( log($interval) / log(10) );
my $roundval = 10**$interval_power;
$parameters{ymax} = int( $parameters{ymax} /$roundval)*$roundval;
my $ydiv = $parameters{ymax} / 5;
#### Calculate fragment ions for the given peptide
my @residues = Fragment($peptide);
my $length = $#residues + 1;
#### Initialize the plot environment
my($progname)= basename $0;
#my($tmpfile) = "$progname.$$.@{[time]}.gif";
#### Reduce length because of PGPLOT 80 char limit??
my($tmpfile) = "Spec.$$.@{[time]}.$parameters{ce}.gif";
$parameters{gifwidth} = 800 unless $parameters{gifwidth};
$parameters{gifheight} = 400 unless $parameters{gifheight};
if ($apply_action eq "PRINTABLE FORMAT") {
$parameters{gifwidth} = 480;
$parameters{gifheight} = 384;
}
#print "Writing GIF to: $PHYSICAL_BASE_DIR/tmp/images/$tmpfile\n";
my $win = pg_setup(Device=>"$PHYSICAL_BASE_DIR/tmp/images/$tmpfile/gif",
title=>"$modified_sequence",
xmin=>$parameters{xmin}, xmax=>$parameters{xmax},
ymax=>$parameters{ymax}, ydiv=>$ydiv, nyticks=>5,
gifwidth=>$parameters{gifwidth},
gifheight=>$parameters{gifheight}
);
pgsch 0.9;
pgmtext 'T',0.7,.01,0,"Peak value = $maxval";
# pgmtext 'RV',-2,1.02,1,"Assumed charge = $parameters{assumed_charge}";
pgmtext 'RV',-2,1.02,1,"Charge = $parameters{charge}";
my @peakcolors;
my @theoretical_spectrum;
#### Loop over each desired charge
my $charge;
foreach $charge (@charge) {
my ($masslist_ref) = CalcIons(Residues=>\@residues, Charge=>$charge,
modified_sequence=>$modified_sequence);
my ($B_ref,$Y_ref);
#### Make the plot
($win,$B_ref,$Y_ref) = PlotPeaks(SpecData=>\%spectrum,
Masslist=>$masslist_ref, Charge=>$charge,
Win=>$win, Length=>$length,
PeakColors=>\@peakcolors);
#### Print out the peptide ion information
printIons(masslist_ref=>$masslist_ref,color=>1,html=>1,
charge=>$charge,length=>$length,
theoretical_spectrum_ref=>\@theoretical_spectrum);
#### Label the peaks on the plot
LabelResidues(Ionmasses=>$masslist_ref, Binten=>$B_ref, Yinten=>$Y_ref,
Charge=>$charge, Win=>$win, Length=>$length,
Xmin=>$parameters{xmin}, Xmax=>$parameters{xmax},
Ymax=>$parameters{ymax}, Angle=>$labangle, Fjust=>$fjust);
} # end foreach
#### Draw Precursor mass symbol
if ($parameters{precursor_mass}) {
pgsci 2; #### Default color
pgsch 2; #### Character size
pgslw 5; #### Line thinkness
pgsclp(0); #### Disable clipping
pgpt(1,$parameters{precursor_mass},-0.34 * $interval,7);
pgsch 1; #### Character size
pgpt(1,$parameters{precursor_mass},-0.34 * $interval,7);
}
#### Finish and close the plot
$win->close();
$results{image} = "$HTML_BASE_DIR/tmp/images/$tmpfile";
return \%results;
} # end printEntryForm
sub get_top_peaks {
my $results = shift;
my $num_peaks = shift || 7;
return '' unless $results->{spectra}->{medium};
my %top_peaks;
$denormalize = 0;
my @medium = $consensus->get_top_n_peaks( n_peaks => $num_peaks,
denormalize => $denormalize,
spectra => $results->{spectra}->{medium} );
$top_peaks{medium} = $medium[0];
my $peak_list = $medium[1];
$ymax = $top_peaks{medium}->{$peak_list->[0]};
for my $ce ( qw( low mlow mhigh high ) ) {
$top_peaks{$ce} = $consensus->get_top_n_peaks( n_peaks => $num_peaks,
denormalize => $denormalize,
spectra => $results->{spectra}->{$ce},
peak_list => $peak_list );
next unless $top_peaks{$ce};
for my $ion ( keys( %{$top_peaks{$ce}} ) ) {
next unless $ion;
$ymax = $top_peaks{$ce}->{$ion} if $top_peaks{$ce}->{$ion} > $ymax;
}
}
my $columns .= " data.addColumn( 'string', 'CE' )\n";
for my $ion ( @{$peak_list} ) {
$columns .= " data.addColumn( 'number', '$ion' )\n";
}
# data.addRows(4);
# data.setValue(0, 0, '2004');
# data.setValue(0, 1, 1000);
# data.setValue(0, 2, 400);
my $plot_data = '';
my %plot_data;
my $num_rows = 0;
my $row = 0;
for my $ce ( qw( low mlow medium mhigh high ) ) {
next unless $results->{spectra}->{$ce};
my $col = 0;
$num_rows++;
my $ce_label = ( $ce eq 'medium' ) ? "$results->{spectra}->{$ce}->{ce}*" : $results->{spectra}->{$ce}->{ce};
$plot_data .= "data.setValue( $row, $col, '$ce_label' );\n";
$col++;
for my $ion ( @{$peak_list} ) {
$top_peaks{$ce}->{$ion} = sprintf( "%i", $top_peaks{$ce}->{$ion} );
$plot_data .= "data.setValue( $row, $col, $top_peaks{$ce}->{$ion} );\n";
$col++;
}
$row++;
}
my $chart_data = qq~
$columns
data.addRows($num_rows);
$plot_data
~;
return $chart_data;
}
sub get_chart {
my %args = @_;
my $data = $args{data} || return '';
my $ion_info = "$args{seq}+$args{chg}" || '';
my $chart = qq~
~;
return $chart;
#
#
#
}
###############################################################################
# get_library_spectrum
###############################################################################
sub get_library_spectrum
{
my %args = @_;
my $inputfile = $args{'inputfile'} || "";
my $verbose = $args{'verbose'} || "";
my $consensus_library_spectrum_id = $args{'consensus_library_spectrum_id'} || "";
# For backwards compatibility with NIST tables (TIQAM).
$consensus_library_spectrum_id ||= $args{NIST_library_spectrum_id};
#### Define some general variables
my ($i,$element,$key,$value,$sql);
my (@rows,$nrows);
#### Define the data hash
my %spectrum;
my @mass_intensities;
#### If we have a msms_spectrum_id, get the data from the database
if ($consensus_library_spectrum_id) {
#### Extract the actual mass,intensity pairs from database
$sql = "SELECT mz, relative_intensity ".
" FROM $TBAT_CONSENSUS_LIBRARY_SPECTRUM_PEAK ".
" WHERE consensus_library_spectrum_id = '$consensus_library_spectrum_id'";
# For backwards compatibility with NIST tables (TIQAM).
$sql = $sbeams->evalSQL( $sql );
if ( $args{NIST_library_spectrum_id} ) {
$sql =~ s/consensus/NIST/gm;
$log->info( "Translated to NIST tables: $sql" );
}
my @mass_intensities = $sbeams->selectSeveralColumns($sql);
#### If we still have no spectrum data, then bail out
unless (@mass_intensities) {
print "\nERROR: Unable to get m/z,intensity pairs for ".
"consensus_library_spectrum_id '$consensus_library_spectrum_id'.\n\n";
$error_state++;
return;
}
#### Extract rows into two arrays of masses and intensities
my (@masses,@intensities);
for ($i=0; $i<=$#mass_intensities; $i++) {
push(@masses,$mass_intensities[$i]->[0]);
push(@intensities,$mass_intensities[$i]->[1]);
}
$spectrum{n_peaks} = $#mass_intensities + 1;
#### Put data into hash and return
$spectrum{masses} = \@masses;
$spectrum{intensities} = \@intensities;
return %spectrum;
#### Otherwise complain and return
} else {
print "\nERROR: Unable to determine which consensus_library_spectrum_id to load.\n\n";
$error_state++;
return;
}
}
sub get_num_ions {
my $sequence = shift;
$log->info( "initial seq is $sequence" );
$sequence =~ s/\[\d+\]//g;
my $length = length $sequence;
my $n_ions = int( $length/2 + 3.1 ) ;
$n_ions = 12 if $n_ions > 12;
$log->info( "mod seq is $sequence, length is $length, n_ions is $n_ions" );
return $n_ions;
}
###############################################################################
# pg_setup
###############################################################################
sub pg_setup {
my %args = @_;
#### Default device is to screen (xserver)
my $device = $args{'Device'} || "\/xs";
#$device = "/xs";
#### Plot title
my $title = $args{'title'} || "";
#### Default x limits are (0,2000)
my $xmin = $args{'xmin'} || 0;
my $xmax = $args{'xmax'} || 2000;
#### Default y limits are (0,500000)
my $ymin = $args{'ymin'} || 0;
my $ymax = $args{'ymax'} || 500000;
#### Default separation between ticks is 100000
my $ytickdiv = $args{'ydiv'} || 100000;
#### Default number of y ticks
my $nyticks = ($args{'nyticks'}+1) || 4;
#### Default image size is 640x480
my $gifwidth = $args{'gifwidth'} || 640;
my $gifheight = $args{'gifheight'} || 480;
#### Set needed PGPLOT environment variables
$ENV{"PGPLOT_GIF_WIDTH"} = $gifwidth;
$ENV{"PGPLOT_GIF_HEIGHT"} = $gifheight;
#### Try to set the proper location of rgb.txt
if ($CONFIG_SETTING{PGPLOT_RGBTXT}) {
$ENV{"PGPLOT_RGB"} = $CONFIG_SETTING{PGPLOT_RGBTXT};
} elsif ( -e "/usr/share/X11/rgb.txt" ) {
$ENV{"PGPLOT_RGB"} = "/usr/share/X11/rgb.txt";
} else {
$ENV{"PGPLOT_RGB"} = "/usr/X11R6/lib/X11/rgb.txt";
}
$ENV{"PGPLOT_FONT"} = $CONFIG_SETTING{PGPLOT_FONT} ||
"/usr/local/lib/grfont.dat";
$ENV{"PGPLOT_BACKGROUND"} = "white";
#### Create a new graphics device
#### WARNING: If the device is a filename, it apparently gets
#### truncated at 80 characters!!!
my $win = PDL::Graphics::PGPLOT::Window -> new({Device => "$device"});
#### Set window limits
pgswin $xmin, $xmax, 0, $ymax;
#### Set viewport limits
pgsvp .095,.9775,.065,.95;
#### Set axis color to black (stealing lt. gray color)
pgscr 15, 0,0,0;
#### Set color index
pgsci 15;
#### Set character height
pgsch 0.9;
#### Set line width
pgslw 1;
#### Set character font (Normal)
pgscf 1;
#### Draw labeled frame around viewport: full frame (BC), labels on
#### bottom and left of frame (N), major tick marks (T), y labels
#### normal to y-axis (V), decimal labels instead of scientific
#### notation (1), automatic x major ticks, $ytickdiv between y ticks,
#### with $nyticks major divisions.
pgbox 'BCNT',0,0,'BCNTV1',$ytickdiv,$nyticks;
#### Reset character height (make labels larger)
pgsch 1;
#### Y label on left, centered vertically along axis
pgmtxt 'L',3.8,.5,.5,'Normalized Intensity';
#### X label on bottom, centered vertically along axis
pgmtxt 'B',2.25,.5,.5,'m/z';
#### Main title above, centered vertically along top
pgmtxt 'T',1,.5,.5,"$title";
#### Reset character height (want in-plot labels small)
pgsch .8;
#### Allow overplotting of this frame
$win -> hold;
return $win;
}
###############################################################################
# PlotPeaks
###############################################################################
sub PlotPeaks {
my %args = @_;
#### Spectrum data to be plotted
my $specdata = $args{'SpecData'};
#### Ions to be plotted
my $masslist_ref = $args{'Masslist'};
#### Charge
my $charge = $args{'Charge'};
#### Plot frame
my $win = $args{'Win'};
#### Peak Colors
my $peakcolors_ref = $args{'PeakColors'};
#### Peak finding window
my $window = $args{'Window'} || 2;
my $length = $args{'Length'};
my @Bmaxinten = (0) x $length;
my @Ymaxinten = (0) x $length;
my @BYmaxinten = (0) x $length;
my @Bmass;
my @Ymass;
my @BYmass;
my @Rmass;
my @Binten;
my @Yinten;
my @BYinten;
my @Rinten;
#my @Rinten = (0) x $specdata->{n_peaks};
my ($redcol,$bluecol,$grcol);
#### Define pink color to be lightcoral
pgscr 6,0.94,0.5,0.5;
#### Define lt. blue color to be navy
pgscr 11,0,0,.5;
#### Define lt. green color to be DarkSeaGreen
pgscr 10,0.56,0.74,0.56;
#### Define red color to be red
pgscr 2,1,0,0;
#### Define blue color to be blue
pgscr 4,0,0,1;
#### Define green color to be ForestGreen
pgscr 3,0.13,0.55,0.13;
if ($charge == 1) {
$redcol = 2;
$bluecol = 4;
$grcol = 3;
} else {
$redcol = 6;
$bluecol = 11;
$grcol = 10;
}
#### Convert to piddle for easy sub-selecting
my $bdata = pdl $masslist_ref->{Bions};
my $ydata = pdl $masslist_ref->{Yions};
#### Draw peaks
my $i;
my $lineclr;
my ($mass, $intensity);
for ($i=0; $i<$specdata->{n_peaks}; $i++) {
$mass = $specdata->{masses}->[$i];
$intensity = $specdata->{intensities}->[$i];
#### Set default line color to Black
$lineclr = $peakcolors_ref->[$i] || 14;
my $mainx = pdl [$mass, $mass];
my $mainy = pdl [0, $intensity];
#### This kludge lets me not colorize the last B and/or
#### first Y peaks found
## problem i'ere
set $bdata, ($length-1),-9999;
set $ydata, 0, -9999;
my $Bind = which($bdata >= ($mass-$window) & $bdata <= ($mass+$window));
my $Yind = which($ydata >= ($mass-$window) & $ydata <= ($mass+$window));
#### If there are just B fragments with mass near enough this peak
if (($Bind !~ 'Empty') && ($Yind =~ 'Empty')) {
$lineclr = $redcol;
push(@Binten,$intensity);
push(@Bmass,$mass);
if ($Bmaxinten[$Bind->at(0)] < $intensity) {
$Bmaxinten[$Bind->at(0)] = $intensity;
$masslist_ref->{Bcolor}->[$Bind->at(0)] = $lineclr
unless ($masslist_ref->{Bcolor}->[$Bind->at(0)]);
}
#### Else if there are just Y fragments with mass near enough this peak
} elsif (($Yind !~ 'Empty') && ($Bind =~ 'Empty')) {
$lineclr = $bluecol;
push(@Yinten,$intensity);
push(@Ymass,$mass);
if ($Ymaxinten[$Yind->at(0)] < $intensity) {
$Ymaxinten[$Yind->at(0)] = $intensity;
$masslist_ref->{Ycolor}->[$Yind->at(0)] = $lineclr;
}
#### Else if both B and Y fragments with mass near enough this peak
} elsif (($Bind !~ 'Empty') && ($Yind !~ 'Empty')) {
$lineclr = $grcol;
push(@BYinten,$intensity);
push(@BYmass,$mass);
if ($Ymaxinten[$Yind->at(0)] < $intensity) {
$Ymaxinten[$Yind->at(0)] = $intensity;
$masslist_ref->{Ycolor}->[$Yind->at(0)] = $lineclr;
}
if ($Bmaxinten[$Bind->at(0)] < $intensity) {
$Bmaxinten[$Bind->at(0)] = $intensity;
$masslist_ref->{Bcolor}->[$Bind->at(0)] = $lineclr;
}
#### else if there are no fragments with mass near enough this peak
} else {
if (($peakcolors_ref->[$i] != 2) & ($peakcolors_ref->[$i] != 3) &
($peakcolors_ref->[$i] != 4) & ($peakcolors_ref->[$i] != 6) &
($peakcolors_ref->[$i] != 10) & ($peakcolors_ref->[$i] != 11)) {
#$Rinten[$i] = $intensity
push(@Rinten,$intensity);
push(@Rmass,$mass);
}
}
$peakcolors_ref->[$i] = $lineclr;
}
my ($mass2, $intensity2);
$mass2 = $specdata->{masses};
$intensity2 = $specdata->{intensities};
#### Now we resort to plotting all peaks by "never lifting the pen"
#### and drawing it all in a continuous line with line() because this
#### is much faster
my $rx = pdl (\@Rmass,\@Rmass,\@Rmass)->xchg(0,1)->clump(2);
#my $rx = pdl ($mass2,$mass2,$mass2)->xchg(0,1)->clump(2);
my $ra = [(0) x scalar(@Rinten)];
my $ry = pdl ($ra,\@Rinten,$ra)->xchg(0,1)->clump(2);
my $rh = {Color => 14};
$win -> line ($rx,$ry,$rh);
my $bx = pdl (\@Bmass,\@Bmass,\@Bmass)->xchg(0,1)->clump(2);
my $ba = [(0) x scalar(@Binten)];
my $by = pdl ($ba,\@Binten,$ba)->xchg(0,1)->clump(2);
my $bh = {Color => $redcol};
$win -> line ($bx,$by,$bh);
my $yx = pdl (\@Ymass,\@Ymass,\@Ymass)->xchg(0,1)->clump(2);
my $ya = [(0) x scalar(@Yinten)];
my $yy = pdl ($ya,\@Yinten,$ya)->xchg(0,1)->clump(2);
my $yh = {Color => $bluecol};
$win -> line ($yx,$yy,$yh);
my $byx = pdl (\@BYmass,\@BYmass,\@BYmass)->xchg(0,1)->clump(2);
my $bya = [(0) x scalar(@BYinten)];
my $byy = pdl ($bya,\@BYinten,$bya)->xchg(0,1)->clump(2);
my $byh = {Color => $grcol};
$win -> line ($byx,$byy,$byh);
return ($win,\@Bmaxinten,\@Ymaxinten);
}
###############################################################################
# LabelResidues
###############################################################################
sub LabelResidues {
my %args = @_;
my $Ionmasses_ref = $args{'Ionmasses'};
my $Bdata = pdl $Ionmasses_ref->{Bions};
my $Ydata = pdl $Ionmasses_ref->{Yions};
my $charge = $args{'Charge'};
my $win = $args{'Win'};
my $Binten_ref = $args{'Binten'};
my @Binten = @$Binten_ref;
my $Yinten_ref = $args{'Yinten'};
my @Yinten = @$Yinten_ref;
my $length = $args{'Length'};
my $labht;
my $angle = $args{'Angle'} || 0;
my $fjust = $args{'Fjust'};
my ($Bcol,$Ycol,$bothcol);
my $i;
my ($lineclr,$redcol,$bluecol,$grcol);
my $Ymax = $args{'Ymax'};
my $Xmin = $args{'Xmin'};
my $Xmax = $args{'Xmax'};
my $interval = $Ymax / 50.0;
my $xshift = ($Xmax - $Xmin) / 200.0;
#### Define pink color to be lightcoral
pgscr 6,0.94,0.5,0.5;
#### Define lt. blue color to be navy
pgscr 11,0,0,.5;
#### Define lt. green color to be DarkSeaGreen
pgscr 10,0.56,0.74,0.56;
#### Define red color to be lightcoral
pgscr 2,1,0,0;
#### Define blue color to be navy
pgscr 4,0,0,1;
#### Define green color to be DarkSeaGreen
pgscr 3,0.13,0.55,0.13;
if ($charge == 1) {
$redcol = 2;
$bluecol = 4;
$grcol = 3;
} else {
$redcol = 6;
$bluecol = 11;
$grcol = 10;
}
for ($i=0; $i < $length; $i++) {
if (($Binten[$i] != 0) && ($i != ($length-1))) {
my $val = $Ionmasses_ref->{indices}->[$i];
++$val;
my $index = "B$charge\-$val";
my $mass = $Bdata->at($i);
my $matchx = pdl [$mass, $mass];
my $y = $Binten[$i];
my $matchy = pdl [$y+($interval/3.), $y+4*($interval/3.)];
my $Yind = which($Ydata >= ($mass-2) & $Ydata <= ($mass+2));
if ($Yind !~ 'Empty') {
#### Green text and line for both ion match
pgsci $grcol;
$lineclr = $grcol;
#### Location of label above tick mark (moved up)
$labht = $y+8.5*($interval/3.);
} else {
#### Red text and line for B ion match
pgsci $redcol;
$lineclr = $redcol;
#### Location of label above tick mark
$labht = $y+5*($interval/3.);
}
#### Plot ion marker line
$win -> line($matchx, $matchy, {Color=>$lineclr});
$win -> hold;
#### Add ion label
pgptext $mass+$xshift,$labht,$angle,$fjust,"$index"
if (($labht < $Ymax) && ($mass > $Xmin) && ($mass < $Xmax));
}
}
for ($i = $length; $i > 0; $i--) {
if (($Yinten[$i] != 0) && ($i != 0)) {
my $index = "Y$charge\-$i";
my $mass = $Ydata->at($i);
my $matchx = pdl [$mass, $mass];
my $y = $Yinten[$i];
my $matchy = pdl [$y+($interval/3.), $y+4*($interval/3.)];
my $Bind = which($Bdata >= ($mass-2) & $Bdata <= ($mass+2));
if ($Bind !~ 'Empty') {
#### Green text and line for both ion match
pgsci $grcol;
$lineclr = $grcol;
#### Location of label above tick mark (moved up)
$labht = $y+8.5*($interval/3.);
} else {
#### Red text and line for B ion match
pgsci $bluecol;
$lineclr = $bluecol;
#### Location of label above tick mark
$labht = $y+5*($interval/3.);
}
#### Plot ion marker line
$win -> line($matchx, $matchy, {Color=>$lineclr});
$win -> hold;
#### Add ion label
pgptext $mass+$xshift,$labht,$angle,$fjust,"$index"
if (($labht < $Ymax) && ($mass > $Xmin) && ($mass < $Xmax));
}
}
return $win;
}
###############################################################################
# Fragment
###############################################################################
sub Fragment {
my $peptide = shift;
my $length = length($peptide);
my @residues = ();
my $i;
for ($i=0; $i<$length; $i++) {
if (substr($peptide,$i+1,1) eq '[') {
push (@residues, substr($peptide,$i,6));
$i = $i + 5;
} elsif (substr($peptide,$i+1,1) =~ /\W/) {
push (@residues, substr($peptide,$i,2));
$i = $i + 1;
} else {
push (@residues, substr($peptide,$i,1));
}
}
#### Return residue array
return @residues;
}
###############################################################################
# CalcIons -- calculate theoretical ions (including modified masses)
###############################################################################
sub CalcIons {
my %args = @_;
my $i;
my $residues_ref = $args{'Residues'};
my @residues = @$residues_ref;
my $charge = $args{'Charge'} || 1;
my $length = scalar(@residues);
my $modified_sequence = $args{'modified_sequence'};
my @masses = $modification_helper->getMasses($modified_sequence);
my $Nterm = 1.0078;
my $Bion = 0.;
my $Yion = 19.0184; ## H_2 + O
my @Bcolor = (14) x $length;
my @Ycolor = (14) x $length;
my %masslist;
my (@aminoacids, @indices, @rev_indices, @Bions, @Yions);
#### Compute the ion masses
for ($i = 0; $i<$length; $i++) {
$Bion += $masses[$i];
#### B index & Y index
$indices[$i] = $i;
$rev_indices[$i] = $length-$i;
$Yion += $masses[ $rev_indices[$i] ] if ($i > 0);
#### B ion mass & Y ion mass
$Bions[$i] = ($Bion + $charge*$Nterm)/$charge;
$Yions[$i] = ($Yion + $charge*$Nterm)/$charge;
}
$masslist{residues} = \@residues;
$masslist{indices} = \@indices;
$masslist{Bions} = \@Bions;
$masslist{Yions} = \@Yions;
$masslist{rev_indices} = \@rev_indices;
#### Return reference to a hash of array references
return (\%masslist);
}
###############################################################################
# printIons
###############################################################################
sub printIons {
my %args = @_;
my $masslist_ref = $args{'masslist_ref'};
my $color = $args{'color'} || 0;
my $html = $args{'html'} || 0;
my $charge = $args{'charge'};
my $length = $args{'length'};
my $theoretical_spectrum_ref = $args{'theoretical_spectrum_ref'};
# print "SEQ # B Y +$charge\n";
# print "--- -- ------ ------ --\n";
# my ($bcolbegin, $bcolend, $ycolbegin, $ycolend);
# my (%colors);
# $colors{2} = "#FF0000";
# $colors{4} = "#0000FF";
# $colors{3} = "#218D21";
# $colors{6} = "#F18080";
# $colors{11} = "#00088";
# $colors{10} = "#8FBE8F";
# #### Printing stuff
for (my $i=0; $i < $length; $i++) {
# #### If the output is in HTML, define the colorizing tags
# if ($html) {
# #### If a color for this B ion mass, set color tags
# if ($masslist_ref->{Bcolor}->[$i] >= 2) {
# $bcolbegin = "{Bcolor}->[$i]}>";
# $bcolend = "";
# #### else no color (default black)
# } else {
# $bcolbegin = "";
# $bcolend = "";
# }
# #### If a color for this Y ion mass, set color tags
# if ($masslist_ref->{Ycolor}->[$i] >= 2) {
# $ycolbegin = "{Ycolor}->[$i]}>";
# $ycolend = "";
# #### else no color (default black)
# } else {
# $ycolbegin = "";
# $ycolend = "";
# }
# }
#### Define the m/z columns formats and values
my $B_format = '%7.1f';
my $Y_format = '%7.1f';
my $B_value = $masslist_ref->{Bions}->[$i];
my $Y_value = $masslist_ref->{Yions}->[$i];
#### Special case --'s for first row
if ($i == 0) {
$Y_format = '%7s';
$Y_value = '-- ';
#### Special case --'s for last row
} elsif ($i == ($length-1)) {
$B_format = '%7s';
$B_value = '-- ';
}
# #### Print out the data
# printf "%3s %2d $bcolbegin$B_format$bcolend ".
# "$ycolbegin$Y_format$ycolend %3d\n",
# $masslist_ref->{residues}->[$i], $i+1,
# $B_value, $Y_value, $length-$i;
#### Fill the theoretical spectrum data in a different format
#### (Residue,Index,Ion,Charge,m/z)
$theoretical_spectrum_ref->[2*$length*($charge-1)+$i] =
[$masslist_ref->{residues}->[$i],$i+1,'B',$charge,$B_value];
$theoretical_spectrum_ref->[2*$length*($charge-1)+2*$length-1-$i] =
[$masslist_ref->{residues}->[$i],$length-$i,'Y',
$charge,$Y_value];
} # end for
# print "\n";
} # end printIons