File Coverage

blib/lib/Bio/Metabolic/Reaction.pm
Criterion Covered Total %
statement 85 111 76.5
branch 26 42 61.9
condition 10 18 55.5
subroutine 15 19 78.9
pod 11 13 84.6
total 147 203 72.4


line stmt bran cond sub pod time code
1              
2             =head1 NAME
3              
4             Bio::Metabolic::Reaction - Perl extension for biochemical reactions
5              
6             =head1 SYNOPSIS
7              
8             use Bio::Metabolic::Reaction;
9              
10             my $r1 = Bio::Metabolic::Reaction->new('r1',[$sub1,$sub2],[$sub3,$sub4]);
11              
12             $r1->kinetics('linear');
13              
14              
15             =head1 DESCRIPTION
16              
17             This class implements objects representing a biochemical reaction.
18             A biochemical reaction in this context is defined by its input and its output
19             substrates, i.e. by two Bio::Metabolic::Network::Cluster objects.
20             Further, every instance of this class is associated with a mathematical expression
21             which determines the dynamical behaviour of the reaction, i.e. the reaction rate.
22              
23             =head2 EXPORT
24              
25             None
26              
27             =head2 OVERLOADED OPERATORS
28              
29             String Conversion
30             $string = "$reaction";
31             print "\$reaction = '$reaction'\n";
32              
33             Equality
34             if ($reaction1 == $reaction2)
35             if ($reaction1 != $reaction2)
36              
37              
38             =head1 AUTHOR
39              
40             Oliver Ebenhöh, oliver.ebenhoeh@rz.hu-berlin.de
41              
42             =head1 SEE ALSO
43              
44             Bio::Metabolic Bio::Metabolic::Substrate Bio::Metabolic::Substrate::Cluster.
45              
46             =cut
47              
48             package Bio::Metabolic::Reaction;
49              
50             require 5.005_62;
51 5     5   29 use strict;
  5         13  
  5         170  
52 5     5   24 use warnings;
  5         8  
  5         163  
53              
54             require Exporter;
55              
56 5     5   24 use Carp;
  5         9  
  5         390  
57              
58 5     5   28 use Bio::Metabolic::Substrate::Cluster;
  5         9  
  5         480  
59              
60             #use Math::Symbolic;
61              
62             use overload
63              
64             # "\"\"" => \&reaction_to_string,
65             "\"\"" => \&to_compact_string,
66             "==" => \&equals,
67 5     5   27 "!=" => sub { return 1 -equals(@_) };
  5     0   7  
  5         59  
  0         0  
68              
69             our @ISA = qw(Exporter);
70              
71             # Items to export into callers namespace by default. Note: do not export
72             # names by default without a very good reason. Use EXPORT_OK instead.
73             # Do not simply export all your public functions/methods/constants.
74              
75             # This allows declaration use Bio::Metabolic::Reaction ':all';
76             # If you do not need this, moving things directly into @EXPORT or @EXPORT_OK
77             # will save memory.
78             our %EXPORT_TAGS = (
79             'all' => [
80             qw(
81              
82             )
83             ]
84             );
85              
86             our @EXPORT_OK = ( @{ $EXPORT_TAGS{'all'} } );
87              
88             our @EXPORT = qw(
89              
90             );
91              
92             our %OutputFormat = (
93             -1 => "%20s",
94             1 => "%-20s"
95             );
96              
97             our $OutputArrow = " => ";
98              
99             our $VERSION = '0.06';
100              
101             #our $DEBUG = 1;
102              
103             =head1 METHODS
104              
105             =head2 Constructor new
106              
107             There are three ways to call the constructor method:
108              
109             1.) $r = Bio::Metabolic::Reaction->new($name, $inlist, $outlist);
110              
111             Here, the first argument must hold the name. The following two arguments
112             provide arrayrefs of Bio::Metabolic::Substrate objects, defining the input and
113             output substrates of the biochemical reaction.
114             If a reactant occurs twice (e.g. X + X -> Y), it has to appear twice in the
115             corresponding list.
116              
117             2.) $r = Bio::Metabolic::Reaction->new($name, $substrates, $coefficients)
118              
119             The first argument must specify the name. The second argument can be an
120             arrayref of Bio::Metabolic::Substrate objects or a Bio::Metabolic::Substrate::Cluster
121             object, defining all participating reactants.
122             The third argument must hold numbers specifying the multiplicity of the
123             reactants in the same order as the reactants have been specified.
124              
125             Example: Let $X and $Y be Bio::Metabolic::Substrate objects defining the
126             reactants X and Y. The reaction X + X -> Y can be defined either by
127              
128             $r1 = Bio::Metabolic::Reaction->new('r1', [$X,$X], [$Y]);
129              
130             or by
131              
132             $r2 = Bio::Metabolic::Reaction->new('r2', [$X,$Y], [-2,1]);
133              
134             3.) The constructor can be called as an object method, using another reaction as
135             template: $r2 = $r1->new().
136              
137             =cut
138              
139             sub new { # defines a new reaction.
140 6     6 1 39 my $proto = shift;
141 6   66     37 my $pkg = ref($proto) || $proto;
142              
143 6 100       25 my %attr = ref($proto) eq 'Bio::Metabolic::Reaction' ? %$proto : ();
144              
145 6         11 my $name = shift;
146              
147 6 100       20 $attr{name} = $name if defined $name;
148 6 50       19 croak("name must be specified in constructor new()")
149             unless defined $attr{name};
150              
151             # my ($insubs,$outsubs) = @_;
152 6         8 my $insubs = shift;
153 6         6 my $outsubs = shift;
154 6 100 66     127 if ( defined $outsubs
    100 100        
155             && ref($outsubs) eq 'ARRAY'
156             && join( '', @$outsubs ) =~ /^[0-9\-\.]*$/ )
157             {
158              
159             # list with stoichiometric coefficients
160 1 50       8 $attr{substrates} =
161             ref($insubs) eq 'Bio::Metabolic::Substrate::Cluster'
162             ? $insubs
163             : Bio::Metabolic::Substrate::Cluster->new(@$insubs);
164 1         6 my @slist = $attr{substrates}->list;
165              
166 1 50       5 croak(
167             "numbers of substrates and stoichiometric coefficients don't agree in constructor new()"
168             )
169             unless @slist == @$outsubs;
170              
171 1         4 $attr{stoichiometry} = { map( ( $_->name, 0 ), @slist ) };
172 1         5 for ( my $i = 0 ; $i < @slist ; $i++ ) {
173 3         9 $attr{stoichiometry}->{ $slist[$i]->name } = $outsubs->[$i];
174             }
175             }
176             elsif ( defined $insubs ) {
177 4         21 $attr{substrates} =
178             Bio::Metabolic::Substrate::Cluster->new( @$insubs, @$outsubs );
179              
180 4         15 my %tmphash = ( -1 => $insubs, 1 => $outsubs );
181 4         17 while ( my ( $dir, $list ) = each %tmphash ) {
182 8         15 foreach my $subs (@$list) {
183 9         29 $attr{stoichiometry}->{ $subs->name } += $dir;
184             }
185             }
186             }
187              
188             # $attr{-1} = Bio::Metabolic::Substrate::Cluster->new(@$insubs) if @$insubs;
189             # croak ("in-metabolites have to be specified in constructor new()") unless defined $attr->{-1};
190             # $attr{1} = Bio::Metabolic::Substrate::Cluster->new(@$insubs) if @$outsubs;
191             # croak ("out-metabolites have to be specified in constructor new()") unless defined $attr->{1};
192              
193             croak(
194 6 50 33     45 "participating compounds have not been specified in constructor new()")
195             unless defined $attr{substrates} && defined $attr{stoichiometry};
196              
197 6 50       19 my %extra_attr = @_ ? %{ shift() } : ();
  0         0  
198              
199 6         37 my $new_reaction = bless {
200             %attr,
201             'parameters' => {},
202             'rate' => undef,
203             %extra_attr,
204             }, $pkg;
205              
206 6         27 return $new_reaction;
207             }
208              
209             =head2 Method copy
210              
211             copy() is exactly the same as $r2 = $r1->new();
212              
213             =cut
214              
215             sub copy {
216 0     0 1 0 return shift->new();
217             }
218              
219             =head2 Method name
220              
221             Optional argument: sets the object's name. Returns the object's name.
222              
223             =cut
224              
225             sub name {
226 1     1 1 608 my $self = shift;
227 1 50       4 $self->{name} = shift if @_;
228 1         57 return $self->{name};
229             }
230              
231             =head2 Method substrates
232              
233             Returns all participating compounds as a Bio::Metabolic::Substrate::Cluster object.
234             Optional argument: sets the substrates.
235              
236             =cut
237              
238             sub substrates {
239 13     13 1 18 my $self = shift;
240 13 50       35 $self->{substrates} = shift if @_;
241 13         46 return $self->{substrates};
242             }
243              
244             =head2 Method stoichiometry
245              
246             Returns a hashref. Keys are the substrate names, values the stoichiometric
247             coefficients (negative for input substrates, positive for output substrates).
248             It the absolute value differs from one, the corresponding substrate is
249             consumed/produced more than once.
250             Optional argument: sets the stoichiometries.
251              
252             =cut
253              
254             sub stoichiometry {
255 54     54 1 58 my $self = shift;
256 54 50       112 $self->{stoichiometry} = shift if @_;
257 54         176 return $self->{stoichiometry};
258             }
259              
260             =head2 Method st_coefficient
261              
262             Argument must be a substrate. Returns the stoichiometric coefficient
263             (cf. method stoichiometry()) of the specified substrate.
264              
265             =cut
266              
267             sub st_coefficient {
268 53     53 1 601 my $self = shift;
269 53         56 my $substrate = shift;
270 53         83 return $self->stoichiometry->{ $substrate->name };
271             }
272              
273             =head2 Method in
274              
275             Returns the input substrates as a Bio::Metabolic::Substrate::Cluster object.
276              
277             =cut
278              
279             sub in {
280 5     5 1 532 my $self = shift;
281 5         20 my @slist = $self->substrates->list;
282 5 100       20 my @inlist = map ( $self->st_coefficient($_) < 0 ? ($_) : (), @slist );
283              
284 5         21 return Bio::Metabolic::Substrate::Cluster->new(@inlist);
285              
286             # return shift->{-1};
287             }
288              
289             =head2 Method out
290              
291             Returns the output substrates as a Bio::Metabolic::Substrate::Cluster object.
292              
293             =cut
294              
295             sub out {
296 5     5 1 9 my $self = shift;
297 5         12 my @slist = $self->substrates->list;
298 5 100       18 my @outlist = map ( $self->st_coefficient($_) > 0 ? ($_) : (), @slist );
299              
300 5         23 return Bio::Metabolic::Substrate::Cluster->new(@outlist);
301              
302             # return shift->{1};
303             }
304              
305             =head2 Method dir
306              
307             Take one parameter which must be -1 or 1. Returns the input or output
308             substrates, respectively.
309              
310             =cut
311              
312             sub dir {
313 4     4 1 7 my $reaction = shift;
314 4         6 my $dir = shift;
315              
316 4 50 66     21 croak("Direction must be either -1 our 1") unless $dir == -1 || $dir == 1;
317              
318 4 100       12 return $dir == -1 ? $reaction->in : $reaction->out;
319             }
320              
321             =head2 Method get_substrate_list
322              
323             Returns input and output substrates as one list.
324              
325             =cut
326              
327             sub get_substrate_list {
328 0     0 1 0 my $reaction = shift;
329              
330 0         0 return $reaction->substrates->list;
331              
332             # return (@{$reaction->{-1}},@{$reaction->{1}});
333             }
334              
335             #sub substrates {
336             # return Bio::Metabolic::Substrate::Cluster->new(shift->get_substrate_list);
337             #}
338              
339             sub reaction_to_string {
340 0     0 0 0 my $reaction = shift;
341              
342             # print "reaction_to_string called.\n";
343              
344 0         0 my $retstr;
345 0         0 my $subsdir = {
346             -1 => [],
347             1 => []
348             };
349 0         0 foreach my $dir ( -1, 1 ) {
350 0         0 foreach my $substrate ( $reaction->dir($dir)->list ) {
351 0         0 push(
352 0         0 @{ $subsdir->{$dir} },
353             sprintf( $OutputFormat{$dir}, "$substrate" )
354             );
355             }
356             }
357 0         0 my $dir;
358 0         0 my $bstr = $OutputArrow;
359 0   0     0 while ( @{ $subsdir->{-1} } || @{ $subsdir->{1} } ) {
  0         0  
  0         0  
360 0         0 my $left =
361 0         0 @{ $subsdir->{-1} }
362 0 0       0 ? shift( @{ $subsdir->{-1} } )
363             : sprintf( $OutputFormat{-1}, "" );
364 0         0 my $right =
365 0         0 @{ $subsdir->{1} }
366 0 0       0 ? shift( @{ $subsdir->{1} } )
367             : sprintf( $OutputFormat{1}, "" );
368 0         0 $retstr .= $left . $bstr . $right . "\n";
369 0         0 $bstr =~ s/./ /g;
370              
371             # print $retstr;
372             }
373 0         0 return $retstr;
374             }
375              
376             sub to_compact_string {
377 2     2 0 3 my $reaction = shift;
378              
379 2         3 my $retstr;
380 2         10 my $subsdir = {
381             -1 => [],
382             1 => []
383             };
384 2         7 foreach my $dir ( -1, 1 ) {
385 4         10 foreach my $substrate ( $reaction->dir($dir)->list ) {
386 5         12 for (
387             my $i = 1 ;
388             $i <= abs( $reaction->st_coefficient($substrate) ) ;
389             $i++
390             )
391             {
392 6         6 push( @{ $subsdir->{$dir} }, "$substrate" );
  6         19  
393             }
394             }
395             }
396              
397             $retstr =
398 2         8 join( "+", @{ $subsdir->{-1} } ) . "->"
  2         5  
399 2         3 . join( "+", @{ $subsdir->{1} } ) . "\n";
400              
401             # if ( defined( $reaction->rate ) ) {
402             # $retstr .= "rate: " . $reaction->rate . "\n";
403             # foreach my $param ( keys( %{ $reaction->parameters } ) ) {
404             # if ( ref( $reaction->parameter($param) )
405             # && ref( $reaction->parameter($param) ) eq
406             # 'Math::Symbolic::Variable'
407             # && defined $reaction->parameter($param)->value )
408             # {
409             # $retstr .= "\t"
410             # . $reaction->parameter($param) . "="
411             # . $reaction->parameter($param)->value . "\n";
412             # }
413             # }
414             # }
415              
416 2         19 return $retstr;
417             }
418              
419             =head2 Method equals()
420              
421             compares two Bio::Metabolic::Reaction objects.
422             Returns 1 if all substrates occur with the same stoichiometric coefficient,
423             0 otherwise.
424              
425             =cut
426              
427             sub equals {
428 1     1 1 4 my ( $r1, $r2 ) = @_;
429              
430 1         4 my $sl1 = $r1->substrates;
431 1         3 my $sl2 = $r2->substrates;
432              
433 1         4 my @sl1 = $sl1->list;
434 1         4 my @sl2 = $sl2->list;
435              
436 1 50       5 return 0 unless @sl1 == @sl2;
437              
438 1         3 foreach my $sub (@sl1) {
439 3 50       8 return 0 unless $sl2->has($sub);
440 3 50       8 return 0 unless $r1->st_coefficient($sub) == $r2->st_coefficient($sub);
441             }
442              
443 1         5 return 1;
444             }
445              
446             1;
447             __END__