Mercurial > repos > fgiacomoni > massbank_ws_searchspectrum
diff lib/massbank_api.pm @ 0:023c380900ef draft default tip
Init repository with last massbank_ws_searchspectrum master version
author | fgiacomoni |
---|---|
date | Wed, 19 Apr 2017 11:31:58 -0400 |
parents | |
children |
line wrap: on
line diff
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/lib/massbank_api.pm Wed Apr 19 11:31:58 2017 -0400 @@ -0,0 +1,699 @@ +package lib::massbank_api ; + +use strict; +use warnings ; +use Exporter ; +use Carp ; + +use Data::Dumper ; +#use SOAP::Lite +trace => [qw (debug)]; +use SOAP::Lite ; + +use vars qw($VERSION @ISA @EXPORT %EXPORT_TAGS); + +our $VERSION = "1.0"; +our @ISA = qw(Exporter); +our @EXPORT = qw( connectMassBankJP connectMassBankDE selectMassBank getInstrumentTypes getRecordInfo searchSpectrum getPeak); +our %EXPORT_TAGS = ( ALL => [qw( connectMassBankJP connectMassBankDE selectMassBank getInstrumentTypes getRecordInfo searchSpectrum getPeak)] ); + + + + +=head1 NAME + +My::Module - An example module + +=head1 SYNOPSIS + + use My::Module; + my $object = My::Module->new(); + print $object->as_string; + +=head1 DESCRIPTION + +This module does not really exist, it +was made for the sole purpose of +demonstrating how POD works. + +=head1 METHODS + +Methods are : + +=head2 METHOD new + + ## Description : new + ## Input : $self + ## Ouput : bless $self ; + ## Usage : new() ; + +=cut + +sub new { + ## Variables + my $self={}; + bless($self) ; + return $self ; +} +### END of SUB + + +=head2 METHOD connectMassBankJP + + ## Description : create a soap object throught the webservice japan massbank. + ## Input : $self + ## Ouput : $soap ; + ## Usage : my $soap = connectMassBankJP() ; + +=cut +sub connectMassBankJP() { + ## Retrieve Values + my $self = shift ; + my $osoap = SOAP::Lite + -> uri('http://api.massbank') + -> proxy('http://www.massbank.jp/api/services/MassBankAPI?wsdl', timeout => 100 ) + -> on_fault(sub { my($soap, $res) = @_; + eval { die ref $res ? $res->faultstring : $soap->transport->status, "\n"}; + return ref $res ? $res : new SOAP::SOM ; + }); + + return ($osoap); +} +### END of SUB + +=head2 METHOD connectMassBankDE + + ## Description : create a soap object throught the webservice UFZ-DE massbank. + ## Input : $self + ## Ouput : $soap ; + ## Usage : my $soap = connectMassBankDE() ; + +=cut +sub connectMassBankDE() { + ## Retrieve Values + my $self = shift ; + my $osoap = SOAP::Lite + -> uri('http://api.massbank') +# -> proxy('http://massbank.ufz.de/MassBank/api/services/MassBankAPI?wsdl', timeout => 500 ) + -> proxy('http://massbank.normandata.eu/MassBank/api/services/MassBankAPI?wsdl', timeout => 500 ) + -> on_fault(sub { my($soap, $res) = @_; + eval { die ref $res ? $res->faultstring : $soap->transport->status, "\n"}; + return ref $res ? $res : new SOAP::SOM ; + }); + + return ($osoap); +} +### END of SUB + +=head2 METHOD selectMassBank + + ## Description : create a soap object throught a choice of servers like UFZ-DE mirror or JP mirror. + ## Input : $server + ## Ouput : $soap ; + ## Usage : my $soap = selectMassBank($server) ; + +=cut +sub selectMassBank() { + ## Retrieve Values + my $self = shift ; + my ( $server ) = @_ ; + + my $osoap = undef ; + + my $ombk = new() ; + + if ( (defined $server ) and ($server eq 'JP') ) { + $osoap = $ombk->connectMassBankJP() ; + } + elsif ( (defined $server ) and ($server eq 'EU') ){ + $osoap = $ombk->connectMassBankDE() ; + } + elsif ( !defined $server ) { + croak "Can't adress SOAP connexion : undefined MassBank server\n" ; + } + else { + croak "Can't adress SOAP connexion : unknown MassBank server ($server)\n" ; + } + return ($osoap); +} +### END of SUB + + + +=head2 METHOD getInstrumentTypes + + ## Description : Get a list of the instrument types resistered in MassBank + ## Input : $soap + ## Ouput : $res ; + ## Usage : $res = getInstrumentTypes($soap) ; + +=cut +sub getInstrumentTypes() { + ## Retrieve Values + my $self = shift ; + my ($osoap) = @_ ; + my @records = () ; + + my $res = $osoap -> getInstrumentTypes ; + + ## DETECTING A SOAP FAULT + if ($res->fault) { @records = $res->faultdetail; } + else { @records = $res->valueof('//return'); } + + return(\@records) ; +} +### END of SUB + +=head2 METHOD getRecordInfo + + ## Description : Get the data of MassBank records specified by Record IDs. A MassBank record includes peak data, analytical conditions and so on). + ## Input : $osoap, $ids + ## Ouput : $dats + ## Usage : $dats = getRecordInfo($osoap, $ids) ; + +=cut + +sub getRecordInfo() { + ## Retrieve Values + my $self = shift ; + my ($osoap, $ids) = @_ ; + + # init in case : + my @dats = () ; + my $numdats = 0 ; + + if ( defined $ids ) { + my $nb_ids = scalar (@{$ids}) ; + + if ( $nb_ids > 0 ) { + + my @ids = @{$ids} ; + + my @params = ( SOAP::Data->name('ids' => @ids ) ); + + my $data = SOAP::Data -> value(@params); + my $som = $osoap -> getRecordInfo($data); + + ## DETECTING A SOAP FAULT OR NOT + if ( $som ) { + if ($som->fault) { + carp "\t\t WARN: The query Id is false, MassBank don't find any record\n" ; + push( @dats, undef ) ; + } + else { + if (!defined $som->valueof('//info')) { + carp "\t\t WARN: The query Id is undef, and MassBank won't find any record\n" ; + } + elsif ($som->valueof('//info') ne '') { # avoid to fill array with false id returning '' value + @dats = $som->valueof('//info'); + } + else { + carp "\t\t WARN: The query Id is false, MassBank don't find any record\n" ; + } + } + } + else { + carp "The som return (from the getRecordInfo method) isn't defined\n" ; } + } + else { carp "Query MZs list is empty, MassBank soap will stop\n" ; } + } + else { carp "Query MZs list is undef, MassBank soap will stop\n" ; } + + return(\@dats) ; +} + + + + +### END of SUB + +=head2 METHOD initRecordObject + + ## Description : init a massbank record object from a string + ## Input : $string + ## Output : $orecord + ## Usage : my ( $orecord ) = initRecordObject ( $string ) ; + +=cut +## START of SUB +sub initRecordObject { + ## Retrieve Values + my $self = shift ; + my ( $string ) = @_; + my ( %orecord ) = ( () ) ; + + if (defined $string) { + my $pkcheck = 0 ; + my (@mzs, @int, @relint) = ( (), (), () ) ; + my @features = split(/\n/, $string) ; + + foreach (@features) { + ## for all key:value + ## todo : known issue with "COMMENT" part (wrong split) + if ($_ =~ /(.+):(.+)/) { + my ($key, $string) = ($1, $2 ); + $string =~ s/^\s+|\s+$//g; + $orecord{$key} = $string ; + if ($key =~/^PK\$PEAK/) { + $pkcheck = 1 ; + (@mzs, @int, @relint) = ( (), (), () ) ; + } + } + elsif ($pkcheck == 1) { + ## case 01 : m/z int. rel.int. + if ($_ =~ /\s+(.+)\s+(.+)\s+(.+)/) { + push (@mzs, $1) ; push (@int, $2) ; push (@relint, $3) ; + } + } + } + ## init mzs, int and relint + my %tmp = () ; + $tmp{'mz'} = \@mzs ; + $tmp{'int'} = \@int ; + $tmp{'relint'} = \@relint ; + $orecord{'PK$PEAK'} = \%tmp ; + } + else { + warn "The given massbank string is undef\n" ; + } + + return (\%orecord) ; +} +### END of SUB + +=head2 METHOD getRecordInfoId + + ## Description : get the Id value in the massbank info string + ## Input : $orecord + ## Output : $orecord + ## Usage : my ( $orecord ) = getRecordInfoId ( $record ) ; + +=cut +## START of SUB +sub getRecordInfoId { + ## Retrieve Values + my $self = shift ; + my ( $orecord ) = @_; + + my $id = undef ; + if ($orecord->{'ACCESSION'}) { $id = $orecord->{'ACCESSION'} ; } + else { $id = 'NA' ; } + return (\$id) ; +} +### END of SUB + + + + + +=head2 METHOD getPeakFromId + + ## Description : Get the peak data of MassBank records specified by Record IDs. + ## Input : $ids + ## Ouput : + ## Usage : my ($pks) = getPeak($soap, $ids) ; + +=cut + +sub getPeak() { + ## Retrieve Values + my $self = shift ; + my ($osoap, $ids) = @_; + my (@dat, @ids, @dats) = ( (), () ); + @ids = @{$ids} ; + + foreach my $id ( @ids ) { + push(@dat, SOAP::Data -> name('ids' => $id)); + } + + my $data = SOAP::Data -> value(@dat); + my $som = $osoap -> getPeak($data) ; + + ## DETECTING A SOAP FAULT OR NOT + if ($som->fault) { @dats = $som->faultdetail ; } + else { @dats = $som->valueof('//return') ; } + +# print Dumper $som->valueof('//return') ; + return(\@dats) ; +} + +=head2 METHOD searchSpectrum + + ## Description : Get the response equivalent to the "Spectrum Search" results. + ## Input : $osoap, $pcgroup_id, $mzs, $intensities, $ion, $instruments, $max, $unit, $tol, $cutoff + ## Ouput : $spectra, $numspectra + ## Usage : ($spectra, $numspectra) = searchSpectrum($osoap, $mzs, $intensities, $ion, $instruments, $max, $unit, $tol, $cutoff) ; + +=cut + +sub searchSpectrum() { + ## Retrieve Values + my $self = shift ; + my ($osoap, $pcgroup_id , $mzs, $intensities, $ion, $instruments, $max, $unit, $tol, $cutoff) = @_; + + # init in case : + $ion = 'both' if ( !defined $ion ) ; + $instruments = ['all'] if ( !defined $instruments ) ; + $max = 0 if ( !defined $max ) ; + $unit = 'unit' if ( !defined $unit ) ; + $cutoff = 5 if ( !defined $cutoff ) ; + if ( !defined $tol ) { + if ( $unit eq 'unit' ) { $tol = 0.3 ; } + else { $tol = 50 ; } + } + + my @dats = () ; + my %ret = (); # %ret = {'res' => [], 'num_res' => int, 'pcgroup_id'=> int } + my $numdats = 0 ; + + if ( defined $mzs ) { + my $nb_mzs = scalar (@{$mzs}) ; + + if ( $nb_mzs > 0 ) { + + my @mzs = @{$mzs} ; + my @ints = @{$intensities} ; + my ( @dat1, @dat2 ) = ( (), () ) ; + my $i = 0 ; + + foreach my $mz (@mzs) { + push(@dat1, SOAP::Data -> name('mzs' => $mz) ); + push(@dat2, SOAP::Data -> name('intensities' => $ints[$i]) ); + $i++ ; + } + + push(@dat2, SOAP::Data -> name('unit' => $unit) ) ; + push(@dat2, SOAP::Data -> name('tolerance' => $tol) ) ; + push(@dat2, SOAP::Data -> name('cutoff' => $cutoff) ) ; + + foreach my $ins ( @{$instruments} ) { + push(@dat2, SOAP::Data -> name('instrumentTypes' => $ins)); + } + push(@dat2, SOAP::Data -> name('ionMode' => $ion)); + push(@dat2, SOAP::Data -> name('maxNumResults' => $max)); + + my $data = SOAP::Data -> value(@dat1, @dat2); + my $som = $osoap -> searchSpectrum($data); + + ## DETECTING A SOAP FAULT OR NOT + if ( $som ) { + if ($som->fault) { + $ret{'fault'} = $som->faultstring; $ret{'num_res'} = -1 ; + } + else { +# print Dumper $som ; + @dats = $som->valueof('//results/[>0]'); + $numdats = $som->valueof('//numResults') ; + my $i ; + my @res = () ; + + if (!defined $numdats) { $numdats = 0 ; } + ## For results + if ($numdats > 0) { + ## insert nb of res + $ret{ 'num_res'} = $numdats ; + $ret{ 'pcgroup_id'} = $pcgroup_id ; + + ## manage mapping for spectral features + +# print Dumper @dats ; ## Bug with order depending of spectra source : + + for ( $i = 0; $i < $numdats; $i ++ ) { + my ($exactMass, $formula, $id, $score, $title) = @dats[($i * 5) .. ($i * 5 + 4)]; + + ## manage issue from massbank like ID MSJ00002 and formula == 1 FROM WS + if ($formula eq '1') { +# print "-------> WS sent mixed value for $id (EM:$exactMass, F:$formula, ID:$id, SC:$score, TI:$title)\n" ; + my (%val) = ('id', $title, 'title', $id, 'formula', $exactMass, 'exactMass', 'NA', 'score', $score); + push(@res, { %val }); + } + else { + my (%val) = ('id', $id, 'title', $title, 'formula', $formula, 'exactMass', $exactMass, 'score', $score); + push(@res, { %val }); + } + } + + ## order res by score + my @sorted = sort { $a->{score} <=> $b->{score} } @res; + + $ret{'res'} = \@sorted; + } + ## for no results for the query + else { + $ret{ 'num_res'} = $numdats ; + $ret{ 'pcgroup_id'} = $pcgroup_id ; + my (%val) = ('id', undef, 'title', undef, 'formula', undef, 'exactMass', undef, 'score', undef); + push(@res, { %val }); + $ret{'res'} = \@res; + } + } + } + else { + carp "The som return (from the searchSpectrum method) isn't defined\n" ; } + } + else { carp "Query MZs list is empty, MassBank soap will stop\n" ; } + } + else { carp "Query MZs list is undef, MassBank soap will stop\n" ; } +# print Dumper @ret ; + return(\%ret, $numdats) ; +} +### END of SUB + + + + +#=head2 METHOD new +# +# ## Description : new +# ## Input : $self +# ## Ouput : bless $self ; +# ## Usage : new() ; +# +#=cut +# +#sub searchPeak() { local($soap, $mz, $max, $ion, $rel, $inst, $tol) = @_; +# $ion = 'both' if ( $ion eq '' ); +# $rel += 0; +# $max += 0; +# local(@inst) = @$inst; +# @inst = ('all') if ( scalar(@inst) == 0 ); +# $tol = 0.3 if ( $tol eq '' ); +# local(@mz) = @$mz; +# local(@dat) = (); +# local($mzv); +# foreach $mzv ( @mz ) { +# push(@dat, SOAP::Data -> name('mzs' => $mzv)); +# } +# push(@dat, SOAP::Data -> name('relativeIntensity' => $rel)); +# push(@dat, SOAP::Data -> name('tolerance' => $tol)); +# local($ins); +# foreach $ins ( @inst ) { +# push(@dat, SOAP::Data -> name('instrumentTypes' => $ins)); +# } +# push(@dat, SOAP::Data -> name('ionMode' => $ion)); +# push(@dat, SOAP::Data -> name('maxNumResults' => $max)); +# local($data) = SOAP::Data -> value(@dat); +# local($som) = $soap -> searchPeak($data); +# local($num) = $som -> valueof('/Envelope/Body/[1]/[>0]/numResults'); +# local(@res) = $som -> valueof('/Envelope/Body/[1]/[>0]/results/[>0]'); +# local($i); +# local(@ret) = (); +# for ( $i = 0; $i < $num; $i ++ ) { +# local($mw, $form, $id, $score, $title) = @res[($i * 5) .. ($i * 5 + 4)]; +# local(%val) = ('id', $id, 'title', $title, 'formula', $form, 'exactMass', $mw); +# push(@ret, { %val }); +# } +# return @ret; +#} +# +#=head2 METHOD new +# +# ## Description : new +# ## Input : $self +# ## Ouput : bless $self ; +# ## Usage : new() ; +# +#=cut +# +#sub searchPeakDiff() { local($soap, $mz, $max, $ion, $rel, $inst, $tol) = @_; +# $ion = 'both' if ( $ion eq '' ); +# $rel += 0; +# $max += 0; +# local(@inst) = @$inst; +# @inst = ('all') if ( scalar(@inst) == 0 ); +# $tol = 0.3 if ( $tol eq '' ); +# local(@mz) = @$mz; +# local(@dat) = (); +# local($mzv); +# foreach $mzv ( @mz ) { +# push(@dat, SOAP::Data -> name('mzs' => $mzv)); +# } +# push(@dat, SOAP::Data -> name('relativeIntensity' => $rel)); +# push(@dat, SOAP::Data -> name('tolerance' => $tol)); +# local($ins); +# foreach $ins ( @inst ) { +# push(@dat, SOAP::Data -> name('instrumentTypes' => $ins)); +# } +# push(@dat, SOAP::Data -> name('ionMode' => $ion)); +# push(@dat, SOAP::Data -> name('maxNumResults' => $max)); +# local($data) = SOAP::Data -> value(@dat); +# local($som) = $soap -> searchPeakDiff($data); +# local($num) = $som -> valueof('/Envelope/Body/[1]/[>0]/numResults'); +# local(@res) = $som -> valueof('/Envelope/Body/[1]/[>0]/results/[>0]'); +# local($i); +# local(@ret) = (); +# for ( $i = 0; $i < $num; $i ++ ) { +# local($mw, $form, $id, $score, $title) = @res[($i * 5) .. ($i * 5 + 4)]; +# local(%val) = ('id', $id, 'title', $title, 'formula', $form, 'exactMass', $mw); +# push(@ret, { %val }); +# } +# return @ret; +#} +# +#=head2 METHOD new +# +# ## Description : new +# ## Input : $self +# ## Ouput : bless $self ; +# ## Usage : new() ; +# +#=cut +# +#sub execBatchJob() { local($soap, $spectra, $ion, $inst, $mail) = @_; +# $ion = 'both' if ( $ion eq '' ); +# local(@inst) = @$inst; +# @inst = ('all') if ( scalar(@inst) == 0 ); +# local(%spectra) = %$spectra; +# local($name); +# local(@query) = (); +# foreach $name ( keys %spectra ) { +# local(@q) = ("Name:$name"); +# local(%peak) = %{$spectra{$name}}; +# local($mz, $inte); +# foreach $mz ( keys %peak ) { +# $inte = $peak{$mz}; +# push(@q, "$mz,$inte"); +# } +# push(@query, join(';', @q)); +# } +# local(@dat) = (); +# local($q); +# push(@dat, SOAP::Data -> name('type' => 1)); +# push(@dat, SOAP::Data -> name('mailAddress' => $mail)); +# foreach $q ( @query ) { +# push(@dat, SOAP::Data -> name('queryStrings' => $q)); +# } +# local($ins); +# foreach $ins ( @inst ) { +# push(@dat, SOAP::Data -> name('instrumentTypes' => $ins)); +# } +# push(@dat, SOAP::Data -> name('ionMode' => $ion)); +# local($data) = SOAP::Data -> value(@dat); +# local($som) = $soap -> execBatchJob($data); +# local($res) = $som -> valueof('/Envelope/Body/[1]'); +# return ${$res}{'return'}; +#} +# +#=head2 METHOD new +# +# ## Description : new +# ## Input : $self +# ## Ouput : bless $self ; +# ## Usage : new() ; +# +#=cut +# +#sub getJobStatus() { local($soap, $job) = @_; +# local(@dat) = (); +# push(@dat, SOAP::Data -> name('jobId' => $job)); +# local($data) = SOAP::Data -> value(@dat); +# local($som) = $soap -> getJobStatus($data); +# local($res) = $som -> valueof('/Envelope/Body/[1]/[1]'); +# local(%res) = %{$res}; +# local($status) = $res{'status'}; +# local($code) = $res{'statusCode'}; +# local($date) = $res{'requestDate'}; +# return ($status, $code, $date); +#} +# +#=head2 METHOD new +# +# ## Description : new +# ## Input : $self +# ## Ouput : bless $self ; +# ## Usage : new() ; +# +#=cut +# +#sub getJobResult() { local($soap, $job) = @_; +# local(@dat) = (); +# push(@dat, SOAP::Data -> name('jobId' => $job)); +# local($data) = SOAP::Data -> value(@dat); +# local($som) = $soap -> getJobResult($data); +# local(@res) = $som -> valueof('/Envelope/Body/[1]/[>0]'); +# local($n) = scalar(@res); +# local(@ret) = (); +# local($i); +# for ( $i = 0; $i < $n; $i ++ ) { +# local(%res) = %{$res[$i]}; +# local(@res1) = $som -> valueof('/Envelope/Body/[1]/['.($i+1).']/results/[>0]'); +# local(%ret) = (); +# local($qname) = $res{'queryName'}; +# $ret{'qname'} = $qname; +# local($num) = $res{'numResults'}; +# $ret{'num'} = $num; +# local(@ret1) = (); +# local($j); +# for ( $j = 0; $j < $num; $j ++ ) { +# local($mw, $form, $id, $score, $title) = @res1[($j * 5) .. ($j * 5 + 4)]; +# local(%val) = ('id', $id, 'title', $title, 'formula', $form, 'exactMass', $mw, 'score', $score); +# push(@ret1, { %val }); +# } +# $ret{'list'} = [ @ret1 ]; +# push(@ret, { %ret }); +# } +# return @ret; +#} + + +1 ; + + +__END__ + +=head1 SUPPORT + +You can find documentation for this module with the perldoc command. + + perldoc massbank_api.pm + +=head1 Exports + +=over 4 + +=item :ALL is ... + +=back + +=head1 AUTHOR + +Franck Giacomoni E<lt>franck.giacomoni@clermont.inra.frE<gt> and marion Landi E<lt>marion.landi@clermont.inra.frE<gt> + +=head1 LICENSE + +This script is fully inspired by MassBank SOAP API Client Package Ver-2.0 with : + Author: Hisayuki Horail (MassBank Group, IAB, Keio U. and JST-BIRD) + Home page: http://www.massbank.jp/ + Date: 25 May 2010 + This software is licensed + under a Creative Commons Attribution License 2.1 Japan License (CC-BY) + (http://creativecommons.org/licensesby/2.1/jp/). + +This new version of this program is free software; you can redistribute it and/or modify it under the same terms as Perl itself. + +=head1 VERSION + +version 1 : 25 / 05 / 2010 + +version 2 : 04 / 06 / 2015 + +=cut \ No newline at end of file