comparison 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
comparison
equal deleted inserted replaced
-1:000000000000 0:023c380900ef
1 package lib::massbank_api ;
2
3 use strict;
4 use warnings ;
5 use Exporter ;
6 use Carp ;
7
8 use Data::Dumper ;
9 #use SOAP::Lite +trace => [qw (debug)];
10 use SOAP::Lite ;
11
12 use vars qw($VERSION @ISA @EXPORT %EXPORT_TAGS);
13
14 our $VERSION = "1.0";
15 our @ISA = qw(Exporter);
16 our @EXPORT = qw( connectMassBankJP connectMassBankDE selectMassBank getInstrumentTypes getRecordInfo searchSpectrum getPeak);
17 our %EXPORT_TAGS = ( ALL => [qw( connectMassBankJP connectMassBankDE selectMassBank getInstrumentTypes getRecordInfo searchSpectrum getPeak)] );
18
19
20
21
22 =head1 NAME
23
24 My::Module - An example module
25
26 =head1 SYNOPSIS
27
28 use My::Module;
29 my $object = My::Module->new();
30 print $object->as_string;
31
32 =head1 DESCRIPTION
33
34 This module does not really exist, it
35 was made for the sole purpose of
36 demonstrating how POD works.
37
38 =head1 METHODS
39
40 Methods are :
41
42 =head2 METHOD new
43
44 ## Description : new
45 ## Input : $self
46 ## Ouput : bless $self ;
47 ## Usage : new() ;
48
49 =cut
50
51 sub new {
52 ## Variables
53 my $self={};
54 bless($self) ;
55 return $self ;
56 }
57 ### END of SUB
58
59
60 =head2 METHOD connectMassBankJP
61
62 ## Description : create a soap object throught the webservice japan massbank.
63 ## Input : $self
64 ## Ouput : $soap ;
65 ## Usage : my $soap = connectMassBankJP() ;
66
67 =cut
68 sub connectMassBankJP() {
69 ## Retrieve Values
70 my $self = shift ;
71 my $osoap = SOAP::Lite
72 -> uri('http://api.massbank')
73 -> proxy('http://www.massbank.jp/api/services/MassBankAPI?wsdl', timeout => 100 )
74 -> on_fault(sub { my($soap, $res) = @_;
75 eval { die ref $res ? $res->faultstring : $soap->transport->status, "\n"};
76 return ref $res ? $res : new SOAP::SOM ;
77 });
78
79 return ($osoap);
80 }
81 ### END of SUB
82
83 =head2 METHOD connectMassBankDE
84
85 ## Description : create a soap object throught the webservice UFZ-DE massbank.
86 ## Input : $self
87 ## Ouput : $soap ;
88 ## Usage : my $soap = connectMassBankDE() ;
89
90 =cut
91 sub connectMassBankDE() {
92 ## Retrieve Values
93 my $self = shift ;
94 my $osoap = SOAP::Lite
95 -> uri('http://api.massbank')
96 # -> proxy('http://massbank.ufz.de/MassBank/api/services/MassBankAPI?wsdl', timeout => 500 )
97 -> proxy('http://massbank.normandata.eu/MassBank/api/services/MassBankAPI?wsdl', timeout => 500 )
98 -> on_fault(sub { my($soap, $res) = @_;
99 eval { die ref $res ? $res->faultstring : $soap->transport->status, "\n"};
100 return ref $res ? $res : new SOAP::SOM ;
101 });
102
103 return ($osoap);
104 }
105 ### END of SUB
106
107 =head2 METHOD selectMassBank
108
109 ## Description : create a soap object throught a choice of servers like UFZ-DE mirror or JP mirror.
110 ## Input : $server
111 ## Ouput : $soap ;
112 ## Usage : my $soap = selectMassBank($server) ;
113
114 =cut
115 sub selectMassBank() {
116 ## Retrieve Values
117 my $self = shift ;
118 my ( $server ) = @_ ;
119
120 my $osoap = undef ;
121
122 my $ombk = new() ;
123
124 if ( (defined $server ) and ($server eq 'JP') ) {
125 $osoap = $ombk->connectMassBankJP() ;
126 }
127 elsif ( (defined $server ) and ($server eq 'EU') ){
128 $osoap = $ombk->connectMassBankDE() ;
129 }
130 elsif ( !defined $server ) {
131 croak "Can't adress SOAP connexion : undefined MassBank server\n" ;
132 }
133 else {
134 croak "Can't adress SOAP connexion : unknown MassBank server ($server)\n" ;
135 }
136 return ($osoap);
137 }
138 ### END of SUB
139
140
141
142 =head2 METHOD getInstrumentTypes
143
144 ## Description : Get a list of the instrument types resistered in MassBank
145 ## Input : $soap
146 ## Ouput : $res ;
147 ## Usage : $res = getInstrumentTypes($soap) ;
148
149 =cut
150 sub getInstrumentTypes() {
151 ## Retrieve Values
152 my $self = shift ;
153 my ($osoap) = @_ ;
154 my @records = () ;
155
156 my $res = $osoap -> getInstrumentTypes ;
157
158 ## DETECTING A SOAP FAULT
159 if ($res->fault) { @records = $res->faultdetail; }
160 else { @records = $res->valueof('//return'); }
161
162 return(\@records) ;
163 }
164 ### END of SUB
165
166 =head2 METHOD getRecordInfo
167
168 ## Description : Get the data of MassBank records specified by Record IDs. A MassBank record includes peak data, analytical conditions and so on).
169 ## Input : $osoap, $ids
170 ## Ouput : $dats
171 ## Usage : $dats = getRecordInfo($osoap, $ids) ;
172
173 =cut
174
175 sub getRecordInfo() {
176 ## Retrieve Values
177 my $self = shift ;
178 my ($osoap, $ids) = @_ ;
179
180 # init in case :
181 my @dats = () ;
182 my $numdats = 0 ;
183
184 if ( defined $ids ) {
185 my $nb_ids = scalar (@{$ids}) ;
186
187 if ( $nb_ids > 0 ) {
188
189 my @ids = @{$ids} ;
190
191 my @params = ( SOAP::Data->name('ids' => @ids ) );
192
193 my $data = SOAP::Data -> value(@params);
194 my $som = $osoap -> getRecordInfo($data);
195
196 ## DETECTING A SOAP FAULT OR NOT
197 if ( $som ) {
198 if ($som->fault) {
199 carp "\t\t WARN: The query Id is false, MassBank don't find any record\n" ;
200 push( @dats, undef ) ;
201 }
202 else {
203 if (!defined $som->valueof('//info')) {
204 carp "\t\t WARN: The query Id is undef, and MassBank won't find any record\n" ;
205 }
206 elsif ($som->valueof('//info') ne '') { # avoid to fill array with false id returning '' value
207 @dats = $som->valueof('//info');
208 }
209 else {
210 carp "\t\t WARN: The query Id is false, MassBank don't find any record\n" ;
211 }
212 }
213 }
214 else {
215 carp "The som return (from the getRecordInfo method) isn't defined\n" ; }
216 }
217 else { carp "Query MZs list is empty, MassBank soap will stop\n" ; }
218 }
219 else { carp "Query MZs list is undef, MassBank soap will stop\n" ; }
220
221 return(\@dats) ;
222 }
223
224
225
226
227 ### END of SUB
228
229 =head2 METHOD initRecordObject
230
231 ## Description : init a massbank record object from a string
232 ## Input : $string
233 ## Output : $orecord
234 ## Usage : my ( $orecord ) = initRecordObject ( $string ) ;
235
236 =cut
237 ## START of SUB
238 sub initRecordObject {
239 ## Retrieve Values
240 my $self = shift ;
241 my ( $string ) = @_;
242 my ( %orecord ) = ( () ) ;
243
244 if (defined $string) {
245 my $pkcheck = 0 ;
246 my (@mzs, @int, @relint) = ( (), (), () ) ;
247 my @features = split(/\n/, $string) ;
248
249 foreach (@features) {
250 ## for all key:value
251 ## todo : known issue with "COMMENT" part (wrong split)
252 if ($_ =~ /(.+):(.+)/) {
253 my ($key, $string) = ($1, $2 );
254 $string =~ s/^\s+|\s+$//g;
255 $orecord{$key} = $string ;
256 if ($key =~/^PK\$PEAK/) {
257 $pkcheck = 1 ;
258 (@mzs, @int, @relint) = ( (), (), () ) ;
259 }
260 }
261 elsif ($pkcheck == 1) {
262 ## case 01 : m/z int. rel.int.
263 if ($_ =~ /\s+(.+)\s+(.+)\s+(.+)/) {
264 push (@mzs, $1) ; push (@int, $2) ; push (@relint, $3) ;
265 }
266 }
267 }
268 ## init mzs, int and relint
269 my %tmp = () ;
270 $tmp{'mz'} = \@mzs ;
271 $tmp{'int'} = \@int ;
272 $tmp{'relint'} = \@relint ;
273 $orecord{'PK$PEAK'} = \%tmp ;
274 }
275 else {
276 warn "The given massbank string is undef\n" ;
277 }
278
279 return (\%orecord) ;
280 }
281 ### END of SUB
282
283 =head2 METHOD getRecordInfoId
284
285 ## Description : get the Id value in the massbank info string
286 ## Input : $orecord
287 ## Output : $orecord
288 ## Usage : my ( $orecord ) = getRecordInfoId ( $record ) ;
289
290 =cut
291 ## START of SUB
292 sub getRecordInfoId {
293 ## Retrieve Values
294 my $self = shift ;
295 my ( $orecord ) = @_;
296
297 my $id = undef ;
298 if ($orecord->{'ACCESSION'}) { $id = $orecord->{'ACCESSION'} ; }
299 else { $id = 'NA' ; }
300 return (\$id) ;
301 }
302 ### END of SUB
303
304
305
306
307
308 =head2 METHOD getPeakFromId
309
310 ## Description : Get the peak data of MassBank records specified by Record IDs.
311 ## Input : $ids
312 ## Ouput :
313 ## Usage : my ($pks) = getPeak($soap, $ids) ;
314
315 =cut
316
317 sub getPeak() {
318 ## Retrieve Values
319 my $self = shift ;
320 my ($osoap, $ids) = @_;
321 my (@dat, @ids, @dats) = ( (), () );
322 @ids = @{$ids} ;
323
324 foreach my $id ( @ids ) {
325 push(@dat, SOAP::Data -> name('ids' => $id));
326 }
327
328 my $data = SOAP::Data -> value(@dat);
329 my $som = $osoap -> getPeak($data) ;
330
331 ## DETECTING A SOAP FAULT OR NOT
332 if ($som->fault) { @dats = $som->faultdetail ; }
333 else { @dats = $som->valueof('//return') ; }
334
335 # print Dumper $som->valueof('//return') ;
336 return(\@dats) ;
337 }
338
339 =head2 METHOD searchSpectrum
340
341 ## Description : Get the response equivalent to the "Spectrum Search" results.
342 ## Input : $osoap, $pcgroup_id, $mzs, $intensities, $ion, $instruments, $max, $unit, $tol, $cutoff
343 ## Ouput : $spectra, $numspectra
344 ## Usage : ($spectra, $numspectra) = searchSpectrum($osoap, $mzs, $intensities, $ion, $instruments, $max, $unit, $tol, $cutoff) ;
345
346 =cut
347
348 sub searchSpectrum() {
349 ## Retrieve Values
350 my $self = shift ;
351 my ($osoap, $pcgroup_id , $mzs, $intensities, $ion, $instruments, $max, $unit, $tol, $cutoff) = @_;
352
353 # init in case :
354 $ion = 'both' if ( !defined $ion ) ;
355 $instruments = ['all'] if ( !defined $instruments ) ;
356 $max = 0 if ( !defined $max ) ;
357 $unit = 'unit' if ( !defined $unit ) ;
358 $cutoff = 5 if ( !defined $cutoff ) ;
359 if ( !defined $tol ) {
360 if ( $unit eq 'unit' ) { $tol = 0.3 ; }
361 else { $tol = 50 ; }
362 }
363
364 my @dats = () ;
365 my %ret = (); # %ret = {'res' => [], 'num_res' => int, 'pcgroup_id'=> int }
366 my $numdats = 0 ;
367
368 if ( defined $mzs ) {
369 my $nb_mzs = scalar (@{$mzs}) ;
370
371 if ( $nb_mzs > 0 ) {
372
373 my @mzs = @{$mzs} ;
374 my @ints = @{$intensities} ;
375 my ( @dat1, @dat2 ) = ( (), () ) ;
376 my $i = 0 ;
377
378 foreach my $mz (@mzs) {
379 push(@dat1, SOAP::Data -> name('mzs' => $mz) );
380 push(@dat2, SOAP::Data -> name('intensities' => $ints[$i]) );
381 $i++ ;
382 }
383
384 push(@dat2, SOAP::Data -> name('unit' => $unit) ) ;
385 push(@dat2, SOAP::Data -> name('tolerance' => $tol) ) ;
386 push(@dat2, SOAP::Data -> name('cutoff' => $cutoff) ) ;
387
388 foreach my $ins ( @{$instruments} ) {
389 push(@dat2, SOAP::Data -> name('instrumentTypes' => $ins));
390 }
391 push(@dat2, SOAP::Data -> name('ionMode' => $ion));
392 push(@dat2, SOAP::Data -> name('maxNumResults' => $max));
393
394 my $data = SOAP::Data -> value(@dat1, @dat2);
395 my $som = $osoap -> searchSpectrum($data);
396
397 ## DETECTING A SOAP FAULT OR NOT
398 if ( $som ) {
399 if ($som->fault) {
400 $ret{'fault'} = $som->faultstring; $ret{'num_res'} = -1 ;
401 }
402 else {
403 # print Dumper $som ;
404 @dats = $som->valueof('//results/[>0]');
405 $numdats = $som->valueof('//numResults') ;
406 my $i ;
407 my @res = () ;
408
409 if (!defined $numdats) { $numdats = 0 ; }
410 ## For results
411 if ($numdats > 0) {
412 ## insert nb of res
413 $ret{ 'num_res'} = $numdats ;
414 $ret{ 'pcgroup_id'} = $pcgroup_id ;
415
416 ## manage mapping for spectral features
417
418 # print Dumper @dats ; ## Bug with order depending of spectra source :
419
420 for ( $i = 0; $i < $numdats; $i ++ ) {
421 my ($exactMass, $formula, $id, $score, $title) = @dats[($i * 5) .. ($i * 5 + 4)];
422
423 ## manage issue from massbank like ID MSJ00002 and formula == 1 FROM WS
424 if ($formula eq '1') {
425 # print "-------> WS sent mixed value for $id (EM:$exactMass, F:$formula, ID:$id, SC:$score, TI:$title)\n" ;
426 my (%val) = ('id', $title, 'title', $id, 'formula', $exactMass, 'exactMass', 'NA', 'score', $score);
427 push(@res, { %val });
428 }
429 else {
430 my (%val) = ('id', $id, 'title', $title, 'formula', $formula, 'exactMass', $exactMass, 'score', $score);
431 push(@res, { %val });
432 }
433 }
434
435 ## order res by score
436 my @sorted = sort { $a->{score} <=> $b->{score} } @res;
437
438 $ret{'res'} = \@sorted;
439 }
440 ## for no results for the query
441 else {
442 $ret{ 'num_res'} = $numdats ;
443 $ret{ 'pcgroup_id'} = $pcgroup_id ;
444 my (%val) = ('id', undef, 'title', undef, 'formula', undef, 'exactMass', undef, 'score', undef);
445 push(@res, { %val });
446 $ret{'res'} = \@res;
447 }
448 }
449 }
450 else {
451 carp "The som return (from the searchSpectrum method) isn't defined\n" ; }
452 }
453 else { carp "Query MZs list is empty, MassBank soap will stop\n" ; }
454 }
455 else { carp "Query MZs list is undef, MassBank soap will stop\n" ; }
456 # print Dumper @ret ;
457 return(\%ret, $numdats) ;
458 }
459 ### END of SUB
460
461
462
463
464 #=head2 METHOD new
465 #
466 # ## Description : new
467 # ## Input : $self
468 # ## Ouput : bless $self ;
469 # ## Usage : new() ;
470 #
471 #=cut
472 #
473 #sub searchPeak() { local($soap, $mz, $max, $ion, $rel, $inst, $tol) = @_;
474 # $ion = 'both' if ( $ion eq '' );
475 # $rel += 0;
476 # $max += 0;
477 # local(@inst) = @$inst;
478 # @inst = ('all') if ( scalar(@inst) == 0 );
479 # $tol = 0.3 if ( $tol eq '' );
480 # local(@mz) = @$mz;
481 # local(@dat) = ();
482 # local($mzv);
483 # foreach $mzv ( @mz ) {
484 # push(@dat, SOAP::Data -> name('mzs' => $mzv));
485 # }
486 # push(@dat, SOAP::Data -> name('relativeIntensity' => $rel));
487 # push(@dat, SOAP::Data -> name('tolerance' => $tol));
488 # local($ins);
489 # foreach $ins ( @inst ) {
490 # push(@dat, SOAP::Data -> name('instrumentTypes' => $ins));
491 # }
492 # push(@dat, SOAP::Data -> name('ionMode' => $ion));
493 # push(@dat, SOAP::Data -> name('maxNumResults' => $max));
494 # local($data) = SOAP::Data -> value(@dat);
495 # local($som) = $soap -> searchPeak($data);
496 # local($num) = $som -> valueof('/Envelope/Body/[1]/[>0]/numResults');
497 # local(@res) = $som -> valueof('/Envelope/Body/[1]/[>0]/results/[>0]');
498 # local($i);
499 # local(@ret) = ();
500 # for ( $i = 0; $i < $num; $i ++ ) {
501 # local($mw, $form, $id, $score, $title) = @res[($i * 5) .. ($i * 5 + 4)];
502 # local(%val) = ('id', $id, 'title', $title, 'formula', $form, 'exactMass', $mw);
503 # push(@ret, { %val });
504 # }
505 # return @ret;
506 #}
507 #
508 #=head2 METHOD new
509 #
510 # ## Description : new
511 # ## Input : $self
512 # ## Ouput : bless $self ;
513 # ## Usage : new() ;
514 #
515 #=cut
516 #
517 #sub searchPeakDiff() { local($soap, $mz, $max, $ion, $rel, $inst, $tol) = @_;
518 # $ion = 'both' if ( $ion eq '' );
519 # $rel += 0;
520 # $max += 0;
521 # local(@inst) = @$inst;
522 # @inst = ('all') if ( scalar(@inst) == 0 );
523 # $tol = 0.3 if ( $tol eq '' );
524 # local(@mz) = @$mz;
525 # local(@dat) = ();
526 # local($mzv);
527 # foreach $mzv ( @mz ) {
528 # push(@dat, SOAP::Data -> name('mzs' => $mzv));
529 # }
530 # push(@dat, SOAP::Data -> name('relativeIntensity' => $rel));
531 # push(@dat, SOAP::Data -> name('tolerance' => $tol));
532 # local($ins);
533 # foreach $ins ( @inst ) {
534 # push(@dat, SOAP::Data -> name('instrumentTypes' => $ins));
535 # }
536 # push(@dat, SOAP::Data -> name('ionMode' => $ion));
537 # push(@dat, SOAP::Data -> name('maxNumResults' => $max));
538 # local($data) = SOAP::Data -> value(@dat);
539 # local($som) = $soap -> searchPeakDiff($data);
540 # local($num) = $som -> valueof('/Envelope/Body/[1]/[>0]/numResults');
541 # local(@res) = $som -> valueof('/Envelope/Body/[1]/[>0]/results/[>0]');
542 # local($i);
543 # local(@ret) = ();
544 # for ( $i = 0; $i < $num; $i ++ ) {
545 # local($mw, $form, $id, $score, $title) = @res[($i * 5) .. ($i * 5 + 4)];
546 # local(%val) = ('id', $id, 'title', $title, 'formula', $form, 'exactMass', $mw);
547 # push(@ret, { %val });
548 # }
549 # return @ret;
550 #}
551 #
552 #=head2 METHOD new
553 #
554 # ## Description : new
555 # ## Input : $self
556 # ## Ouput : bless $self ;
557 # ## Usage : new() ;
558 #
559 #=cut
560 #
561 #sub execBatchJob() { local($soap, $spectra, $ion, $inst, $mail) = @_;
562 # $ion = 'both' if ( $ion eq '' );
563 # local(@inst) = @$inst;
564 # @inst = ('all') if ( scalar(@inst) == 0 );
565 # local(%spectra) = %$spectra;
566 # local($name);
567 # local(@query) = ();
568 # foreach $name ( keys %spectra ) {
569 # local(@q) = ("Name:$name");
570 # local(%peak) = %{$spectra{$name}};
571 # local($mz, $inte);
572 # foreach $mz ( keys %peak ) {
573 # $inte = $peak{$mz};
574 # push(@q, "$mz,$inte");
575 # }
576 # push(@query, join(';', @q));
577 # }
578 # local(@dat) = ();
579 # local($q);
580 # push(@dat, SOAP::Data -> name('type' => 1));
581 # push(@dat, SOAP::Data -> name('mailAddress' => $mail));
582 # foreach $q ( @query ) {
583 # push(@dat, SOAP::Data -> name('queryStrings' => $q));
584 # }
585 # local($ins);
586 # foreach $ins ( @inst ) {
587 # push(@dat, SOAP::Data -> name('instrumentTypes' => $ins));
588 # }
589 # push(@dat, SOAP::Data -> name('ionMode' => $ion));
590 # local($data) = SOAP::Data -> value(@dat);
591 # local($som) = $soap -> execBatchJob($data);
592 # local($res) = $som -> valueof('/Envelope/Body/[1]');
593 # return ${$res}{'return'};
594 #}
595 #
596 #=head2 METHOD new
597 #
598 # ## Description : new
599 # ## Input : $self
600 # ## Ouput : bless $self ;
601 # ## Usage : new() ;
602 #
603 #=cut
604 #
605 #sub getJobStatus() { local($soap, $job) = @_;
606 # local(@dat) = ();
607 # push(@dat, SOAP::Data -> name('jobId' => $job));
608 # local($data) = SOAP::Data -> value(@dat);
609 # local($som) = $soap -> getJobStatus($data);
610 # local($res) = $som -> valueof('/Envelope/Body/[1]/[1]');
611 # local(%res) = %{$res};
612 # local($status) = $res{'status'};
613 # local($code) = $res{'statusCode'};
614 # local($date) = $res{'requestDate'};
615 # return ($status, $code, $date);
616 #}
617 #
618 #=head2 METHOD new
619 #
620 # ## Description : new
621 # ## Input : $self
622 # ## Ouput : bless $self ;
623 # ## Usage : new() ;
624 #
625 #=cut
626 #
627 #sub getJobResult() { local($soap, $job) = @_;
628 # local(@dat) = ();
629 # push(@dat, SOAP::Data -> name('jobId' => $job));
630 # local($data) = SOAP::Data -> value(@dat);
631 # local($som) = $soap -> getJobResult($data);
632 # local(@res) = $som -> valueof('/Envelope/Body/[1]/[>0]');
633 # local($n) = scalar(@res);
634 # local(@ret) = ();
635 # local($i);
636 # for ( $i = 0; $i < $n; $i ++ ) {
637 # local(%res) = %{$res[$i]};
638 # local(@res1) = $som -> valueof('/Envelope/Body/[1]/['.($i+1).']/results/[>0]');
639 # local(%ret) = ();
640 # local($qname) = $res{'queryName'};
641 # $ret{'qname'} = $qname;
642 # local($num) = $res{'numResults'};
643 # $ret{'num'} = $num;
644 # local(@ret1) = ();
645 # local($j);
646 # for ( $j = 0; $j < $num; $j ++ ) {
647 # local($mw, $form, $id, $score, $title) = @res1[($j * 5) .. ($j * 5 + 4)];
648 # local(%val) = ('id', $id, 'title', $title, 'formula', $form, 'exactMass', $mw, 'score', $score);
649 # push(@ret1, { %val });
650 # }
651 # $ret{'list'} = [ @ret1 ];
652 # push(@ret, { %ret });
653 # }
654 # return @ret;
655 #}
656
657
658 1 ;
659
660
661 __END__
662
663 =head1 SUPPORT
664
665 You can find documentation for this module with the perldoc command.
666
667 perldoc massbank_api.pm
668
669 =head1 Exports
670
671 =over 4
672
673 =item :ALL is ...
674
675 =back
676
677 =head1 AUTHOR
678
679 Franck Giacomoni E<lt>franck.giacomoni@clermont.inra.frE<gt> and marion Landi E<lt>marion.landi@clermont.inra.frE<gt>
680
681 =head1 LICENSE
682
683 This script is fully inspired by MassBank SOAP API Client Package Ver-2.0 with :
684 Author: Hisayuki Horail (MassBank Group, IAB, Keio U. and JST-BIRD)
685 Home page: http://www.massbank.jp/
686 Date: 25 May 2010
687 This software is licensed
688 under a Creative Commons Attribution License 2.1 Japan License (CC-BY)
689 (http://creativecommons.org/licensesby/2.1/jp/).
690
691 This new version of this program is free software; you can redistribute it and/or modify it under the same terms as Perl itself.
692
693 =head1 VERSION
694
695 version 1 : 25 / 05 / 2010
696
697 version 2 : 04 / 06 / 2015
698
699 =cut