[Bio] / FigKernelPackages / FIGMODELmodel.pm Repository:
ViewVC logotype

Diff of /FigKernelPackages/FIGMODELmodel.pm

Parent Directory Parent Directory | Revision Log Revision Log | View Patch Patch

revision 1.2, Fri Dec 11 21:37:02 2009 UTC revision 1.24, Mon Jul 26 06:21:14 2010 UTC
# Line 1  Line 1 
 package FIGMODELmodel;  
1  use strict;  use strict;
2    package FIGMODELmodel;
3    
4  =head1 FIGMODELmodel object  =head1 FIGMODELmodel object
5  =head2 Introduction  =head2 Introduction
# Line 13  Line 13 
13          This is the constructor for the FIGMODELmodel object.          This is the constructor for the FIGMODELmodel object.
14  =cut  =cut
15  sub new {  sub new {
16          my ($class,$figmodel,$id) = @_;          my ($class,$figmodel,$id,$metagenome) = @_;
17          #Error checking first          #Error checking first
18          if (!defined($figmodel)) {          if (!defined($figmodel)) {
19                  print STDERR "FIGMODELmodel->new(undef,".$id."):figmodel must be defined to create a model object!\n";                  print STDERR "FIGMODELmodel->new(undef,".$id."):figmodel must be defined to create a model object!\n";
# Line 25  Line 25 
25                  $self->figmodel()->error_message("FIGMODELmodel->new(figmodel,undef):id must be defined to create a model object");                  $self->figmodel()->error_message("FIGMODELmodel->new(figmodel,undef):id must be defined to create a model object");
26                  return undef;                  return undef;
27          }          }
   
28          #Checking that the id exists          #Checking that the id exists
29          my $tbl = $self->figmodel()->database()->GetDBTable("MODELS");          if (!defined($metagenome) || $metagenome != 1) {
30          if (!defined($tbl)) {                  my $modelHandle = $self->figmodel()->database()->get_object_manager("model");
31                  $self->figmodel()->error_message("FIGMODELmodel->new(figmodel,".$id."):could not load MODELS table. Check database!");                  if (defined($modelHandle)) {
32                  return undef;                          #If the id is a number, we get the model row by index
33                            if ($id =~ m/^\d+$/) {
34                                    my $objects = $modelHandle->get_objects();
35                                    if (defined($objects->[$id])) {
36                                            $self->{_data} = $objects->[$id];
37                                            $self->figmodel()->{_models}->{$id} = $self;
38          }          }
39                            } else {
40                                    my $objects = $modelHandle->get_objects({id => $id});
41                                    if (defined($objects->[0])) {
42                                            $self->{_data} = $objects->[0];
43                                    } elsif (!defined($objects->[0]) && $id =~ m/(.+)(V[^V]+)/) {
44                                            $objects = $modelHandle->get_objects({id => $1});
45                                            if (defined($objects->[0])) {
46                                                    $self->{_selectedversion} = $2;
47                                                    $self->{_data} = $objects->[0];
48                                            }
49                                    }
50                            }
51                    }
52                    if (defined($self->{_data})) {
53                            $self->{_modeltype} = "genome";
54                    }
55            }
56            if (!defined($self->{_data})) {
57                    my $modelHandle = $self->figmodel()->database()->get_object_manager("mgmodel");
58                    if (defined($modelHandle)) {
59          #If the id is a number, we get the model row by index          #If the id is a number, we get the model row by index
         my $index = $id;  
60          if ($id =~ m/^\d+$/) {          if ($id =~ m/^\d+$/) {
61                  $self->{_data} = $tbl->get_row($id);                                  my $objects = $modelHandle->get_objects();
62                                    if (defined($objects->[$id])) {
63                                            $self->{_data} = $objects->[$id];
64                                            $self->figmodel()->{_models}->{"MG".$id} = $self;
65                                    }
66          } else {          } else {
67                  $self->{_data} = $tbl->get_row_by_key($id,"id");                                  my $objects = $modelHandle->get_objects({id => $id});
68                                    if (defined($objects->[0])) {
69                                            $self->{_data} = $objects->[0];
70                                    } elsif (!defined($objects->[0]) && $id =~ m/(.+)(V[^V]+)/) {
71                                            $objects = $modelHandle->get_objects({id => $1});
72                                            if (defined($objects->[0])) {
73                                                    $self->{_selectedversion} = $2;
74                                                    $self->{_data} = $objects->[0];
75                                            }
76                                    }
77                            }
78                    }
79                  if (defined($self->{_data})) {                  if (defined($self->{_data})) {
80                          $index = $tbl->row_index($self->{_data});                          $self->{_modeltype} = "metagenome";
81                  }                  }
82          }          }
83          if (!defined($self->{_data})) {          if (!defined($self->{_data})) {
84                  $self->figmodel()->error_message("FIGMODELmodel->new(figmodel,".$id."):could not find specified id in database!");                  $self->figmodel()->error_message("FIGMODELmodel->new(figmodel,".$id."):could not find model ".$id." in database!");
85                  return undef;                  return undef;
86          }          }
         $self->{_index} = $index;  
87          $self->figmodel()->{_models}->{$self->id()} = $self;          $self->figmodel()->{_models}->{$self->id()} = $self;
         $self->figmodel()->{_models}->{$self->index()} = $self;  
   
88          return $self;          return $self;
89  }  }
90    
# Line 107  Line 141 
141  =cut  =cut
142  sub fig {  sub fig {
143          my ($self) = @_;          my ($self) = @_;
   
144          if (!defined($self->{_fig}) && $self->source() !~ /^MGRAST/) {          if (!defined($self->{_fig}) && $self->source() !~ /^MGRAST/) {
145                  if ($self->source() =~ /^RAST/) {                  if ($self->source() =~ /^RAST/) {
146                          $self->{"_fig"} = $self->figmodel()->fig();#$self->genome());                          $self->{"_fig"} = $self->figmodel()->fig();#$self->genome());
# Line 115  Line 148 
148                          $self->{"_fig"} = $self->figmodel()->fig();                          $self->{"_fig"} = $self->figmodel()->fig();
149                  }                  }
150          }          }
   
151          return $self->{"_fig"};          return $self->{"_fig"};
152  }  }
153    
154    =head3 aquireModelLock
155    
156    Definition:
157    
158            FIGMODELmodel->aquireModelLock();
159    
160    Description:
161    
162            Locks the database for alterations relating to the current model object
163    
164    =cut
165    sub aquireModelLock {
166            my ($self) = @_;
167            $self->figmodel()->database()->genericLock($self->id());
168    }
169    
170    =head3 releaseModelLock
171    
172    Definition:
173    
174            FIGMODELmodel->releaseModelLock();
175    
176    Description:
177    
178            Unlocks the database for alterations relating to the current model object
179    
180    =cut
181    sub releaseModelLock {
182            my ($self) = @_;
183            $self->figmodel()->database()->genericUnlock($self->id());
184    }
185    
186  =head3 mgdata  =head3 mgdata
187  Definition:  Definition:
188          FIGMODEL = FIGMODELmodel->mgdata();          FIGMODEL = FIGMODELmodel->mgdata();
# Line 127  Line 191 
191  =cut  =cut
192  sub mgdata {  sub mgdata {
193          my ($self) = @_;          my ($self) = @_;
194            if (!defined($self->{_mgdata})) {
195          if (!defined($self->{_mgdata}) && $self->source() =~ /^MGRAST/) {                  my $mgrastdbhandle = $self->figmodel()->database()->get_object_manager("mgjob");
196                  require MGRAST;                  my $objects = $mgrastdbhandle->get_objects( { 'genome_id' => $self->genome() } );
197                  $self->{_mgdata} = $self->figmodel()->mgrast()->Job->get_objects( { 'genome_id' => $self->genome() } )                  $self->{_mgdata} = $objects->[0];
198          }          }
   
199          return $self->{_mgdata};          return $self->{_mgdata};
200  }  }
201    
# Line 144  Line 207 
207  =cut  =cut
208  sub id {  sub id {
209          my ($self) = @_;          my ($self) = @_;
210          return $self->{_data}->{id}->[0];          return $self->{_data}->id();
211  }  }
212    
213  =head3 owner  =head3 get_model_type
214  Definition:  Definition:
215          string = FIGMODELmodel->owner();          string = FIGMODELmodel->get_model_type();
216  Description:  Description:
217          Returns the username for the model owner          Returns the type of the model
218  =cut  =cut
219  sub owner {  sub get_model_type {
220          my ($self) = @_;          my ($self) = @_;
221          return $self->{_data}->{owner}->[0];          return $self->{_modeltype};
222  }  }
223    
224  =head3 index  =head3 owner
225  Definition:  Definition:
226          string = FIGMODELmodel->index();          string = FIGMODELmodel->owner();
227  Description:  Description:
228          Returns model index          Returns the username for the model owner
229  =cut  =cut
230  sub index {  sub owner {
231          my ($self) = @_;          my ($self) = @_;
232          return $self->{_index};          return $self->{_data}->owner();
233  }  }
234    
235  =head3 name  =head3 name
# Line 185  Line 248 
248                          if (defined($self->mgdata())) {                          if (defined($self->mgdata())) {
249                                  $self->{_name} = $self->mgdata()->genome_name;                                  $self->{_name} = $self->mgdata()->genome_name;
250                          }                          }
                 } elsif (defined($self->stats())) {  
                         $self->{_name} = $self->stats()->{'Organism name'}->[0];  
251                  } elsif ($source !~ /^RAST/) {                  } elsif ($source !~ /^RAST/) {
252                          $self->{_name} = $self->fig()->orgname_of_orgid($self->genome());                          $self->{_name} = $self->fig()->orgname_of_orgid($self->genome());
253                    } else {
254                            $self->{_name} = $self->figmodel()->get_genome_stats($self->genome())->{NAME}->[0];
255                  }                  }
256          }          }
257    
258          return $self->{_name};          return $self->{_name};
259  }  }
260    
 =head3 stats  
 Definition:  
         string = FIGMODELmodel->stats();  
 Description:  
         Returns model stats  
 =cut  
 sub stats {  
         my ($self) = @_;  
   
         if (!defined($self->{_stats})) {  
                 $self->{_stats} = $self->figmodel()->database()->GetDBTable("MODEL STATS")->get_row_by_key($self->id(),"Model ID");  
         }  
         return $self->{_stats};  
 }  
   
261  =head3 get_reaction_class  =head3 get_reaction_class
262  Definition:  Definition:
263          string = FIGMODELmodel->get_reaction_class(string::reaction ID);          string = FIGMODELmodel->get_reaction_class(string::reaction ID);
# Line 217  Line 265 
265          Returns reaction class          Returns reaction class
266  =cut  =cut
267  sub get_reaction_class {  sub get_reaction_class {
268          my ($self,$reaction,$nohtml) = @_;          my ($self,$reaction,$nohtml,$brief_flux) = @_;
269    
270          if (!-e $self->directory()."ReactionClassification-".$self->id().".tbl") {          if (!-e $self->directory()."ReactionClassification-".$self->id().".tbl") {
271                  if (!defined($self->{_reaction_classes})) {                  if (!defined($self->{_reaction_classes})) {
# Line 230  Line 278 
278                  my $ClassRow = $self->{_reaction_classes}->get_row_by_key($reaction,"REACTION");                  my $ClassRow = $self->{_reaction_classes}->get_row_by_key($reaction,"REACTION");
279                  if (defined($ClassRow) && defined($ClassRow->{CLASS})) {                  if (defined($ClassRow) && defined($ClassRow->{CLASS})) {
280                          my $class;                          my $class;
281                            my $min = $ClassRow->{MIN}->[0];
282                            my $max = $ClassRow->{MAX}->[0];
283                          if ($ClassRow->{CLASS}->[0] eq "Positive") {                          if ($ClassRow->{CLASS}->[0] eq "Positive") {
284                                  $class = "Essential =>";                                  $class = "Essential =>";
285                                    $brief_flux ? $class.="<br>[Flux: ".sprintf("%.3g",$min)." to ".sprintf("%.3g",$max)."]<br>" : $class.="<br>[Flux: ".$min." to ".$max."]<br>";
286                          } elsif ($ClassRow->{CLASS}->[0] eq "Negative") {                          } elsif ($ClassRow->{CLASS}->[0] eq "Negative") {
287                                  $class = "Essential <=";                                  $class = "Essential <=";
288                                    $brief_flux ? $class.="<br>[Flux: ".sprintf("%.3g",$min)." to ".sprintf("%.3g",$max)."]<br>" : $class.="<br>[Flux: ".$min." to ".$max."]<br>";
289                          } elsif ($ClassRow->{CLASS}->[0] eq "Positive variable") {                          } elsif ($ClassRow->{CLASS}->[0] eq "Positive variable") {
290                                  $class = "Active =>";                                  $class = "Active =>";
291                                    $brief_flux ? $class.="<br>[Flux: ".sprintf("%.3g",$min)." to ".sprintf("%.3g",$max)."]<br>" : $class.="<br>[Flux: ".$min." to ".$max."]<br>";
292                          } elsif ($ClassRow->{CLASS}->[0] eq "Negative variable") {                          } elsif ($ClassRow->{CLASS}->[0] eq "Negative variable") {
293                                  $class = "Active <=";                                  $class = "Active <=";
294                                    $brief_flux ? $class.="<br>[Flux: ".sprintf("%.3g",$min)." to ".sprintf("%.3g",$max)."]<br>" : $class.="<br>[Flux: ".$min." to ".$max."]<br>";
295                          } elsif ($ClassRow->{CLASS}->[0] eq "Variable") {                          } elsif ($ClassRow->{CLASS}->[0] eq "Variable") {
296                                  $class = "Active <=>";                                  $class = "Active <=>";
297                                    $brief_flux ? $class.="<br>[Flux: ".sprintf("%.3g",$min)." to ".sprintf("%.3g",$max)."]<br>" : $class.="<br>[Flux: ".$min." to ".$max."]<br>";
298                          } elsif ($ClassRow->{CLASS}->[0] eq "Blocked") {                          } elsif ($ClassRow->{CLASS}->[0] eq "Blocked") {
299                                  $class = "Inactive";                                  $class = "Inactive";
300                          } elsif ($ClassRow->{CLASS}->[0] eq "Dead") {                          } elsif ($ClassRow->{CLASS}->[0] eq "Dead") {
301                                  $class = "Disconnected";                                  $class = "Disconnected";
302                          }                          }
303    
304                          if (!defined($nohtml) || $nohtml ne "1") {                          if (!defined($nohtml) || $nohtml ne "1") {
305                                  $class = "<span title=\"Flux:".$ClassRow->{MIN}->[0]." to ".$ClassRow->{MAX}->[0]."\">".$class."</span>";                                  $class = "<span title=\"Flux:".$min." to ".$max."\">".$class."</span>";
306                          }                          }
307    
308                          return $class;                          return $class;
309                  }                  }
310                  return undef;                  return undef;
# Line 268  Line 325 
325                                  $classstring .= "<br>";                                  $classstring .= "<br>";
326                          }                          }
327                          my $NewClass;                          my $NewClass;
328                            my $min = $ClassRow->{MIN}->[$i];
329                            my $max = $ClassRow->{MAX}->[$i];
330                          if ($ClassRow->{CLASS}->[$i] eq "Positive") {                          if ($ClassRow->{CLASS}->[$i] eq "Positive") {
331                                  $NewClass = $ClassRow->{MEDIA}->[$i].":Essential =>";                                  $NewClass = $ClassRow->{MEDIA}->[$i].":Essential =>";
332                                  if (!defined($nohtml) || $nohtml ne "1") {                                  $brief_flux ? $NewClass.="<br>[Flux: ".sprintf("%.3g",$min)." to ".sprintf("%.3g",$max)."]<br>" : $NewClass.="<br>[Flux: ".$min." to ".$max."]<br>";
                                         $NewClass = "<span title=\"Flux:".$ClassRow->{MIN}->[$i]." to ".$ClassRow->{MAX}->[$i]."\">".$NewClass."</span>";  
                                 }  
333                          } elsif ($ClassRow->{CLASS}->[$i] eq "Negative") {                          } elsif ($ClassRow->{CLASS}->[$i] eq "Negative") {
334                                  $NewClass = $ClassRow->{MEDIA}->[$i].":Essential <=";                                  $NewClass = $ClassRow->{MEDIA}->[$i].":Essential <=";
335                                  if (!defined($nohtml) || $nohtml ne "1") {                                  $brief_flux ? $NewClass.="<br>[Flux: ".sprintf("%.3g",$min)." to ".sprintf("%.3g",$max)."]<br>" : $NewClass.="<br>[Flux: ".$min." to ".$max."]<br>";
                                         $NewClass = "<span title=\"Flux:".$ClassRow->{MIN}->[$i]." to ".$ClassRow->{MAX}->[$i]."\">".$NewClass."</span>";  
                                 }  
336                          } elsif ($ClassRow->{CLASS}->[$i] eq "Positive variable") {                          } elsif ($ClassRow->{CLASS}->[$i] eq "Positive variable") {
337                                  $NewClass = $ClassRow->{MEDIA}->[$i].":Active =>";                                  $NewClass = $ClassRow->{MEDIA}->[$i].":Active =>";
338                                  if (!defined($nohtml) || $nohtml ne "1") {                                  $brief_flux ? $NewClass.="<br>[Flux: ".sprintf("%.3g",$min)." to ".sprintf("%.3g",$max)."]<br>" : $NewClass.="<br>[Flux: ".$min." to ".$max."]<br>";
                                         $NewClass = "<span title=\"Flux:".$ClassRow->{MIN}->[$i]." to ".$ClassRow->{MAX}->[$i]."\">".$NewClass."</span>";  
                                 }  
339                          } elsif ($ClassRow->{CLASS}->[$i] eq "Negative variable") {                          } elsif ($ClassRow->{CLASS}->[$i] eq "Negative variable") {
340                                  $NewClass = $ClassRow->{MEDIA}->[$i].":Active <=";                                  $NewClass = $ClassRow->{MEDIA}->[$i].":Active <=";
341                                  if (!defined($nohtml) || $nohtml ne "1") {                                  $brief_flux ? $NewClass.="<br>[Flux: ".sprintf("%.3g",$min)." to ".sprintf("%.3g",$max)."]<br>" : $NewClass.="<br>[Flux: ".$min." to ".$max."]<br>";
                                         $NewClass = "<span title=\"Flux:".$ClassRow->{MIN}->[$i]." to ".$ClassRow->{MAX}->[$i]."\">".$NewClass."</span>";  
                                 }  
342                          } elsif ($ClassRow->{CLASS}->[$i] eq "Variable") {                          } elsif ($ClassRow->{CLASS}->[$i] eq "Variable") {
343                                  $NewClass = $ClassRow->{MEDIA}->[$i].":Active <=>";                                  $NewClass = $ClassRow->{MEDIA}->[$i].":Active <=>";
344                                  if (!defined($nohtml) || $nohtml ne "1") {                                  $brief_flux ? $NewClass.="<br>[Flux: ".sprintf("%.3g",$min)." to ".sprintf("%.3g",$max)."]<br>" : $NewClass.="<br>[Flux: ".$min." to ".$max."]<br>";
                                         $NewClass = "<span title=\"Flux:".$ClassRow->{MIN}->[$i]." to ".$ClassRow->{MAX}->[$i]."\">".$NewClass."</span>";  
                                 }  
345                          } elsif ($ClassRow->{CLASS}->[$i] eq "Blocked") {                          } elsif ($ClassRow->{CLASS}->[$i] eq "Blocked") {
346                                  $NewClass = $ClassRow->{MEDIA}->[$i].":Inactive";                                  $NewClass = $ClassRow->{MEDIA}->[$i].":Inactive";
                                 if (!defined($nohtml) || $nohtml ne "1") {  
                                         $NewClass = "<span title=\"Flux:".$ClassRow->{MIN}->[$i]." to ".$ClassRow->{MAX}->[$i]."\">".$NewClass."</span>";  
                                 }  
347                          } elsif ($ClassRow->{CLASS}->[$i] eq "Dead") {                          } elsif ($ClassRow->{CLASS}->[$i] eq "Dead") {
348                                  $NewClass = $ClassRow->{MEDIA}->[$i].":Disconnected";                                  $NewClass = $ClassRow->{MEDIA}->[$i].":Disconnected";
                                 if (!defined($nohtml) || $nohtml ne "1") {  
                                         $NewClass = "<span title=\"Flux:".$ClassRow->{MIN}->[$i]." to ".$ClassRow->{MAX}->[$i]."\">".$NewClass."</span>";  
349                                  }                                  }
350    
351                            if (!defined($nohtml) || $nohtml ne "1") {
352                                    $NewClass = "<span title=\"Flux:".$min." to ".$max."\">".$NewClass."</span>";
353                          }                          }
354                          $classstring .= $NewClass;                          $classstring .= $NewClass;
355                  }                  }
# Line 321  Line 368 
368    
369          if (!defined($self->{_biomass})) {          if (!defined($self->{_biomass})) {
370                  my $rxntbl = $self->reaction_table();                  my $rxntbl = $self->reaction_table();
371                    if (defined($rxntbl)) {
372                  for (my $i=0; $i < $rxntbl->size(); $i++) {                  for (my $i=0; $i < $rxntbl->size(); $i++) {
373                          if ($rxntbl->get_row($i)->{"LOAD"}->[0] =~ m/bio\d\d\d\d\d/) {                          if ($rxntbl->get_row($i)->{"LOAD"}->[0] =~ m/bio\d\d\d\d\d/) {
374                                  $self->{_biomass} = $rxntbl->get_row($i)->{"LOAD"}->[0];                                  $self->{_biomass} = $rxntbl->get_row($i)->{"LOAD"}->[0];
# Line 328  Line 376 
376                          }                          }
377                  }                  }
378          }          }
379            }
380    
381          return $self->get_reaction_data($self->{_biomass});          return $self->get_reaction_data($self->{_biomass});
382  }  }
# Line 340  Line 389 
389  =cut  =cut
390  sub get_reaction_data {  sub get_reaction_data {
391          my ($self,$reaction) = @_;          my ($self,$reaction) = @_;
   
392          if (!defined($self->reaction_table())) {          if (!defined($self->reaction_table())) {
393                  return undef;                  return undef;
394          }          }
395          if ($reaction =~ m/^\d+$/) {          if ($reaction =~ m/^\d+$/) {
396                  $self->reaction_table()->get_row($reaction);                  return $self->reaction_table()->get_row($reaction);
397          }          }
398          return $self->reaction_table()->get_row_by_key($reaction,"LOAD");          return $self->reaction_table()->get_row_by_key($reaction,"LOAD");
399  }  }
# Line 366  Line 414 
414          return $Data->{LOAD}->[0];          return $Data->{LOAD}->[0];
415  }  }
416    
417    =head3 load_model_table
418    
419    Definition: FIGMODELTable = FIGMODELmodel->load_model_table(string:table name,0/1:refresh the table));
420    
421    Description: Returns the table specified by the input filename. Table will be stored in a file in the model directory.
422    
423    =cut
424    sub load_model_table {
425            my ($self,$name,$refresh) = @_;
426            if (defined($refresh) && $refresh == 1) {
427                    delete $self->{"_".$name};
428            }
429            if (!defined($self->{"_".$name})) {
430                    my $tbldef = $self->figmodel()->config($name);
431                    if (!defined($tbldef)) {
432                            return undef;
433                    }
434                    my $itemDelim = "|";
435                    if (defined($tbldef->{itemdelimiter}->[0])) {
436                            $itemDelim = $tbldef->{itemdelimiter}->[0];
437                            if ($itemDelim eq "SC") {
438                                    $itemDelim = ";";
439                            }
440                    }
441                    my $columnDelim = "\t";
442                    if (defined($tbldef->{columndelimiter}->[0])) {
443                            $columnDelim = $tbldef->{columndelimiter}->[0];
444                            if ($columnDelim eq "SC") {
445                                    $columnDelim = ";";
446                            }
447                    }
448                    my $suffix = ".tbl";
449                    if (defined($tbldef->{filename_suffix}->[0])) {
450                            $suffix = $tbldef->{filename_suffix}->[0];
451                    }
452                    my $filename = $self->directory().$name."-".$self->id().$self->selected_version().$suffix;
453                    if (defined($tbldef->{filename_prefix}->[0])) {
454                            if ($tbldef->{filename_prefix}->[0] eq "NONE") {
455                                    $filename = $self->directory().$self->id().$self->selected_version().$suffix;
456                            } else {
457                                    $filename = $self->directory().$tbldef->{filename_prefix}->[0]."-".$self->id().$self->selected_version().$suffix;
458                            }
459                    }
460                    if (-e $filename) {
461                            $self->{"_".$name} = $self->figmodel()->database()->load_table($filename,$columnDelim,$itemDelim,$tbldef->{headingline}->[0],$tbldef->{hashcolumns});
462                    } else {
463                            if (defined($tbldef->{prefix})) {
464                                    $self->{"_".$name} = FIGMODELTable->new($tbldef->{columns},$filename,$tbldef->{hashcolumns},$columnDelim,$itemDelim,join(@{$tbldef->{prefix}},"\n"));
465                            } else {
466                                    $self->{"_".$name} = FIGMODELTable->new($tbldef->{columns},$filename,$tbldef->{hashcolumns},$columnDelim,$itemDelim);
467                            }
468                    }
469            }
470            return $self->{"_".$name};
471    }
472    
473    =head3 create_table_prototype
474    
475    Definition:
476            FIGMODELTable::table = FIGMODELmodel->create_table_prototype(string::table);
477    Description:
478            Returns a empty FIGMODELTable with all the metadata associated with the input table name
479    
480    =cut
481    sub create_table_prototype {
482            my ($self,$TableName) = @_;
483            #Checking if the table definition exists in the FIGMODELconfig file
484            my $tbldef = $self->figmodel()->config($TableName);
485            if (!defined($tbldef)) {
486                    $self->figmodel()->error_message("FIGMODELdatabase:create_table_prototype:Definition not found for ".$TableName);
487                    return undef;
488            }
489            #Checking that this is a database table
490            if (!defined($tbldef->{tabletype}) || $tbldef->{tabletype}->[0] ne "ModelTable") {
491                    $self->figmodel()->error_message("FIGMODELdatabase:create_table_prototype:".$TableName." is not a model table!");
492                    return undef;
493            }
494            #Setting default values for table parameters
495            my $prefix;
496            if (defined($tbldef->{prefix})) {
497                    $prefix = join("\n",@{$self->config($TableName)->{prefix}})."\n";
498            }
499            my $itemDelim = "|";
500            if (defined($tbldef->{itemdelimiter}->[0])) {
501                    $itemDelim = $tbldef->{itemdelimiter}->[0];
502                    if ($itemDelim eq "SC") {
503                            $itemDelim = ";";
504                    }
505            }
506            my $columnDelim = "\t";
507            if (defined($tbldef->{columndelimiter}->[0])) {
508                    $columnDelim = $tbldef->{columndelimiter}->[0];
509                    if ($columnDelim eq "SC") {
510                            $columnDelim = ";";
511                    }
512            }
513            my $suffix = ".tbl";
514            if (defined($tbldef->{filename_suffix}->[0])) {
515                    $suffix = $tbldef->{filename_suffix}->[0];
516            }
517            my $filename = $self->directory().$TableName."-".$self->id().$self->selected_version().$suffix;
518            if (defined($tbldef->{filename_prefix}->[0])) {
519                    if ($tbldef->{filename_prefix}->[0] eq "NONE") {
520                            $filename = $self->directory().$self->id().$self->selected_version().$suffix;
521                    } else {
522                            $filename = $self->directory().$tbldef->{filename_prefix}->[0]."-".$self->id().$self->selected_version().$suffix;
523                    }
524            }
525            #Creating the table prototype
526            my $tbl = FIGMODELTable->new($tbldef->{columns},$filename,$tbldef->{hashcolumns},$columnDelim,$itemDelim,$prefix);
527            return $tbl;
528    }
529    
530  =head3 get_reaction_number  =head3 get_reaction_number
531  Definition:  Definition:
532          int = FIGMODELmodel->get_reaction_number();          int = FIGMODELmodel->get_reaction_number();
# Line 374  Line 535 
535  =cut  =cut
536  sub get_reaction_number {  sub get_reaction_number {
537          my ($self) = @_;          my ($self) = @_;
   
538          if (!defined($self->reaction_table())) {          if (!defined($self->reaction_table())) {
539                  return 0;                  return 0;
540          }          }
   
541          return $self->reaction_table()->size();          return $self->reaction_table()->size();
542  }  }
543    
# Line 389  Line 548 
548          Returns FIGMODELTable with the reaction list for the model          Returns FIGMODELTable with the reaction list for the model
549  =cut  =cut
550  sub reaction_table {  sub reaction_table {
551          my ($self) = @_;          my ($self,$clear) = @_;
552            if (defined($clear) && $clear == 1) {
553                    delete $self->{_reaction_table};
554            }
555            if (!defined($self->{_reaction_table})) {
556                    $self->{_reaction_table} = $self->load_model_table("ModelReactions",$clear);
557                    my $classTbl = $self->reaction_class_table();
558                    if (defined($classTbl)) {
559                            for (my $i=0; $i < $classTbl->size(); $i++) {
560                                    my $row = $classTbl->get_row($i);
561                                    if (defined($row->{REACTION})) {
562                                            my $rxnRow = $self->{_reaction_table}->get_row_by_key($row->{"REACTION"}->[0],"LOAD");
563                                            if (defined($row->{MEDIA})) {
564                                                    for (my $j=0; $j < @{$row->{MEDIA}};$j++) {
565                                                            my $class = "Active <=>";
566                                                            if ($row->{CLASS}->[$j] eq "Positive") {
567                                                                    $class = "Essential =>";
568                                                            } elsif ($row->{CLASS}->[$j] eq "Negative") {
569                                                                    $class = "Essential <=";
570                                                            } elsif ($row->{CLASS}->[$j] eq "Blocked") {
571                                                                    $class = "Inactive";
572                                                            } elsif ($row->{CLASS}->[$j] eq "Positive variable") {
573                                                                    $class = "Active =>";
574                                                            } elsif ($row->{CLASS}->[$j] eq "Negative variable") {
575                                                                    $class = "Active <=";
576                                                            } elsif ($row->{CLASS}->[$j] eq "Variable") {
577                                                                    $class = "Active <=>";
578                                                            } elsif ($row->{CLASS}->[$j] eq "Dead") {
579                                                                    $class = "Dead";
580                                                            }
581                                                            push(@{$rxnRow->{PREDICTIONS}},$row->{MEDIA}->[$j].":".$class);
582                                                    }
583                                            }
584                                    }
585                            }
586                    }
587            }
588            return $self->{_reaction_table};
589    }
590    
591          if (!defined($self->{_reaction_data})) {  =head3 essentials_table
592                  $self->{_reaction_data} = $self->figmodel()->database()->GetDBModel($self->id());  Definition:
593            FIGMODELTable = FIGMODELmodel->essentials_table();
594    Description:
595            Returns FIGMODELTable with the essential genes for the model
596    =cut
597    sub essentials_table {
598            my ($self,$clear) = @_;
599            my $tbl = $self->load_model_table("ModelEssentialGenes",$clear);
600            return $tbl;
601          }          }
602    
603          return $self->{_reaction_data};  =head3 model_history
604    Definition:
605            FIGMODELTable = FIGMODELmodel->model_history();
606    Description:
607            Returns FIGMODELTable with the history of model changes
608    =cut
609    sub model_history {
610            my ($self,$clear) = @_;
611            return $self->load_model_table("ModelHistory",$clear);
612  }  }
613    
614  =head3 reaction_class_table  =head3 feature_table
615  Definition:  Definition:
616          FIGMODELTable = FIGMODELmodel->reaction_class_table();          FIGMODELTable = FIGMODELmodel->feature_table();
617  Description:  Description:
618          Returns FIGMODELTable with the reaction class data, and creates the table file  if it does not exist          Returns FIGMODELTable with the feature list for the model
619  =cut  =cut
620  sub reaction_class_table {  sub feature_table {
621          my ($self) = @_;          my ($self) = @_;
622    
623          if (!defined($self->{_reaction_class_table})) {          if (!defined($self->{_feature_data})) {
624                  if (-e $self->directory()."ReactionClassification-".$self->id().$self->selected_version().".tbl") {                  #Getting the genome feature list
625                          $self->{_reaction_class_table} = $self->figmodel()->database()->load_table($self->directory()."ReactionClassification-".$self->id().$self->selected_version().".tbl",";","|",0,["REACTION","CLASS","MEDIA"]);                  my $FeatureTable = $self->figmodel()->GetGenomeFeatureTable($self->genome());
626                    if (!defined($FeatureTable)) {
627                            print STDERR "FIGMODELmodel:feature_table:Could not get features for genome ".$self->genome()." in database!";
628                            return undef;
629                    }
630                    #Getting the reaction table for the model
631                    my $rxnTable = $self->reaction_table();
632                    if (!defined($rxnTable)) {
633                            print STDERR "FIGMODELmodel:feature_table:Could not get reaction table for model ".$self->id()." in database!";
634                            return undef;
635                    }
636                    #Cloning the feature table
637                    $self->{_feature_data} = $FeatureTable->clone_table_def();
638                    $self->{_feature_data}->add_headings(($self->id()."REACTIONS",$self->id()."PREDICTIONS"));
639                    for (my $i=0; $i < $rxnTable->size(); $i++) {
640                            my $Row = $rxnTable->get_row($i);
641                            if (defined($Row) && defined($Row->{"ASSOCIATED PEG"})) {
642                                    foreach my $GeneSet (@{$Row->{"ASSOCIATED PEG"}}) {
643                                            my $temp = $GeneSet;
644                                            $temp =~ s/\+/|/g;
645                                            $temp =~ s/\sAND\s/|/gi;
646                                            $temp =~ s/\sOR\s/|/gi;
647                                            $temp =~ s/[\(\)\s]//g;
648                                            my @GeneList = split(/\|/,$temp);
649                                            foreach my $Gene (@GeneList) {
650                                                    my $FeatureRow = $self->{_feature_data}->get_row_by_key("fig|".$self->genome().".".$Gene,"ID");
651                                                    if (!defined($FeatureRow)) {
652                                                            $FeatureRow = $FeatureTable->get_row_by_key("fig|".$self->genome().".".$Gene,"ID");
653                                                            if (defined($FeatureRow)) {
654                                                                    $self->{_feature_data}->add_row($FeatureRow);
655                                                            }
656                                                    }
657                                                    if (defined($FeatureRow)) {
658                                                            $self->{_feature_data}->add_data($FeatureRow,$self->id()."REACTIONS",$Row->{"LOAD"}->[0],1);
659                                                    }
660                                            }
661                                    }
662                            }
663                    }
664                    #Loading predictions
665                    my $esstbl = $self->essentials_table();
666                    for (my $i=0; $i < $self->{_feature_data}->size(); $i++) {
667                            my $Row = $self->{_feature_data}->get_row($i);
668                            if ($Row->{ID}->[0] =~ m/(peg\.\d+)/) {
669                                    my $gene = $1;
670                                    my @rows = $esstbl->get_rows_by_key($gene,"ESSENTIAL GENES");
671                                    my $mediahash;
672                                    for (my $j=0; $j < $esstbl->size(); $j++) {
673                                            $mediahash->{$esstbl->get_row($j)->{MEDIA}->[0]} = 0;
674                                    }
675                                    for (my $j=0; $j < @rows; $j++) {
676                                            $mediahash->{$rows[$j]->{MEDIA}->[0]} = 1;
677                                    }
678                                    my @mediaList = keys(%{$mediahash});
679                                    for (my $j=0; $j < @mediaList; $j++) {
680                                            if ($mediahash->{$mediaList[$j]} == 1) {
681                                                    push(@{$Row->{$self->id()."PREDICTIONS"}},$mediaList[$j].":essential");
682                  } else {                  } else {
683                          $self->{_reaction_class_table} = FIGMODELTable->new(["REACTION","MEDIA","CLASS","MIN","MAX"],$self->directory()."ReactionClassification-".$self->id().$self->selected_version().".tbl",["REACTION","CLASS","MEDIA"],";","|",undef);                                                  push(@{$Row->{$self->id()."PREDICTIONS"}},$mediaList[$j].":nonessential");
684                                            }
685                                    }
686                            }
687                    }
688                  }                  }
689            return $self->{_feature_data};
690          }          }
691    
692          return $self->{_reaction_class_table};  =head3 reaction_class_table
693    Definition:
694            FIGMODELTable = FIGMODELmodel->reaction_class_table();
695    Description:
696            Returns FIGMODELTable with the reaction class data, and creates the table file  if it does not exist
697    =cut
698    sub reaction_class_table {
699            my ($self,$clear) = @_;
700            return $self->load_model_table("ModelReactionClasses",$clear);
701  }  }
702    
703  =head3 compound_class_table  =head3 compound_class_table
# Line 425  Line 707 
707          Returns FIGMODELTable with the compound class data, and creates the table file  if it does not exist          Returns FIGMODELTable with the compound class data, and creates the table file  if it does not exist
708  =cut  =cut
709  sub compound_class_table {  sub compound_class_table {
710          my ($self) = @_;          my ($self,$clear) = @_;
711            return $self->load_model_table("ModelCompoundClasses",$clear);
         if (!defined($self->{_compound_class_table})) {  
                 if (-e $self->directory()."CompoundClassification-".$self->id().$self->selected_version().".tbl") {  
                         $self->{_compound_class_table} = $self->figmodel()->database()->load_table($self->directory()."CompoundClassification-".$self->id().$self->selected_version().".tbl",";","|",0,["COMPOUND","CLASS","MEDIA"]);  
                 } else {  
                         $self->{_compound_class_table} = FIGMODELTable->new(["COMPOUND","MEDIA","CLASS","MIN","MAX"],$self->directory()."CompoundClassification-".$self->id().$self->selected_version().".tbl",["COMPOUND","CLASS","MEDIA"],";","|",undef);  
                 }  
712          }          }
713    
714          return $self->{_compound_class_table};  =head3 get_essential_genes
715    Definition:
716            [string::peg ID] = FIGMODELmodel->get_essential_genes(string::media condition);
717    Description:
718            Returns an reference to an array of the predicted essential genes during growth in the input media condition
719    =cut
720    sub get_essential_genes {
721            my ($self,$media) = @_;
722            my $tbl = $self->essentials_table();
723            my $row = $tbl->get_row_by_key($media,"MEDIA");
724            if (defined($row)) {
725                    return $row->{"ESSENTIAL GENES"};
726            }
727            return undef;
728  }  }
729    
730  =head3 compound_table  =head3 compound_table
# Line 448  Line 737 
737          my ($self) = @_;          my ($self) = @_;
738    
739          if (!defined($self->{_compound_table})) {          if (!defined($self->{_compound_table})) {
740                  $self->{_compound_table} = $self->figmodel()->database()->GetDBModelCompounds($self->id());                  $self->{_compound_table} = $self->create_table_prototype("ModelCompounds");
741                    #Loading the reactions
742                    my $ReactionTable = $self->figmodel()->database()->get_table("REACTIONS");
743                    my $BiomassTable = $self->figmodel()->database()->get_table("BIOMASS");
744                    #Loading the model
745                    my $ModelTable = $self->reaction_table();
746                    #Checking that the tables were loaded
747                    if (!defined($ModelTable) || !defined($ReactionTable)) {
748                            return undef;
749                    }
750                    #Finding the biomass reaction
751                    for (my $i=0; $i < $ModelTable->size(); $i++) {
752                            my $ID = $ModelTable->get_row($i)->{"LOAD"}->[0];
753                            my $Row = $ReactionTable->get_row_by_key($ID,"DATABASE");
754                            my $IsBiomass = 0;
755                            if (!defined($Row)) {
756                                    $Row = $BiomassTable->get_row_by_key($ID,"DATABASE");
757                                    $IsBiomass = 1;
758                            }
759                            if (defined($Row->{"EQUATION"}->[0])) {
760                                    $_ = $Row->{"EQUATION"}->[0];
761                                    my @OriginalArray = /(cpd\d\d\d\d\d[\[\w]*)/g;
762                                    foreach my $Compound (@OriginalArray) {
763                                            my $ID = substr($Compound,0,8);
764                                            my $NewRow = $self->{_compound_table}->get_row_by_key($ID,"DATABASE",1);
765                                            if ($IsBiomass == 1) {
766                                                    $self->{_compound_table}->add_data($NewRow,"BIOMASS",$Row->{"DATABASE"}->[0],1);
767                                            }
768                                            if (length($Compound) > 8) {
769                                                    #print $Compound."\t".$Row->{"EQUATION"}->[0]."\t".$Row->{"DATABASE"}->[0]."\n";
770                                                    my $Compartment = substr($Compound,8,1);
771                                                    $self->{_compound_table}->add_data($NewRow,"COMPARTMENTS",$Compartment,1);
772                                                    $self->{_compound_table}->add_data($NewRow,"TRANSPORTERS",$Row->{"DATABASE"}->[0],1);
773                                            }
774                                    }
775                            }
776                    }
777          }          }
778    
779          return $self->{_compound_table};          return $self->{_compound_table};
# Line 456  Line 781 
781    
782  =head3 get_compound_data  =head3 get_compound_data
783  Definition:  Definition:
784          string = FIGMODELmodel->get_compound_data(string::compound ID);          {string:key=>[string]:values} = FIGMODELmodel->get_compound_data(string::compound ID);
785  Description:  Description:
786          Returns model compound data          Returns model compound data
787  =cut  =cut
# Line 467  Line 792 
792                  return undef;                  return undef;
793          }          }
794          if ($compound =~ m/^\d+$/) {          if ($compound =~ m/^\d+$/) {
795                  $self->compound_table()->get_row($compound);                  return $self->compound_table()->get_row($compound);
796          }          }
797          return $self->compound_table()->get_row_by_key($compound,"DATABASE");          return $self->compound_table()->get_row_by_key($compound,"DATABASE");
798  }  }
799    
800    =head3 get_feature_data
801    Definition:
802            {string:key=>[string]:values} = FIGMODELmodel->get_feature_data(string::feature ID);
803    Description:
804            Returns model feature data
805    =cut
806    sub get_feature_data {
807            my ($self,$feature) = @_;
808            if (!defined($self->feature_table())) {
809                    return undef;
810            }
811            if ($feature =~ m/^\d+$/) {
812                    return $self->feature_table()->get_row($feature);
813            }
814            if ($feature =~ m/(peg\.\d+)/) {
815                    $feature = $1;
816            }
817            return $self->feature_table()->get_row_by_key("fig|".$self->genome().".".$feature,"ID");
818    }
819    
820  =head3 genome  =head3 genome
821  Definition:  Definition:
822          string = FIGMODELmodel->genome();          string = FIGMODELmodel->genome();
# Line 480  Line 825 
825  =cut  =cut
826  sub genome {  sub genome {
827          my ($self) = @_;          my ($self) = @_;
828          return $self->{_data}->{genome}->[0];          return $self->{_data}->genome();
829  }  }
830    
831  =head3 source  =head3 source
# Line 491  Line 836 
836  =cut  =cut
837  sub source {  sub source {
838          my ($self) = @_;          my ($self) = @_;
839          return $self->{_data}->{source}->[0];          return $self->{_data}->source();
840  }  }
841    
842  =head3 rights  =head3 rights
# Line 502  Line 847 
847  =cut  =cut
848  sub rights {  sub rights {
849          my ($self,$username) = @_;          my ($self,$username) = @_;
   
850          if ($self->public()) {          if ($self->public()) {
851                  return 1;                  return 1;
852          }          }
# Line 510  Line 854 
854                  return 0;                  return 0;
855          }          }
856          if (!defined($self->{_userrights}->{$username})) {          if (!defined($self->{_userrights}->{$username})) {
857                  if (defined($self->{_data}->{master})) {                  $self->{_userrights}->{$self->{_data}->owner()} = 1;
858                          for (my $i=0; $i < @{$self->{_data}->{master}};$i++) {                  my @users = split(/\|/,$self->{_data}->users());
859                                  $self->{_userrights}->{$self->{_data}->{master}->[$i]} = 1;                  for (my $i=0; $i < @users;$i++) {
860                          }                          $self->{_userrights}->{$users[$i]} = 1;
                 }  
                 if (defined($self->{_data}->{users})) {  
                         for (my $i=0; $i < @{$self->{_data}->{users}};$i++) {  
                                 $self->{_userrights}->{$self->{_data}->{users}->[$i]} = 1;  
                         }  
861                  }                  }
862          }          }
863          return $self->{_userrights}->{$username};          return $self->{_userrights}->{$username};
# Line 532  Line 871 
871  =cut  =cut
872  sub public {  sub public {
873          my ($self) = @_;          my ($self) = @_;
874            if ($self->{_data}->users() eq "all") {
875          if (!defined($self->{_public})) {                  return 1;
                 $self->{_public} = 0;  
                 if (defined($self->{_data}->{users}->[0]) && $self->{_data}->{users}->[0] eq "all") {  
                         $self->{_public} = 1;  
                 }  
876          }          }
877          return $self->{_public};          return 0;
878  }  }
879    
880  =head3 directory  =head3 directory
# Line 558  Line 893 
893                  }                  }
894                  my $source = $self->source();                  my $source = $self->source();
895                  if ($source =~ /^MGRAST/) {                  if ($source =~ /^MGRAST/) {
896                          $self->{_directory} = $self->figmodel()->config("organism directory")->[0].$userdirectory.$self->genome()."/";                          $self->{_directory} = $self->figmodel()->config("mgrast model directory")->[0].$userdirectory.$self->genome()."/";
897                  } elsif ($source =~ /^RAST/) {                  } elsif ($source =~ /^RAST/) {
898                          $self->{_directory} = $self->figmodel()->config("organism directory")->[0].$userdirectory.$self->genome()."/";                          $self->{_directory} = $self->figmodel()->config("organism directory")->[0].$userdirectory.$self->genome()."/";
899                  } elsif ($source =~ /^SEED/) {                  } elsif ($source =~ /^SEED/) {
# Line 587  Line 922 
922          return $self->directory().$self->id().$self->selected_version().".txt";          return $self->directory().$self->id().$self->selected_version().".txt";
923  }  }
924    
 =head3 set_metagenome_stats  
 Definition:  
         string = FIGMODELmodel->set_metagenome_stats();  
 Description:  
         Sets the values of many model stats for a metagenome  
 =cut  
 sub set_metagenome_stats {  
         my ($self) = @_;  
   
         $self->{_total_compounds} = 0;  
         if (defined($self->compound_table())) {  
                 $self->{_total_compounds} = $self->compound_table()->size();  
         }  
         $self->{_gene_reactions} = 0;  
         $self->{_gapfilling_reactions} = 0;  
         $self->{_model_genes} = 0;  
         $self->{_total_reactions} = 0;  
         if (defined($self->reaction_table())) {  
                 $self->{_total_reactions} = $self->reaction_table()->size();  
                 my $tbl = $self->reaction_table();  
                 my $spontaneous = 0;  
                 for (my $i=0; $i < $tbl->size(); $i++) {  
                         my $row = $tbl->get_row($i);  
                         if (!defined($row->{"ASSOCIATED PEG"}->[0]) || $row->{"ASSOCIATED PEG"}->[0] !~ m/peg/) {  
                                 if ($row->{"ASSOCIATED PEG"}->[0] =~ m/SPONTANEOUS/) {  
                                         $spontaneous++;  
                                 } else {  
                                         $self->{_gapfilling_reactions}++;  
                                 }  
                         } else {  
                                 for (my $j=0; $j < @{$row->{"CONFIDENCE"}}; $j++) {  
                                         my @ecores = split(/;/,$row->{"CONFIDENCE"}->[$j]);  
                                         $self->{_model_genes} += @ecores;  
                                 }  
                         }  
                 }  
                 $self->{_gene_reactions} = $tbl->size() - $spontaneous - $self->{_gapfilling_reactions};  
         }  
 }  
   
925  =head3 version  =head3 version
926  Definition:  Definition:
927          string = FIGMODELmodel->version();          string = FIGMODELmodel->version();
# Line 638  Line 933 
933    
934          if (!defined($self->{_version})) {          if (!defined($self->{_version})) {
935                  if (!defined($self->{_selectedversion})) {                  if (!defined($self->{_selectedversion})) {
936                          if (defined($self->stats())) {                          $self->{_version} = "V".$self->{_data}->version().".".$self->{_data}->autocompleteVersion();
                                 $self->{_version} = "V".$self->stats()->{"Version"}->[0].".".$self->stats()->{"Gap fill version"}->[0];  
                         }  
937                  } else {                  } else {
938                          $self->{_version} = $self->{_selectedversion};                          $self->{_version} = $self->{_selectedversion};
939                  }                  }
# Line 671  Line 964 
964  =cut  =cut
965  sub modification_time {  sub modification_time {
966          my ($self) = @_;          my ($self) = @_;
967          if (!defined($self->{_modification_time})) {          return $self->{_data}->modificationDate();
                 my $stats = $self->stats();  
                 if (defined($stats)) {  
                         $self->{_modification_time} = 0;  
                         if (defined($stats->{"Build date"}->[0]) && $self->{_modification_time} < $stats->{"Build date"}->[0]) {  
                                 $self->{_modification_time} = $stats->{"Build date"}->[0];  
                         } elsif (defined($stats->{"Gap fill date"}->[0]) && $self->{_modification_time} < $stats->{"Gap fill date"}->[0]) {  
                                 $self->{_modification_time} = $stats->{"Gap fill date"}->[0];  
                         }  
                 } else {  
                         $self->{_modification_time} = 0;  
                 }  
         }  
         return $self->{_modification_time};  
968  }  }
969    
970  =head3 gene_reactions  =head3 gene_reactions
# Line 695  Line 975 
975  =cut  =cut
976  sub gene_reactions {  sub gene_reactions {
977          my ($self) = @_;          my ($self) = @_;
978            return ($self->{_data}->reactions() - $self->{_data}->autoCompleteReactions() - $self->{_data}->spontaneousReactions() - $self->{_data}->gapFillReactions());
         if (!defined($self->{_gene_reactions})) {  
                 if ($self->source() =~ /^MGRAST/) {  
                         $self->set_metagenome_stats();  
                 } elsif (defined($self->stats())) {  
                         $self->{_gene_reactions} = $self->total_reactions() - $self->gapfilling_reactions() - $self->stats()->{'Spontaneous'}->[0] - $self->stats()->{'Growmatch reactions'}->[0] - $self->stats()->{'Biolog gap filling reactions'}->[0];  
                 }  
         }  
         return $self->{_gene_reactions};  
979  }  }
980    
981  =head3 total_compounds  =head3 total_compounds
# Line 714  Line 986 
986  =cut  =cut
987  sub total_compounds {  sub total_compounds {
988          my ($self) = @_;          my ($self) = @_;
989            return $self->{_data}->compounds();
         if (!defined($self->{_total_compounds})) {  
                 if ($self->source() =~ /^MGRAST/) {  
                         $self->set_metagenome_stats();  
                 } elsif (defined($self->stats())) {  
                         $self->{_total_compounds} = $self->stats()->{'Metabolites'}->[0];  
                 }  
         }  
         return $self->{_total_compounds};  
990  }  }
991    
992  =head3 gapfilling_reactions  =head3 gapfilling_reactions
# Line 733  Line 997 
997  =cut  =cut
998  sub gapfilling_reactions {  sub gapfilling_reactions {
999          my ($self) = @_;          my ($self) = @_;
1000            return ($self->{_data}->autoCompleteReactions()+$self->{_data}->gapFillReactions());
         if (!defined($self->{_gapfilling_reactions})) {  
                 if ($self->source() =~ /^MGRAST/) {  
                         $self->set_metagenome_stats();  
                 } elsif (defined($self->stats())) {  
                         $self->{_gapfilling_reactions} = $self->stats()->{'Gap filling reactions'}->[0];  
                 }  
         }  
         return $self->{_gapfilling_reactions};  
1001  }  }
1002    
1003  =head3 total_reactions  =head3 total_reactions
# Line 752  Line 1008 
1008  =cut  =cut
1009  sub total_reactions {  sub total_reactions {
1010          my ($self) = @_;          my ($self) = @_;
1011            return $self->{_data}->reactions();
         if (!defined($self->{_total_reactions})) {  
                 if ($self->source() =~ /^MGRAST/) {  
                         $self->set_metagenome_stats();  
                 } elsif (defined($self->stats())) {  
                         $self->{_total_reactions} = $self->stats()->{'Number of reactions'}->[0];  
                 }  
         }  
         return $self->{_total_reactions};  
1012  }  }
1013    
1014  =head3 model_genes  =head3 model_genes
# Line 771  Line 1019 
1019  =cut  =cut
1020  sub model_genes {  sub model_genes {
1021          my ($self) = @_;          my ($self) = @_;
1022            return $self->{_data}->associatedGenes();
         if (!defined($self->{_model_genes})) {  
                 if ($self->source() =~ /^MGRAST/) {  
                         $self->set_metagenome_stats();  
                 } elsif (defined($self->stats())) {  
                         $self->{_model_genes} = $self->stats()->{'Genes with reactions'}->[0];  
                 }  
         }  
         return $self->{_model_genes};  
1023  }  }
1024    
1025  =head3 class  =head3 class
# Line 790  Line 1030 
1030  =cut  =cut
1031  sub class {  sub class {
1032          my ($self) = @_;          my ($self) = @_;
1033            return $self->{_data}->cellwalltype();
1034    }
1035    
1036          if (!defined($self->{_class})) {  sub autocompleteMedia {
1037                  if ($self->source() =~ /^MGRAST/) {          my ($self,$newMedia) = @_;
1038                          $self->{_class} = "Other";          if (defined($newMedia)) {
1039                  } elsif (defined($self->stats())) {                  return $self->{_data}->autoCompleteMedia($newMedia);
1040                          $self->{_class} = $self->stats()->{Class}->[0];          }
1041            return $self->{_data}->autoCompleteMedia();
1042    }
1043    
1044    sub biomassReaction {
1045            my ($self,$newBiomass) = @_;
1046            if (!defined($newBiomass)) {
1047                    return $self->{_data}->biomassReaction();
1048            } else {
1049                    #Figuring out what the old biomass is
1050                    my $oldBiomass = $self->{_data}->biomassReaction();
1051                    if ($newBiomass ne $oldBiomass) {
1052                            #Figuring out if the new biomass exists
1053                            my $handle = $self->database()->get_object_manager("bof");
1054                            my $objects = $handle->get_objects({"DATABASE" => [$newBiomass]});
1055                            if (!defined($objects) || !defined($objects->[0])) {
1056                                    print STDERR "Could not find new biomass reaction ".$newBiomass."\n";
1057                                    return $oldBiomass;
1058                            }
1059                            #Changing the biomass reaction in the model file
1060                            my $rxnTbl = $self->reaction_table();
1061                            for (my $i=0; $i < $rxnTbl->size(); $i++) {
1062                                    my $row = $rxnTbl->get_row($i);
1063                                    if ($row->{LOAD}->[0] =~ m/^bio/) {
1064                                            $row->{LOAD}->[0] = $newBiomass;
1065                                    }
1066                            }
1067                            $rxnTbl->save();
1068                            #Changing the biomass reaction in the database
1069                            return  $self->{_data}->biomassReaction($newBiomass);
1070                  }                  }
1071          }          }
         return $self->{_class};  
1072  }  }
1073    
1074  =head3 taxonomy  =head3 taxonomy
# Line 866  Line 1136 
1136                          if (defined($self->mgdata())) {                          if (defined($self->mgdata())) {
1137                                  $self->{_genome_genes} = $self->mgdata()->genome_contig_count;                                  $self->{_genome_genes} = $self->mgdata()->genome_contig_count;
1138                          }                          }
1139                  } elsif (defined($self->stats())) {                  } else {
1140                          $self->{_genome_genes} = $self->stats()->{'Total genes'}->[0];                          $self->{_genome_genes} = $self->figmodel()->get_genome_stats($self->genome())->{"TOTAL GENES"}->[0];
1141                  }                  }
1142          }          }
1143    
# Line 884  Line 1154 
1154    
1155          #Assuming complete media if none is provided          #Assuming complete media if none is provided
1156          if (!defined($Media)) {          if (!defined($Media)) {
1157                  $Media = "Complete";                  $Media = $self->autocompleteMedia();
1158          }          }
1159    
1160          #Predicting essentiality          #Predicting essentiality
1161          my $result = $self->figmodel()->RunFBASimulation($self->id(),"SINGLEKO",undef,undef,[$self->id()],[$Media]);          my $result = $self->figmodel()->RunFBASimulation($self->id(),"SINGLEKO",undef,undef,[$self->id()],[$Media]);
1162          #Checking that the table is defined and the output file exists          #Checking that the table is defined and the output file exists
1163          if (defined($result) && defined($result->get_row(0)->{"ESSENTIALGENES"})) {          if (defined($result) && defined($result->get_row(0)->{"ESSENTIALGENES"})) {
1164                  $self->figmodel()->database()->print_array_to_file($self->directory()."EssentialGenes-".$self->id()."-".$Media.".tbl",[join("\n",@{$result->get_row(0)->{"ESSENTIALGENES"}})]);                  my $tbl = $self->essentials_table();
1165                    my $row = $tbl->get_row_by_key($Media,"MEDIA",1);
1166                    $row->{"ESSENTIAL GENES"} = $result->get_row(0)->{"ESSENTIALGENES"};
1167                    $tbl->save();
1168            } else {
1169                    $self->figmodel()->error_message("FIGMODELmodel:run_default_model_predictions:could not identify essential reactions for model ".$self->id().$self->selected_version().".");
1170                    return $self->figmodel()->fail();
1171          }          }
1172    
1173          #Classifying reactions and compounds          #Classifying reactions and compounds
1174          my $tbl = $self->classify_model_reactions($Media);          my $tbl = $self->classify_model_reactions($Media);
1175            if (!defined($tbl)) {
1176                    $self->figmodel()->error_message("FIGMODELmodel:run_default_model_predictions:could not classify reactions for model ".$self->id().$self->selected_version().".");
1177                    return $self->figmodel()->fail();
1178            }
1179          $tbl->save();          $tbl->save();
1180    
1181          return $self->figmodel()->success();          return $self->figmodel()->success();
1182  }  }
1183    
 =head3 save_obsolete_stats  
 Definition:  
         FIGMODELmodel->save_obsolete_stats();  
 Description:  
 =cut  
 sub save_obsolete_stats {  
         my ($self) = @_;  
   
         #checking if stats exists  
         my $stats = $self->stats();  
         if (defined($stats)) {  
                 $stats->{"Model ID"}->[0] = $self->id()."V".$stats->{"Version"}->[0].".".$stats->{"Gap fill version"}->[0];  
                 $self->figmodel()->database()->update_row("OBSOLETE MODEL STATS",$stats,"Model ID");  
                 $stats->{"Model ID"}->[0] = $self->id();  
         }  
 }  
   
1184  =head3 update_stats_for_gap_filling  =head3 update_stats_for_gap_filling
1185  Definition:  Definition:
1186          {string => [string]} = FIGMODELmodel->update_stats_for_gap_filling(int::gapfill time);          {string => [string]} = FIGMODELmodel->update_stats_for_gap_filling(int::gapfill time);
# Line 925  Line 1188 
1188  =cut  =cut
1189  sub update_stats_for_gap_filling {  sub update_stats_for_gap_filling {
1190          my ($self,$gapfilltime) = @_;          my ($self,$gapfilltime) = @_;
1191            $self->{_data}->autoCompleteTime($gapfilltime);
1192          #preserving the stats for the now obselete model          $self->{_data}->autocompleteDate(time());
1193          $self->save_obsolete_stats();          $self->{_data}->modificationDate(time());
1194          my $stats = $self->update_model_stats(0);          my $version = $self->{_data}->autocompleteVersion();
1195          $stats->{"Gap filling time"}->[0] = $gapfilltime;          $self->{_data}->autocompleteVersion($version+1);
1196          $stats->{"Gap fill date"}->[0] = time();          $self->update_model_stats();
         if (!defined($stats->{"Gap fill version"}->[0])) {  
                 $stats->{"Gap fill version"}->[0] = 0;  
         }  
         $stats->{"Gap fill version"}->[0]++;  
   
         #Updating the stats stored in the table  
         $self->figmodel()->database()->update_row("MODEL STATS",$stats,"Model ID");  
         return $stats;  
1197  }  }
1198    
1199  =head3 update_stats_for_build  =head3 update_stats_for_build
# Line 948  Line 1203 
1203  =cut  =cut
1204  sub update_stats_for_build {  sub update_stats_for_build {
1205          my ($self) = @_;          my ($self) = @_;
1206            $self->{_data}->builtDate(time());
1207          #preserving the stats for the now obselete model          $self->{_data}->modificationDate(time());
1208          $self->save_obsolete_stats();          my $version = $self->{_data}->version();
1209          my $stats = $self->update_model_stats(0);          $self->{_data}->version($version+1);
         $stats->{"Build date"}->[0] = time();  
         if (!defined($stats->{"Version"}->[0])) {  
                 $stats->{"Version"}->[0] = 0;  
         }  
         $stats->{"Version"}->[0]++;  
   
         #Updating the stats stored in the table  
         $self->figmodel()->database()->update_row("MODEL STATS",$stats,"Model ID");  
         return $stats;  
1210  }  }
1211    
1212  =head3 update_model_stats  =head3 update_model_stats
# Line 979  Line 1225 
1225          }          }
1226          my $cpdtbl = $self->compound_table();          my $cpdtbl = $self->compound_table();
1227    
1228          #Creating empty status row          #Calculating all necessary stats
         my $CurrentStats = {"Genes with reactions" => [0],  
                                                  "Metabolites" => [$cpdtbl->size()],  
                                                  "Growmatch reactions" => [0],  
                                                  "Spontaneous" => [0],  
                                                  "Biolog gap filling reactions" => [0],  
                                                  "Number of reactions" => [$rxntbl->size()],  
                                                  "Transport reaction"=>[0],  
                                                  "Gap filling reactions" => [0],  
                                                  "Model ID" => [$self->id()],  
                                                  "Subsystem genes with reactions" => [0],  
                                                  "Nonsubsystem genes with reactions" => [0],  
                                                  Version => [0],  
                                                  "Gap fill version" => [0],  
                                                  Source => [$self->source()],  
                                                  "Genes with one reaction" => [0],  
                                                  "Genome ID" => [$self->genome()]};  
   
         my $genomestats = $self->figmodel()->get_genome_stats($self->genome());  
         if (defined($genomestats)) {  
                 $CurrentStats->{SOURCE}->[0] = $genomestats->{SOURCE}->[0];  
                 $CurrentStats->{"Organism name"}->[0] = $genomestats->{NAME}->[0];  
                 $CurrentStats->{"Total genes"}->[0] = $genomestats->{"TOTAL GENES"}->[0];  
                 $CurrentStats->{"Gram positive genes"}->[0] = $genomestats->{"GRAM POSITIVE GENES"}->[0];  
                 $CurrentStats->{"Gram negative genes"}->[0] = $genomestats->{"GRAM NEGATIVE GENES"}->[0];  
                 $CurrentStats->{"Class"}->[0] = $genomestats->{CLASS}->[0];  
                 $CurrentStats->{"Genes with functions"}->[0] = $genomestats->{"GENES WITH FUNCTIONS"}->[0];  
                 $CurrentStats->{"Subsystem genes"}->[0] = $genomestats->{"SUBSYSTEM GENES"}->[0];  
                 $CurrentStats->{"Nonsubsystem genes"}->[0] = $genomestats->{"NON SUBSYSTEM GENES"}->[0];  
                 if (defined($genomestats->{TAXONOMY})) {  
                         $CurrentStats->{"Taxonomy 0"}->[0] = $genomestats->{TAXONOMY}->[0];  
                         $CurrentStats->{"Taxonomy 1"}->[0] = $genomestats->{TAXONOMY}->[1];  
                         $CurrentStats->{"Taxonomy 2"}->[0] = $genomestats->{TAXONOMY}->[2];  
                         $CurrentStats->{"Taxonomy 3"}->[0] = $genomestats->{TAXONOMY}->[3];  
                         $CurrentStats->{"Taxonomy 4"}->[0] = $genomestats->{TAXONOMY}->[4];  
                         $CurrentStats->{"Taxonomy 5"}->[0] = $genomestats->{TAXONOMY}->[5];  
                 }  
         }  
   
         #Transfering build, version, and gap fill data from existing stats  
         if (defined($self->stats())) {  
                 $CurrentStats->{Version}->[0] = $self->stats()->{Version}->[0];  
                 $CurrentStats->{"Gap fill version"}->[0] = $self->stats()->{"Gap fill version"}->[0];  
                 $CurrentStats->{"Gap filling time"}->[0] = $self->stats()->{"Gap filling time"}->[0];  
                 $CurrentStats->{"Gap fill date"}->[0] = $self->stats()->{"Gap fill date"}->[0];  
                 $CurrentStats->{"Build date"}->[0] = $self->stats()->{"Build date"}->[0];  
         }  
   
1229          my %GeneHash;          my %GeneHash;
1230          my %NonpegHash;          my %NonpegHash;
1231          my %CompoundHash;          my %CompoundHash;
1232            my $spontaneousReactions = 0;
1233            my $gapFillReactions = 0;
1234            my $biologReactions = 0;
1235            my $transporters = 0;
1236            my $autoCompleteReactions = 0;
1237            my $associatedSubsystemGenes = 0;
1238          for (my $i=0; $i < $rxntbl->size(); $i++) {          for (my $i=0; $i < $rxntbl->size(); $i++) {
1239                  my $Row = $rxntbl->get_row($i);                  my $Row = $rxntbl->get_row($i);
1240                  if (defined($Row) && defined($Row->{"ASSOCIATED PEG"})) {                  if (defined($Row) && defined($Row->{"ASSOCIATED PEG"})) {
# Line 1037  Line 1242 
1242                          if (defined($ReactionRow->{"EQUATION"}->[0])) {                          if (defined($ReactionRow->{"EQUATION"}->[0])) {
1243                                  #Checking for extracellular metabolites which indicate that this is a transporter                                  #Checking for extracellular metabolites which indicate that this is a transporter
1244                                  if ($ReactionRow->{"EQUATION"}->[0] =~ m/\[e\]/) {                                  if ($ReactionRow->{"EQUATION"}->[0] =~ m/\[e\]/) {
1245                                          $CurrentStats->{"Transport reaction"}->[0]++;                                          $transporters++;
1246                                  }                                  }
1247                          }                          }
1248                          #Identifying spontaneous/biolog/gapfilling/gene associated reactions                          #Identifying spontaneous/biolog/gapfilling/gene associated reactions
1249                          if ($Row->{"ASSOCIATED PEG"}->[0] =~ m/BIOLOG/i) {                          if ($Row->{"ASSOCIATED PEG"}->[0] =~ m/BIOLOG/i) {
1250                                  $CurrentStats->{"Biolog gap filling reactions"}->[0]++;                                  $biologReactions++;
1251                            } elsif ($Row->{"ASSOCIATED PEG"}->[0] =~ m/GROW/i) {
1252                                    $gapFillReactions++;
1253                          } elsif ($Row->{"ASSOCIATED PEG"}->[0] =~ m/SPONTANEOUS/i) {                          } elsif ($Row->{"ASSOCIATED PEG"}->[0] =~ m/SPONTANEOUS/i) {
1254                                  $CurrentStats->{"Spontaneous"}->[0]++;                                  $spontaneousReactions++;
1255                          } elsif ($Row->{"ASSOCIATED PEG"}->[0] =~ m/GAP/ || $Row->{"ASSOCIATED PEG"}->[0] =~ m/UNIVERSAL/i || $Row->{"ASSOCIATED PEG"}->[0] =~ m/UNKNOWN/i) {                          } elsif ($Row->{"ASSOCIATED PEG"}->[0] =~ m/GAP/ || $Row->{"ASSOCIATED PEG"}->[0] =~ m/UNIVERSAL/i || $Row->{"ASSOCIATED PEG"}->[0] =~ m/UNKNOWN/i) {
1256                                  $CurrentStats->{"Gap filling reactions"}->[0]++;                                  $autoCompleteReactions++;
1257                          } else {                          } else {
1258                                  foreach my $GeneSet (@{$Row->{"ASSOCIATED PEG"}}) {                                  foreach my $GeneSet (@{$Row->{"ASSOCIATED PEG"}}) {
1259                                          my @GeneList = split(/\+/,$GeneSet);                                          $_ = $GeneSet;
1260                                            my @GeneList = /(peg\.\d+)/g;
1261                                          foreach my $Gene (@GeneList) {                                          foreach my $Gene (@GeneList) {
1262                                                  if ($Gene =~ m/(peg\.\d+)/) {                                                  if ($Gene =~ m/(peg\.\d+)/) {
1263                                                          $GeneHash{$1} = 1;                                                          $GeneHash{$1} = 1;
# Line 1063  Line 1271 
1271          }          }
1272          my @genes = keys(%GeneHash);          my @genes = keys(%GeneHash);
1273          my @othergenes = keys(%NonpegHash);          my @othergenes = keys(%NonpegHash);
         $CurrentStats->{"Genes with reactions"}->[0] = @genes + @othergenes;  
1274    
1275          #Updating the stats stored in the table          #Setting the reaction count
1276          $self->figmodel()->database()->update_row("MODEL STATS",$CurrentStats,"Model ID");          $self->{_data}->reactions($rxntbl->size());
1277          $self->{_stats} = $CurrentStats;          #Setting the metabolite count
1278          return $CurrentStats;          $self->{_data}->compounds($cpdtbl->size());
1279            #Setting the gene count
1280            my $geneCount = @genes + @othergenes;
1281            $self->{_data}->associatedGenes($geneCount);
1282            #Setting remaining stats
1283            $self->{_data}->spontaneousReactions($spontaneousReactions);
1284            $self->{_data}->gapFillReactions($gapFillReactions);
1285            $self->{_data}->biologReactions($biologReactions);
1286            $self->{_data}->transporters($transporters);
1287            $self->{_data}->autoCompleteReactions($autoCompleteReactions);
1288            $self->{_data}->associatedSubsystemGenes($associatedSubsystemGenes);
1289            #Setting the model class
1290            my $class = "";
1291            for (my $i=0; $i < @{$self->figmodel()->config("class list")}; $i++) {
1292                    if (defined($self->figmodel()->config($self->figmodel()->config("class list")->[$i]))) {
1293                            if (defined($self->figmodel()->config($self->figmodel()->config("class list")->[$i])->{$self->id()})) {
1294                                    $class = $self->figmodel()->config("class list")->[$i];
1295                                    last;
1296                            }
1297                            if ($class eq "" && defined($self->figmodel()->config($self->figmodel()->config("class list")->[$i])->{$self->genome()})) {
1298                                    $class = $self->figmodel()->config("class list")->[$i];
1299                            }
1300                    }
1301            }
1302            if ($class eq "") {
1303                    $class = $self->figmodel()->get_genome_stats($self->genome())->{CLASS}->[0];
1304            }
1305            if ($class eq "") {
1306                    $class = "unknown";
1307            }
1308            $self->{_data}->cellwalltype($class);
1309  }  }
1310    
1311  =head3 GapFillModel  =head3 GapFillModel
# Line 1088  Line 1325 
1325          my $UniqueFilename = $self->figmodel()->filename();          my $UniqueFilename = $self->figmodel()->filename();
1326          my $StartTime = time();          my $StartTime = time();
1327    
1328          #Archiving the existing model          #Reading original reaction table
1329          $self->ArchiveModel();          my $OriginalRxn = $self->reaction_table();
1330            #Clearing the table
1331            $self->reaction_table(1);
1332    
1333          #Removing any gapfilling reactions that may be currently present in the model          #Removing any gapfilling reactions that may be currently present in the model
1334          if (!defined($donotclear) || $donotclear != 1) {          if (!defined($donotclear) || $donotclear != 1) {
1335                  my $ModelTable = $self->reaction_table();                  my $ModelTable = $self->reaction_table();
1336                  for (my $i=0; $i < $ModelTable->size(); $i++) {                  for (my $i=0; $i < $ModelTable->size(); $i++) {
1337                          if (!defined($ModelTable->get_row($i)->{"ASSOCIATED PEG"}->[0]) || $ModelTable->get_row($i)->{"ASSOCIATED PEG"}->[0] eq "GAP FILLING" || $ModelTable->get_row($i)->{"ASSOCIATED PEG"}->[0] =~ m/BIOLOG/ || $ModelTable->get_row($i)->{"ASSOCIATED PEG"}->[0] =~ m/GROWMATCH/) {                          if (!defined($ModelTable->get_row($i)->{"ASSOCIATED PEG"}->[0]) || $ModelTable->get_row($i)->{"ASSOCIATED PEG"}->[0] eq "AUTOCOMPLETION" || $ModelTable->get_row($i)->{"ASSOCIATED PEG"}->[0] eq "GAP FILLING" || $ModelTable->get_row($i)->{"ASSOCIATED PEG"}->[0] =~ m/BIOLOG/ || $ModelTable->get_row($i)->{"ASSOCIATED PEG"}->[0] =~ m/GROWMATCH/) {
1338                                  $ModelTable->delete_row($i);                                  $ModelTable->delete_row($i);
1339                                  $i--;                                  $i--;
1340                          }                          }
# Line 1104  Line 1343 
1343          }          }
1344    
1345          #Calling the MFAToolkit to run the gap filling optimization          #Calling the MFAToolkit to run the gap filling optimization
1346          my $MinimalMediaTable = $self->figmodel()->database()->GetDBTable("MINIMAL MEDIA TABLE");          my $Media = $self->autocompleteMedia();
1347          my $Media = "Complete";          if ($Media eq "Complete") {
1348          if (defined($MinimalMediaTable->get_row_by_key($self->genome(),"Organism"))) {                  system($self->figmodel()->GenerateMFAToolkitCommandLineCall($UniqueFilename,$self->id(),undef,["GapFilling"],{"Reactions to knockout" => $self->config("permanently knocked out reactions")->[0]},"GapFill".$self->id().".log",undef));
1349                  $Media = $MinimalMediaTable->get_row_by_key($self->genome(),"Organism")->{"Minimal media"}->[0];          } else {
1350                  #Loading media, changing bounds, saving media as a test media                  #Loading media, changing bounds, saving media as a test media
1351                  my $MediaTable = FIGMODELTable::load_table($self->config("Media directory")->[0].$Media.".txt",";","",0,["VarName"]);                  my $MediaTable = FIGMODELTable::load_table($self->config("Media directory")->[0].$Media.".txt",";","",0,["VarName"]);
1352                  for (my $i=0; $i < $MediaTable->size(); $i++) {                  for (my $i=0; $i < $MediaTable->size(); $i++) {
# Line 1119  Line 1358 
1358                          }                          }
1359                  }                  }
1360                  $MediaTable->save($self->config("Media directory")->[0].$UniqueFilename."TestMedia.txt");                  $MediaTable->save($self->config("Media directory")->[0].$UniqueFilename."TestMedia.txt");
1361                  system($self->figmodel()->GenerateMFAToolkitCommandLineCall($UniqueFilename,$self->id(),$UniqueFilename."TestMedia",["GapFilling"],{"Default max drain flux" => 0},"GapFill".$self->id().".log",undef));                  #print $self->figmodel()->GenerateMFAToolkitCommandLineCall($UniqueFilename,$self->id(),$UniqueFilename."TestMedia",["GapFilling"],{"Default max drain flux" => 0,"Reactions to knockout" => $self->config("permanently knocked out reactions")->[0]},"GapFill".$self->id().".log",undef)."\n";
1362                    system($self->figmodel()->GenerateMFAToolkitCommandLineCall($UniqueFilename,$self->id(),$UniqueFilename."TestMedia",["GapFilling"],{"Default max drain flux" => 0,"Reactions to knockout" => $self->config("permanently knocked out reactions")->[0]},"GapFill".$self->id().".log",undef));
1363                  unlink($self->config("Media directory")->[0].$UniqueFilename."TestMedia.txt");                  unlink($self->config("Media directory")->[0].$UniqueFilename."TestMedia.txt");
         } else {  
                 system($self->figmodel()->GenerateMFAToolkitCommandLineCall($UniqueFilename,$self->id(),undef,["GapFilling"],undef,"GapFill".$self->id().".log",undef));  
1364          }          }
1365    
1366          #Parse the solutions file for the model and get the reaction list from it          #Parse the solutions file for the model and get the reaction list from it
1367          my $SolutionData = $self->figmodel()->LoadProblemReport($UniqueFilename);          my $SolutionData = $self->figmodel()->LoadProblemReport($UniqueFilename);
1368    
1369          #Clearing the mfatoolkit output and log file          #Clearing the mfatoolkit output and log file
1370          $self->figmodel()->clearing_output($UniqueFilename,"GapFill".$self->id().".log");          $self->figmodel()->clearing_output($UniqueFilename,"GapFill".$self->id().".log");
1371          if (!defined($SolutionData) || $SolutionData->size() == 0) {          if (!defined($SolutionData) || $SolutionData->size() == 0) {
# Line 1134  Line 1373 
1373                  $self->figmodel()->error_message("FIGMODEL:GapFillModel: Gap filling report not found!");                  $self->figmodel()->error_message("FIGMODEL:GapFillModel: Gap filling report not found!");
1374                  return $self->fail();                  return $self->fail();
1375          }          }
         $SolutionData->save("/home/chenry/Solution.txt");  
1376    
1377          #Looking for the last printed recursive MILP solution          #Looking for the last printed recursive MILP solution
1378          for (my $i=($SolutionData->size()-1); $i >=0; $i--) {          for (my $i=($SolutionData->size()-1); $i >=0; $i--) {
1379                  if (defined($SolutionData->get_row($i)->{"Notes"}) && $SolutionData->get_row($i)->{"Notes"}->[0] =~ m/^Recursive/) {                  if (defined($SolutionData->get_row($i)->{"Notes"}) && $SolutionData->get_row($i)->{"Notes"}->[0] =~ m/^Recursive/) {
1380                          my $AllSolutions = substr($SolutionData->get_row($i)->{"Notes"}->[0],15);                          my $AllSolutions = substr($SolutionData->get_row($i)->{"Notes"}->[0],15);
                         print "Solution:".$AllSolutions."\n";  
1381                          my @TempThree = split(/\|/,$AllSolutions);                          my @TempThree = split(/\|/,$AllSolutions);
1382                          if (@TempThree > 0 && $TempThree[0] =~ m/.+:(.+)/) {                          if (@TempThree > 0 && $TempThree[0] =~ m/.+:(.+)/) {
1383                                  my @TempFour = split(/,/,$1);                                  my @TempFour = split(/,/,$1);
# Line 1163  Line 1400 
1400                                                  push(@{$ReactionList},$ID);                                                  push(@{$ReactionList},$ID);
1401                                          }                                          }
1402                                  }                                  }
1403                                  print "Solution:".$TempThree[0]."\n";                                  $self->figmodel()->IntegrateGrowMatchSolution($self->id(),undef,$ReactionList,$DirectionList,"AUTOCOMPLETION",0,1);
                                 $self->figmodel()->IntegrateGrowMatchSolution($self->id(),undef,$ReactionList,$DirectionList,"GAP FILLING",0,1);  
1404                          }                          }
1405                          last;                          last;
1406                  }                  }
1407          }          }
1408    
1409          #Updating model stats with gap filling results          #Updating model stats with gap filling results
1410          my $ElapsedTime = time() - $StartTime;          my $ElapsedTime = time() - $StartTime;
1411          $self->figmodel()->ClearDBModel($self->id(),1);          $self->reaction_table(1);
1412            $self->calculate_model_changes($OriginalRxn,"AUTOCOMPLETION");
1413    
1414          #Determining why each gap filling reaction was added          #Determining why each gap filling reaction was added
1415          $self->figmodel()->IdentifyDependancyOfGapFillingReactions($self->id(),$Media);          $self->figmodel()->IdentifyDependancyOfGapFillingReactions($self->id(),$Media);
1416          if (!defined($donotclear) || $donotclear != 1) {          if (!defined($donotclear) || $donotclear != 1) {
                 $self->figmodel()->AddBiologTransporters($self->id());  
1417                  if ($self->id() !~ m/MGRast/) {                  if ($self->id() !~ m/MGRast/) {
1418                          $self->update_stats_for_gap_filling($ElapsedTime);                          $self->update_stats_for_gap_filling($ElapsedTime);
1419                  }                  }
# Line 1191  Line 1429 
1429          return $self->success();          return $self->success();
1430  }  }
1431    
1432    =head3 calculate_model_changes
1433    Definition:
1434            FIGMODELmodel->calculate_model_changes(FIGMODELTable:original reaction table,string:modification cause);
1435    Description:
1436    
1437    =cut
1438    
1439    sub calculate_model_changes {
1440            my ($self,$originalReactions,$cause,$tbl,$version) = @_;
1441            my $modTime = time();
1442            if (!defined($version)) {
1443                    $version = $self->selected_version();
1444            }
1445            my $user = $self->figmodel()->user();
1446            #Getting the history table
1447            my $histTbl = $self->model_history();
1448            #Checking for differences
1449            if (!defined($tbl)) {
1450                    $tbl = $self->reaction_table();
1451            }
1452            for (my $i=0; $i < $tbl->size(); $i++) {
1453                    my $row = $tbl->get_row($i);
1454                    my $orgRow = $originalReactions->get_row_by_key($row->{LOAD}->[0],"LOAD");
1455                    if (!defined($orgRow)) {
1456                            $histTbl->add_row({Reaction => [$row->{LOAD}->[0]], DirectionChange => $row->{DIRECTIONALITY}, GeneChange => $row->{"ASSOCIATED PEG"}, Action => ["ADDED"], ModificationTime => [$modTime], ModifcationCause => [$cause], User => [$user], Version => [$version]});
1457                    } else {
1458                            my $geneChanges;
1459                            my $directionChange;
1460                            if ($orgRow->{"DIRECTIONALITY"}->[0] ne $row->{"DIRECTIONALITY"}->[0]) {
1461                                    $directionChange = $orgRow->{"DIRECTIONALITY"}->[0]." to ".$row->{"DIRECTIONALITY"}->[0];
1462                            }
1463                            for (my $j=0; $j < @{$row->{"ASSOCIATED PEG"}}; $j++) {
1464                                    my $match = 0;
1465                                    if (defined($orgRow->{"ASSOCIATED PEG"})) {
1466                                            for (my $k=0; $k < @{$orgRow->{"ASSOCIATED PEG"}}; $k++) {
1467                                                    if ($row->{"ASSOCIATED PEG"}->[$j] eq $orgRow->{"ASSOCIATED PEG"}->[$k]) {
1468                                                            $match = 1;
1469                                                    }
1470                                            }
1471                                    }
1472                                    if ($match == 0) {
1473                                            push(@{$geneChanges},"Added ".$row->{"ASSOCIATED PEG"}->[$j]);
1474                                    }
1475                            }
1476                            if (defined($orgRow->{"ASSOCIATED PEG"})) {
1477                                    for (my $k=0; $k < @{$orgRow->{"ASSOCIATED PEG"}}; $k++) {
1478                                            my $match = 0;
1479                                            if (defined($row->{"ASSOCIATED PEG"})) {
1480                                                    for (my $j=0; $j < @{$row->{"ASSOCIATED PEG"}}; $j++) {
1481                                                            if ($row->{"ASSOCIATED PEG"}->[$j] eq $orgRow->{"ASSOCIATED PEG"}->[$k]) {
1482                                                                    $match = 1;
1483                                                            }
1484                                                    }
1485                                            }
1486                                            if ($match == 0) {
1487                                                    push(@{$geneChanges},"Removed ".$orgRow->{"ASSOCIATED PEG"}->[$k]);
1488                                            }
1489                                    }
1490                            }
1491                            if ((defined($directionChange) && length($directionChange) > 0) || defined($geneChanges) && @{$geneChanges} > 0) {
1492                                    $histTbl->add_row({Reaction => [$row->{LOAD}->[0]], DirectionChange => [$directionChange], GeneChange => $geneChanges, Action => ["CHANGE"], ModificationTime => [$modTime], ModifcationCause => [$cause], User => [$user], Version => [$version]});
1493                            }
1494                    }
1495            }
1496            #Looking for removed reactions
1497            for (my $i=0; $i < $originalReactions->size(); $i++) {
1498                    my $row = $originalReactions->get_row($i);
1499                    my $orgRow = $tbl->get_row_by_key($row->{LOAD}->[0],"LOAD");
1500                    if (!defined($orgRow)) {
1501                            $histTbl->add_row({Reaction => [$row->{LOAD}->[0]], DirectionChange => $row->{DIRECTIONALITY}, GeneChange => $row->{"ASSOCIATED PEG"}, Action => ["REMOVED"], ModificationTime => [$modTime], ModifcationCause => [$cause], User => [$user], Version => [$version]});
1502                    }
1503            }
1504            $histTbl->save();
1505    }
1506    
1507    =head3 GapGenModel
1508    Definition:
1509            FIGMODELmodel->GapGenModel();
1510    Description:
1511            Runs the gap generation algorithm to correct a single false positive prediction. Results are loaded into a table.
1512    =cut
1513    
1514    sub GapGenModel {
1515            my ($self,$Media,$KOList,$NoKOList,$Experiment,$SolutionLimit) = @_;
1516    
1517            #Enforcing nonoptional arguments
1518            if (!defined($Media)) {
1519                    return undef;
1520            }
1521            if (!defined($KOList)) {
1522                    $KOList->[0] = "none";
1523            }
1524            if (!defined($NoKOList)) {
1525                    $NoKOList->[0] = "none";
1526            }
1527            if (!defined($Experiment)) {
1528                    $Experiment= "ReactionKO";
1529            }
1530            if (!defined($SolutionLimit)) {
1531                    $SolutionLimit = "10";
1532            }
1533    
1534            #Translating the KO lists into arrays
1535            if (ref($KOList) ne "ARRAY") {
1536                    my $temp = $KOList;
1537                    $KOList = ();
1538                    push(@{$KOList},split(/[,;]/,$temp));
1539            }
1540            my $noKOHash;
1541            if (defined($NoKOList) && ref($NoKOList) ne "ARRAY") {
1542                    my $temp = $NoKOList;
1543                    $NoKOList = ();
1544                    push(@{$NoKOList},split(/[,;]/,$temp));
1545                    foreach my $rxn (@{$NoKOList}) {
1546                            $noKOHash->{$rxn} = 1;
1547                    }
1548            }
1549    
1550            #Checking if solutions exist for the input parameters
1551            $self->aquireModelLock();
1552            my $tbl = $self->load_model_table("GapGenSolutions");
1553            my $solutionRow = $tbl->get_table_by_key($Experiment,"Experiment")->get_table_by_key($Media,"Media")->get_row_by_key(join(",",@{$KOList}),"KOlist");
1554            my $solutions;
1555            if (defined($solutionRow)) {
1556                    #Checking if any solutions conform to the no KO list
1557                    foreach my $solution (@{$solutionRow->{Solutions}}) {
1558                            my @reactions = split(/,/,$solution);
1559                            my $include = 1;
1560                            foreach my $rxn (@reactions) {
1561                                    if ($rxn =~ m/(rxn\d\d\d\d\d)/) {
1562                                            if (defined($noKOHash->{$1})) {
1563                                                    $include = 0;
1564                                            }
1565                                    }
1566                            }
1567                            if ($include == 1) {
1568                                    push(@{$solutions},$solution);
1569                            }
1570                    }
1571            } else {
1572                    $solutionRow = {Media => [$Media],Experiment => [$Experiment],KOlist => [join(",",@{$KOList})]};
1573                    $tbl->add_row($solutionRow);
1574                    $self->figmodel()->database()->save_table($tbl);
1575            }
1576            $self->releaseModelLock();
1577    
1578            #Returning solution list of solutions were found
1579            if (defined($solutions) && @{$solutions} > 0) {
1580                    return $solutions;
1581            }
1582    
1583            #Getting unique filename
1584            my $Filename = $self->figmodel()->filename();
1585    
1586            #Running the gap generation
1587            system($self->figmodel()->GenerateMFAToolkitCommandLineCall($Filename,$self->id().$self->selected_version(),$Media,["GapGeneration"],{"Recursive MILP solution limit" => $SolutionLimit ,"Reactions that should always be active" => join(";",@{$NoKOList}),"Reactions to knockout" => join(";",@{$KOList}),"Reactions that are always blocked" => "none"},"Gapgeneration-".$self->id().$self->selected_version()."-".$Filename.".log",undef,undef));
1588            my $ProblemReport = $self->figmodel()->LoadProblemReport($Filename);
1589            if (!defined($ProblemReport)) {
1590                    $self->figmodel()->error_message("FIGMODEL:GapGenerationAlgorithm;No problem report;".$Filename.";".$self->id().$self->selected_version().";".$Media.";".$KOList.";".$NoKOList);
1591                    return undef;
1592            }
1593    
1594            #Clearing the output folder and log file
1595            $self->figmodel()->clearing_output($Filename,"Gapgeneration-".$self->id().$self->selected_version()."-".$Filename.".log");
1596    
1597            #Saving the solution
1598            $self->aquireModelLock();
1599            $tbl = $self->load_model_table("GapGenSolutions");
1600            $solutionRow = $tbl->get_table_by_key($Experiment,"Experiment")->get_table_by_key($Media,"Media")->get_row_by_key(join(",",@{$KOList}),"KOlist");
1601            for (my $j=0; $j < $ProblemReport->size(); $j++) {
1602                    if ($ProblemReport->get_row($j)->{"Notes"}->[0] =~ m/^Recursive\sMILP\s([^)]+)/) {
1603                            my @SolutionList = split(/\|/,$1);
1604                            for (my $k=0; $k < @SolutionList; $k++) {
1605                                    if ($SolutionList[$k] =~ m/(\d+):(.+)/) {
1606                                            push(@{$solutionRow->{Solutions}},$2);
1607                                            push(@{$solutions},$2);
1608                                    }
1609                            }
1610                    }
1611            }
1612            $self->figmodel()->database()->save_table($tbl);
1613            $self->releaseModelLock();
1614    
1615            return $solutions;
1616    }
1617    
1618  =head3 datagapfill  =head3 datagapfill
1619  Definition:  Definition:
1620          success()/fail() = FIGMODELmodel->datagapfill();          success()/fail() = FIGMODELmodel->datagapfill();
# Line 1201  Line 1625 
1625          my ($self,$GapFillingRunSpecs,$TansferFileSuffix) = @_;          my ($self,$GapFillingRunSpecs,$TansferFileSuffix) = @_;
1626          my $UniqueFilename = $self->figmodel()->filename();          my $UniqueFilename = $self->figmodel()->filename();
1627          if (defined($GapFillingRunSpecs) && @{$GapFillingRunSpecs} > 0) {          if (defined($GapFillingRunSpecs) && @{$GapFillingRunSpecs} > 0) {
                 print "Gap filling specs:\n".join("\n",@{$GapFillingRunSpecs})."\n\n";  
1628                  system($self->figmodel()->GenerateMFAToolkitCommandLineCall($UniqueFilename,$self->id().$self->selected_version(),"NoBounds",["DataGapFilling"],{"Reactions to knockout" => $self->config("permanently knocked out reactions")->[0],"Gap filling runs" => join(";",@{$GapFillingRunSpecs})},"GapFilling-".$self->id().$self->selected_version()."-".$UniqueFilename.".log",undef,undef));                  system($self->figmodel()->GenerateMFAToolkitCommandLineCall($UniqueFilename,$self->id().$self->selected_version(),"NoBounds",["DataGapFilling"],{"Reactions to knockout" => $self->config("permanently knocked out reactions")->[0],"Gap filling runs" => join(";",@{$GapFillingRunSpecs})},"GapFilling-".$self->id().$self->selected_version()."-".$UniqueFilename.".log",undef,undef));
   
1629                  #Checking that the solution exists                  #Checking that the solution exists
1630                  if (!-e $self->config("MFAToolkit output directory")->[0].$UniqueFilename."/GapFillingSolutionTable.txt") {                  if (!-e $self->config("MFAToolkit output directory")->[0].$UniqueFilename."/GapFillingSolutionTable.txt") {
1631                          $self->figmodel()->error_message("FIGMODEL:GapFillingAlgorithm: Could not find MFA output file!");                          $self->figmodel()->error_message("FIGMODEL:GapFillingAlgorithm: Could not find MFA output file!");
# Line 1213  Line 1635 
1635                  my $GapFillResultTable = $self->figmodel()->database()->load_table($self->config("MFAToolkit output directory")->[0].$UniqueFilename."/GapFillingSolutionTable.txt",";","",0,undef);                  my $GapFillResultTable = $self->figmodel()->database()->load_table($self->config("MFAToolkit output directory")->[0].$UniqueFilename."/GapFillingSolutionTable.txt",";","",0,undef);
1636                  if (defined($TansferFileSuffix)) {                  if (defined($TansferFileSuffix)) {
1637                          system("cp ".$self->config("MFAToolkit output directory")->[0].$UniqueFilename."/GapFillingSolutionTable.txt ".$self->directory().$self->id().$self->selected_version()."-".$TansferFileSuffix.".txt");                          system("cp ".$self->config("MFAToolkit output directory")->[0].$UniqueFilename."/GapFillingSolutionTable.txt ".$self->directory().$self->id().$self->selected_version()."-".$TansferFileSuffix.".txt");
                         system("cp ".$self->config("MFAToolkit output directory")->[0].$UniqueFilename."/GapFillingReport.txt ".$self->directory().$self->id().$self->selected_version()."-".$TansferFileSuffix.".txt");  
1638                  }                  }
   
1639                  #If the system is not configured to preserve all logfiles, then the mfatoolkit output folder is deleted                  #If the system is not configured to preserve all logfiles, then the mfatoolkit output folder is deleted
1640                  $self->figmodel()->clearing_output($UniqueFilename,"GapFilling-".$self->id().$self->selected_version()."-".$UniqueFilename.".log");                  $self->figmodel()->clearing_output($UniqueFilename,"GapFilling-".$self->id().$self->selected_version()."-".$UniqueFilename.".log");
1641                  return $GapFillingRunSpecs;                  return $GapFillResultTable;
1642          }          }
1643          if (defined($TansferFileSuffix)) {          if (defined($TansferFileSuffix)) {
1644                  $self->figmodel()->database()->print_array_to_file($self->directory().$self->id().$self->selected_version()."-".$TansferFileSuffix.".txt",["Experiment;Solution index;Solution cost;Solution reactions"]);                  $self->figmodel()->database()->print_array_to_file($self->directory().$self->id().$self->selected_version()."-".$TansferFileSuffix.".txt",["Experiment;Solution index;Solution cost;Solution reactions"]);
# Line 1284  Line 1704 
1704                          push(@{$DirectionArray},$SolutionHash{$ReactionList[$k]});                          push(@{$DirectionArray},$SolutionHash{$ReactionList[$k]});
1705                  }                  }
1706                  print "Integrating solution!\n";                  print "Integrating solution!\n";
1707                  $self->IntegrateGrowMatchSolution($self->id().$self->selected_version(),$self->directory().$self->id().$TempVersion.".txt",$ReactionArray,$DirectionArray,"Gapfilling ".$GapFillResultTable->get_row($i)->{"Experiment"}->[0],1,1);                  $self->figmodel()->IntegrateGrowMatchSolution($self->id().$self->selected_version(),$self->directory().$self->id().$TempVersion.".txt",$ReactionArray,$DirectionArray,"Gapfilling ".$GapFillResultTable->get_row($i)->{"Experiment"}->[0],1,1);
1708                  my $model = $self->get_model($self->id().$TempVersion);                  $self->PrintModelLPFile();
                 $model->PrintModelLPFile();  
1709                  #Running the model against all available experimental data                  #Running the model against all available experimental data
1710                  print "Running test model!\n";                  print "Running test model!\n";
1711                  my ($FalsePostives,$FalseNegatives,$CorrectNegatives,$CorrectPositives,$Errorvector,$HeadingVector) = $self->RunAllStudiesWithDataFast("All");                  my ($FalsePostives,$FalseNegatives,$CorrectNegatives,$CorrectPositives,$Errorvector,$HeadingVector) = $self->RunAllStudiesWithDataFast("All");
# Line 1322  Line 1741 
1741  =cut  =cut
1742  sub status {  sub status {
1743          my ($self) = @_;          my ($self) = @_;
1744          return $self->{_data}->{status}->[0];          return $self->{_data}->status();
1745  }  }
1746    
1747  =head3 message  =head3 message
# Line 1333  Line 1752 
1752  =cut  =cut
1753  sub message {  sub message {
1754          my ($self) = @_;          my ($self) = @_;
1755          return $self->{_data}->{message}->[0];          return $self->{_data}->message();
1756  }  }
1757    
1758  =head3 set_status  =head3 set_status
# Line 1348  Line 1767 
1767  =cut  =cut
1768  sub set_status {  sub set_status {
1769          my ($self,$NewStatus,$Message) = @_;          my ($self,$NewStatus,$Message) = @_;
1770            $self->{_data}->status($NewStatus);
1771          #Getting the model row from the MODELS table          $self->{_data}->message($Message);
         $self->{_data}->{status}->[0] = $NewStatus;  
         $self->{_data}->{message}->[0] = $Message;  
         $self->figmodel()->database()->update_row("MODELS",$self->{_data},"id");  
1772          return $self->config("SUCCESS")->[0];          return $self->config("SUCCESS")->[0];
1773  }  }
1774    
# Line 1367  Line 1783 
1783  sub CreateSingleGenomeReactionList {  sub CreateSingleGenomeReactionList {
1784          my ($self,$RunGapFilling) = @_;          my ($self,$RunGapFilling) = @_;
1785    
1786            #Creating directory
1787            if ($self->owner() ne "master" && !-d $self->figmodel()->config("organism directory")->[0].$self->owner()."/") {
1788                    system("mkdir ".$self->figmodel()->config("organism directory")->[0].$self->owner()."/");
1789            } elsif ($self->owner() eq "master" && !-d $self->figmodel()->config("organism directory")->[0].$self->genome()."/") {
1790                    system("mkdir ".$self->figmodel()->config("organism directory")->[0].$self->genome()."/");
1791            }
1792            if ($self->owner() ne "master" && !-d $self->figmodel()->config("organism directory")->[0].$self->owner()."/".$self->genome()."/") {
1793                    system("mkdir ".$self->figmodel()->config("organism directory")->[0].$self->owner()."/".$self->genome()."/");
1794            }
1795    
1796          #Getting genome stats          #Getting genome stats
1797          my $genomestats = $self->figmodel()->get_genome_stats($self->genome());          my $genomestats = $self->figmodel()->get_genome_stats($self->genome());
1798          my $FeatureTable = $self->figmodel()->GetGenomeFeatureTable($self->genome());          my $FeatureTable = $self->figmodel()->GetGenomeFeatureTable($self->genome());
# Line 1381  Line 1807 
1807          }          }
1808          #Setting up needed variables          #Setting up needed variables
1809          my $OriginalModelTable = undef;          my $OriginalModelTable = undef;
1810          #Locking model status table          if ($self->status() == 0) {
         my $ModelTable = $self->figmodel()->database()->LockDBTable("MODELS");  
         my $Row = $ModelTable->get_row_by_key($self->id(),"id");  
         if (!defined($Row) || !defined($Row->{status}->[0])) {  
                 $self->figmodel()->database()->UnlockDBTable("MODELS");  
                 $self->figmodel()->error_message("FIGMODEL:CreateSingleGenomeReactionList: ".$self->id()." has no row in models table!");  
                 return $self->fail();  
         } elsif ($Row->{status}->[0] == 0) {  
1811                  $self->figmodel()->error_message("FIGMODEL:CreateSingleGenomeReactionList:Model is already being built. Canceling current build.");                  $self->figmodel()->error_message("FIGMODEL:CreateSingleGenomeReactionList:Model is already being built. Canceling current build.");
                 $self->figmodel()->database()->UnlockDBTable("MODELS");  
1812                  return $self->fail();                  return $self->fail();
1813          }elsif ($Row->{status}->[0] == 1) {          }elsif ($self->status() == 1) {
1814                  $OriginalModelTable = $self->reaction_table();                  $OriginalModelTable = $self->reaction_table();
1815                  $self->ArchiveModel();                  $self->set_status(0,"Rebuilding preliminary reconstruction");
                 $Row->{status}->[0] = 0;  
                 $Row->{message}->[0] = "Rebuilding preliminary reconstruction";  
1816          } else {          } else {
1817                  $Row->{status}->[0] = 0;                  $self->set_status(0,"Preliminary reconstruction");
                 $Row->{message}->[0] = "Preliminary reconstruction";  
1818          }          }
         #Updating the status table  
         $self->figmodel()->database()->save_table($ModelTable);  
         $self->figmodel()->database()->UnlockDBTable("MODELS");  
1819          #Sorting GenomeData by gene location on the chromosome          #Sorting GenomeData by gene location on the chromosome
1820            my $ftrTbl = $self->figmodel()->database()->get_table("ROLERXNMAPPING");
1821          $FeatureTable->sort_rows("MIN LOCATION");          $FeatureTable->sort_rows("MIN LOCATION");
1822          my ($ComplexHash,$SuggestedMappings,$UnrecognizedReactions,$ReactionHash);          my ($ComplexHash,$SuggestedMappings,$UnrecognizedReactions,$ReactionHash);
1823          my %LastGenePosition;          my %LastGenePosition;
# Line 1476  Line 1889 
1889                          }                          }
1890                  }                  }
1891          }          }
   
1892          #Creating nonadjacent complexes          #Creating nonadjacent complexes
1893          my @ReactionList = keys(%{$ReactionHash});          my @ReactionList = keys(%{$ReactionHash});
1894          foreach my $Reaction (@ReactionList) {          foreach my $Reaction (@ReactionList) {
# Line 1582  Line 1994 
1994                  $NewModelTable->add_row({"LOAD" => [$ReactionID],"DIRECTIONALITY" => [$Directionality],"COMPARTMENT" => ["c"],"ASSOCIATED PEG" => [join("|",@{$ReactionHash->{$ReactionID}->{"GENES"}})],"SUBSYSTEM" => [$Subsystem],"CONFIDENCE" => [$ReactionHash->{$ReactionID}->{"CONFIDENCE"}->[0]],"REFERENCE" => [$Source],"NOTES" => ["NONE"]});                  $NewModelTable->add_row({"LOAD" => [$ReactionID],"DIRECTIONALITY" => [$Directionality],"COMPARTMENT" => ["c"],"ASSOCIATED PEG" => [join("|",@{$ReactionHash->{$ReactionID}->{"GENES"}})],"SUBSYSTEM" => [$Subsystem],"CONFIDENCE" => [$ReactionHash->{$ReactionID}->{"CONFIDENCE"}->[0]],"REFERENCE" => [$Source],"NOTES" => ["NONE"]});
1995          }          }
1996    
1997            #Getting feature rows for features that are lumped
1998            my @rows = $ftrTbl->get_rows_by_key("2","MASTER");
1999            for (my $i=0; $i < @rows; $i++) {
2000                    my $rxn = $rows[$i]->{REACTION}->[0];
2001                    my $role = $rows[$i]->{ROLE}->[0];
2002                    my @orgrows = $FeatureTable->get_rows_by_key($role,"ROLES");
2003                    my $genes;
2004                    for (my $j=0; $j < @orgrows; $j++) {
2005                            if ($orgrows[$j]->{ID}->[0] =~ m/(peg\.\d+)/) {
2006                                    push(@{$genes},$1);
2007                            }
2008                    }
2009                    if (defined($genes) && @{$genes} > 0) {
2010                            my $row = $NewModelTable->get_row_by_key($rxn,"LOAD");
2011                            my $newGeneAssociations;
2012                            for (my $k=0; $k < @{$genes}; $k++) {
2013                                    for (my $j=0; $j < @{$row->{"ASSOCIATED PEG"}}; $j++) {
2014                                            my $peg = $genes->[$k];
2015                                            if ($row->{"ASSOCIATED PEG"}->[$j] !~ m/$peg/) {
2016                                                    push(@{$newGeneAssociations},$row->{"ASSOCIATED PEG"}->[$j]."+".$peg);
2017                                            }
2018                                    }
2019                            }
2020                            $row->{"ASSOCIATED PEG"} = $newGeneAssociations;
2021                    }
2022            }
2023    
2024          #Adding the spontaneous and universal reactions          #Adding the spontaneous and universal reactions
2025          foreach my $ReactionID (@{$self->config("spontaneous reactions")}) {          foreach my $ReactionID (@{$self->config("spontaneous reactions")}) {
2026                  #Getting the thermodynamic reversibility from the database                  #Getting the thermodynamic reversibility from the database
# Line 1601  Line 2040 
2040          }          }
2041    
2042          #Checking if a biomass reaction already exists          #Checking if a biomass reaction already exists
2043          my $BiomassReactionRow = $self->figmodel()->database()->get_row_by_key("BIOMASS TABLE",$self->id(),"MODELS");          my $BiomassReactionRow = $self->BuildSpecificBiomassReaction();
         if (!defined($BiomassReactionRow)) {  
                 $BiomassReactionRow = $self->BuildSpecificBiomassReaction();  
2044                  if (!defined($BiomassReactionRow)) {                  if (!defined($BiomassReactionRow)) {
2045                          $self->set_status(-2,"Preliminary reconstruction failed: could not generate biomass reaction");                          $self->set_status(-2,"Preliminary reconstruction failed: could not generate biomass reaction");
2046                          $self->figmodel()->error_message("FIGMODEL:CreateModelReactionList: Could not generate biomass function for ".$self->id()."!");                          $self->figmodel()->error_message("FIGMODEL:CreateModelReactionList: Could not generate biomass function for ".$self->id()."!");
2047                          return $self->fail();                          return $self->fail();
2048                  }                  }
         }  
2049          my $ReactionList = $BiomassReactionRow->{"ESSENTIAL REACTIONS"};          my $ReactionList = $BiomassReactionRow->{"ESSENTIAL REACTIONS"};
2050          push(@{$ReactionList},$BiomassReactionRow->{DATABASE}->[0]);          push(@{$ReactionList},$BiomassReactionRow->{DATABASE}->[0]);
2051    
# Line 1641  Line 2077 
2077                  }                  }
2078          }          }
2079    
2080            #If an original model exists, we copy the gap filling solution from that model
2081            if (defined($OriginalModelTable)) {
2082                    for (my $i=0; $i < $OriginalModelTable->size(); $i++) {
2083                            if ($OriginalModelTable->get_row($i)->{"ASSOCIATED PEG"}->[0] =~ m/GAP/ && $OriginalModelTable->get_row($i)->{"ASSOCIATED PEG"}->[0] ne "INITIAL GAP FILLING") {
2084                                    my $Row = $NewModelTable->get_row_by_key($OriginalModelTable->get_row($i)->{"LOAD"}->[0],"LOAD");
2085                                    if (!defined($Row)) {
2086                                            $NewModelTable->add_row($OriginalModelTable->get_row($i));
2087                                    }
2088                            }
2089                    }
2090            }
2091    
2092          #Now we compare the model to the previous model to determine if any differences exist that aren't gap filling reactions          #Now we compare the model to the previous model to determine if any differences exist that aren't gap filling reactions
2093          if (defined($OriginalModelTable)) {          if (defined($OriginalModelTable)) {
2094                  my $PerfectMatch = 1;                  my $PerfectMatch = 1;
# Line 1700  Line 2148 
2148          #Saving the new model to file          #Saving the new model to file
2149          $self->set_status(1,"Preliminary reconstruction complete");          $self->set_status(1,"Preliminary reconstruction complete");
2150          $self->figmodel()->database()->save_table($NewModelTable);          $self->figmodel()->database()->save_table($NewModelTable);
2151          $self->{_reaction_data} = $NewModelTable;          $self->reaction_table(1);
         #Clearing the previous model from the cache  
         $self->figmodel()->ClearDBModel($self->id(),1);  
2152          #Updating the model stats table          #Updating the model stats table
2153          $self->update_stats_for_build();          $self->update_stats_for_build();
2154          $self->PrintSBMLFile();          $self->PrintSBMLFile();
2155            if (defined($OriginalModelTable)) {
2156                    $self->calculate_model_changes($OriginalModelTable,"REBUILD");
2157            }
2158    
2159          #Adding model to gapfilling queue          #Adding model to gapfilling queue
2160          if (defined($RunGapFilling) && $RunGapFilling == 1) {          if (defined($RunGapFilling) && $RunGapFilling == 1) {
# Line 1724  Line 2173 
2173    
2174  sub CreateMetaGenomeReactionList {  sub CreateMetaGenomeReactionList {
2175          my ($self) = @_;          my ($self) = @_;
   
2176          #Checking if the metagenome file exists          #Checking if the metagenome file exists
2177          if (!-e $self->config("raw MGRAST directory")->[0].$self->genome().".summary") {          if (!-e $self->config("raw MGRAST directory")->[0].$self->genome().".summary") {
2178                  $self->error_message("FIGMODEL:CreateMetaGenomeReactionList: could not find raw data file for metagenome ".$self->genome());                  $self->error_message("FIGMODEL:CreateMetaGenomeReactionList: could not find raw data file for metagenome ".$self->genome());
2179                    return $self->fail();
2180          }          }
2181          #Loading metagenome data          #Loading metagenome data
2182          my $MGRASTData = $self->figmodel()->database()->load_multiple_column_file($self->config("raw MGRAST directory")->[0].$self->genome().".summary","\t");          my $MGRASTData = $self->figmodel()->database()->load_multiple_column_file($self->config("raw MGRAST directory")->[0].$self->genome().".summary","\t");
2183          if (!defined($MGRASTData)) {          if (!defined($MGRASTData)) {
2184                  $self->error_message("FIGMODEL:CreateMetaGenomeReactionList: could not find raw data file for metagenome ".$self->genome());                  $self->error_message("FIGMODEL:CreateMetaGenomeReactionList: could not find raw data file for metagenome ".$self->genome());
2185                    return $self->fail();
2186          }          }
   
2187          #Setting up needed variables          #Setting up needed variables
2188          my $OriginalModelTable = undef;          my $OriginalModelTable = undef;
   
2189          #Checking status          #Checking status
2190          if ($self->status() < 0) {          if ($self->status() < 0) {
2191                  $self->set_status(0,"Preliminary reconstruction");                  $self->set_status(0,"Preliminary reconstruction");
# Line 1749  Line 2197 
2197                  $self->ArchiveModel();                  $self->ArchiveModel();
2198                  $self->set_status(0,"Rebuilding preliminary reconstruction");                  $self->set_status(0,"Rebuilding preliminary reconstruction");
2199          }          }
2200            #Creating a hash of escores and pegs associated with each role
2201            my $rolePegHash;
2202            my $roleEscores;
2203            for (my $i=0; $i < @{$MGRASTData};$i++) {
2204                    #MD5,PEG,number of sims,role,sim e-scores,max escore,min escore,ave escore,stdev escore,ave exponent,stddev exponent
2205                    $rolePegHash->{$MGRASTData->[$i]->[3]}->{substr($MGRASTData->[$i]->[1],4)} = 1;
2206                    push(@{$roleEscores->{$MGRASTData->[$i]->[3]}},split(/;/,$MGRASTData->[$i]->[4]));
2207            }
2208          #Getting the reaction table          #Getting the reaction table
2209          my $ReactionTable = $self->figmodel()->database()->GetDBTable("REACTIONS");          my $ReactionTable = $self->figmodel()->database()->get_table("REACTIONS");
2210          #Creating model table          #Creating model table
2211          my $ModelTable = FIGMODELTable->new(["LOAD","DIRECTIONALITY","COMPARTMENT","ASSOCIATED PEG","SUBSYSTEM","CONFIDENCE","REFERENCE","NOTES"],$self->directory().$self->id().".txt",["LOAD"],";","|","REACTIONS\n");          my $ModelTable = $self->create_table_prototype("ModelReactions");
2212          for (my $i=0; $i < @{$MGRASTData};$i++) {          print $ModelTable->filename();
2213                  #MD5,PEG,number of sims,role,sim e-scores          my @roles = keys(%{$rolePegHash});
2214                  my $Role = $MGRASTData->[$i]->[3];          for (my $i=0; $i < @roles; $i++) {
2215                  my $MD5 = $MGRASTData->[$i]->[0];                  my $min = -1;
2216                  my $peg = $MGRASTData->[$i]->[1];                  my $max = -1;
2217                  my $sims = $MGRASTData->[$i]->[4];                  my $count = @{$roleEscores->{$roles[$i]}};
2218                  $sims =~ s/;/,/g;                  my $ave = 0;
2219                    my $stdev = 0;
2220                    my $aveexp = 0;
2221                    my $stdevexp = 0;
2222                    for (my $j=0; $j < @{$roleEscores->{$roles[$i]}}; $j++) {
2223                            if ($roleEscores->{$roles[$i]} < $min || $min == -1) {
2224                                    $min = $roleEscores->{$roles[$i]};
2225                            }
2226                            if ($roleEscores->{$roles[$i]} > $max || $max == -1) {
2227                                    $max = $roleEscores->{$roles[$i]};
2228                            }
2229                            $ave += $roleEscores->{$roles[$i]}->[$j];
2230                            if ($roleEscores->{$roles[$i]}->[$j] =~ m/e(-\d+$)/) {
2231                                    $aveexp += $1;
2232                            }
2233                    }
2234                    $ave = $ave/$count;
2235                    $aveexp = $aveexp/$count;
2236                    for (my $j=0; $j < @{$roleEscores->{$roles[$i]}}; $j++) {
2237                            $stdev += ($roleEscores->{$roles[$i]}->[$j]-$ave)*($roleEscores->{$roles[$i]}->[$j]-$ave);
2238                            if ($roleEscores->{$roles[$i]}->[$j] =~ m/e(-\d+$)/) {
2239                                    $stdevexp += ($1-$aveexp)*($1-$aveexp);
2240                            }
2241                    }
2242                    $stdev = sqrt($stdev/$count);
2243                    $stdevexp = sqrt($stdevexp/$count);
2244                  #Checking for subsystems                  #Checking for subsystems
2245                  my $GeneSubsystems = $self->figmodel()->subsystems_of_role($Role);                  my $GeneSubsystems = $self->figmodel()->subsystems_of_role($roles[$i]);
2246                  #Checking if there are reactions associated with this role                  #Checking if there are reactions associated with this role
2247                  my $ReactionHashArrayRef = $self->figmodel()->reactions_of_role($Role);                  my $ReactionHashArrayRef = $self->figmodel()->reactions_of_role($roles[$i]);
2248                  if ($ReactionHashArrayRef != 0) {                  if ($ReactionHashArrayRef != 0) {
2249                          foreach my $Mapping (@{$ReactionHashArrayRef}) {                          foreach my $Mapping (@{$ReactionHashArrayRef}) {
2250                                  if (defined($Mapping->{"REACTION"}) && defined($Mapping->{"MASTER"}) && defined($Mapping->{"SUBSYSTEM"}) && defined($Mapping->{"SOURCE"})) {                                  if (defined($Mapping->{"REACTION"}) && defined($Mapping->{"MASTER"}) && defined($Mapping->{"SUBSYSTEM"}) && defined($Mapping->{"SOURCE"})) {
# Line 1777  Line 2256 
2256                                                                  $ReactionRow = {"LOAD" => [$Mapping->{"REACTION"}->[0]],"DIRECTIONALITY" => [$self->figmodel()->reversibility_of_reaction($Mapping->{"REACTION"}->[0])],"COMPARTMENT" => ["c"]};                                                                  $ReactionRow = {"LOAD" => [$Mapping->{"REACTION"}->[0]],"DIRECTIONALITY" => [$self->figmodel()->reversibility_of_reaction($Mapping->{"REACTION"}->[0])],"COMPARTMENT" => ["c"]};
2257                                                                  $ModelTable->add_row($ReactionRow);                                                                  $ModelTable->add_row($ReactionRow);
2258                                                          }                                                          }
2259                                                          push(@{$ReactionRow->{"ASSOCIATED PEG"}},substr($peg,4));                                                          my %pegHash = %{$rolePegHash->{$roles[$i]}};
2260                                                          push(@{$ReactionRow->{"REFERENCE"}},$MD5.":".$Role);                                                          if (defined($ReactionRow->{"ASSOCIATED PEG"})) {
2261                                                          push(@{$ReactionRow->{"CONFIDENCE"}},$sims);                                                                  for (my $j=0; $j < @{$ReactionRow->{"ASSOCIATED PEG"}}; $j++) {
2262                                                                            $pegHash{$ReactionRow->{"ASSOCIATED PEG"}->[$j]} = 1;
2263                                                                    }
2264                                                            }
2265                                                            delete $ReactionRow->{"ASSOCIATED PEG"};
2266                                                            push(@{$ReactionRow->{"ASSOCIATED PEG"}},keys(%pegHash));
2267                                                            push(@{$ReactionRow->{"REFERENCE"}},$count.":".$ave.":".$stdev.":".$aveexp.":".$stdevexp.":".$min.":".$max);
2268                                                          if (defined($GeneSubsystems)) {                                                          if (defined($GeneSubsystems)) {
2269                                                                  push(@{$ReactionRow->{"SUBSYSTEM"}},@{$GeneSubsystems});                                                                  push(@{$ReactionRow->{"SUBSYSTEM"}},@{$GeneSubsystems});
2270                                                          }                                                          }
# Line 1823  Line 2308 
2308          }          }
2309    
2310          #Clearing the previous model from the cache          #Clearing the previous model from the cache
2311          $self->figmodel()->ClearDBModel($self->id(),1);          $self->figmodel()->database()->ClearDBModel($self->id(),1);
2312          $ModelTable->save();          $ModelTable->save();
2313    
2314          return $self->success();          return $self->success();
# Line 1839  Line 2324 
2324  sub ArchiveModel {  sub ArchiveModel {
2325          my ($self) = @_;          my ($self) = @_;
2326    
         #Making sure the model exists  
         if (!defined($self->stats())) {  
                 $self->figmodel()->error_message("FIGMODEL:ArchiveModel: Could not find specified ".$self->id()." in database!");  
                 return $self->fail();  
         }  
   
2327          #Checking that the model file exists          #Checking that the model file exists
2328          if (!(-e $self->filename())) {          if (!(-e $self->filename())) {
2329                  $self->figmodel()->error_message("FIGMODEL:ArchiveModel: Model file ".$self->filename()." not found!");                  $self->figmodel()->error_message("FIGMODEL:ArchiveModel: Model file ".$self->filename()." not found!");
# Line 1895  Line 2374 
2374          Runs microarray analysis attempting to turn off genes that are inactive in the microarray          Runs microarray analysis attempting to turn off genes that are inactive in the microarray
2375  =cut  =cut
2376  sub run_microarray_analysis {  sub run_microarray_analysis {
2377          my ($self,$media,$jobid,$index,$genecall) = @_;          my ($self,$media,$label,$index,$genecall) = @_;
2378          $genecall =~ s/_/:/g;          $genecall =~ s/_/:/g;
2379          $genecall =~ s/\//;/g;          $genecall =~ s/\//;/g;
2380          #print "\n\n".$genecall."\n\n";          my $uniqueFilename = $self->figmodel()->filename();
2381          my $command = $self->figmodel()->GenerateMFAToolkitCommandLineCall($jobid,$self->id(),$media,["MFA","MicroarrayAssertions"],{"Microarray assertions" => $self->id().";".$index.";".$genecall,"MFASolver" => "CPLEX","Network output location" => "/scratch/"},"MicroarrayAnalysis-".$jobid.".txt",undef,$self->selected_version());          my $command = $self->figmodel()->GenerateMFAToolkitCommandLineCall($uniqueFilename,$self->id(),$media,["ProductionMFA","ShewenellaExperiment"],{"Microarray assertions" => $label.";".$index.";".$genecall,"MFASolver" => "CPLEX","Network output location" => "/scratch/"},"MicroarrayAnalysis-".$uniqueFilename.".txt",undef,$self->selected_version());
         #print $command."\n";  
2382          system($command);          system($command);
2383          #system("/home/chenry/Software/MFAToolkitRepository/Linux/mfatoolkit resetparameter \"user bounds filename\" \"Carbon-D-Glucose.txt\" resetparameter output_folder \"32749.354149.0/\" resetparameter \"Microarray assertions\" \"Seed83333.1;0;peg.3130:-1;peg.4035:-1\" resetparameter \"MFASolver\" \"CPLEX\" resetparameter \"Network output location\" \"/scratch/\" LoadCentralSystem \"/vol/model-dev/MODEL_DEV_DB/Models/83333.1/Seed83333.1.txt\" > \"/vol/model-dev/MODEL_DEV_DB/ReactionDB/log/MicroarrayAnalysis-32749.354149.0.txt\"");          my $filename = $self->figmodel()->config("MFAToolkit output directory")->[0].$uniqueFilename."/MicroarrayOutput-".$index.".txt";
2384            if (-e $filename) {
2385                    my $output = $self->figmodel()->database()->load_single_column_file($filename);
2386                    if (defined($output->[0])) {
2387                            my @array = split(/;/,$output->[0]);
2388                            $self->figmodel()->clearing_output($uniqueFilename,"MicroarrayAnalysis-".$uniqueFilename.".txt");
2389                            return ($array[0],$array[1],$array[8].":".$array[2],$array[9].":".$array[3],$array[10].":".$array[4],$array[11].":".$array[5],$array[12].":".$array[6],$array[13].":".$array[7]);
2390                    }
2391                    print STDERR $filename." is empty!";
2392            }
2393            print STDERR $filename." not found!";
2394            $self->figmodel()->clearing_output($uniqueFilename,"MicroarrayAnalysis-".$uniqueFilename.".txt");
2395    
2396            return undef;
2397  }  }
2398    
2399  =head3 find_minimal_pathways  =head3 find_minimal_pathways
# Line 1912  Line 2403 
2403          Runs microarray analysis attempting to turn off genes that are inactive in the microarray          Runs microarray analysis attempting to turn off genes that are inactive in the microarray
2404  =cut  =cut
2405  sub find_minimal_pathways {  sub find_minimal_pathways {
2406          my ($self,$media,$objective,$solutionnum) = @_;          my ($self,$media,$objective,$solutionnum,$AllReversible,$additionalexchange) = @_;
2407    
2408          #Setting default media          #Setting default media
2409          if (!defined($media)) {          if (!defined($media)) {
# Line 1924  Line 2415 
2415                  $solutionnum = "5";                  $solutionnum = "5";
2416          }          }
2417    
2418            #Setting additional exchange fluxes
2419            if (!defined($additionalexchange) || length($additionalexchange) == 0) {
2420                    if ($self->id() eq "iAF1260") {
2421                            $additionalexchange = "cpd03422[c]:-100:100;cpd01997[c]:-100:100;cpd11416[c]:-100:0;cpd15378[c]:-100:0;cpd15486[c]:-100:0";
2422                    } else {
2423                            $additionalexchange = $self->figmodel()->config("default exchange fluxes")->[0];
2424                    }
2425            }
2426    
2427          #Translating objective          #Translating objective
2428          my $objectivestring;          my $objectivestring;
2429          if ($objective eq "ALL") {          if ($objective eq "ALL") {
# Line 1944  Line 2444 
2444                          }                          }
2445                  }                  }
2446                  for (my $i=0; $i < @objectives; $i++) {                  for (my $i=0; $i < @objectives; $i++) {
2447                          $self->find_minimal_pathways($media,$objectives[$i])                          $self->find_minimal_pathways($media,$objectives[$i]);
2448                  }                  }
2449                    return;
2450          } elsif ($objective eq "ENERGY") {          } elsif ($objective eq "ENERGY") {
2451                  $objectivestring = "MAX;FLUX;rxn00062;c;1";                  $objectivestring = "MAX;FLUX;rxn00062;c;1";
2452          } elsif ($objective =~ m/cpd\d\d\d\d\d/) {          } elsif ($objective =~ m/cpd\d\d\d\d\d/) {
2453                    if ($objective =~ m/\[(\w)\]/) {
2454                            $objectivestring = "MIN;DRAIN_FLUX;".$objective.";".$1.";1";
2455                            $additionalexchange .= ";".$objective."[".$1."]:-100:0";
2456                    } else {
2457                  $objectivestring = "MIN;DRAIN_FLUX;".$objective.";c;1";                  $objectivestring = "MIN;DRAIN_FLUX;".$objective.";c;1";
2458                            $additionalexchange .= ";".$objective."[c]:-100:0";
2459                    }
2460            } elsif ($objective =~ m/(rxn\d\d\d\d\d)/) {
2461                    my ($Reactants,$Products) = $self->figmodel()->GetReactionSubstrateData($objective);
2462                    for (my $i=0; $i < @{$Products};$i++) {
2463                            my $temp = $Products->[$i]->{"DATABASE"}->[0];
2464                            if ($additionalexchange !~ m/$temp/) {
2465                                    #$additionalexchange .= ";".$temp."[c]:-100:0";
2466                            }
2467                    }
2468                    for (my $i=0; $i < @{$Reactants};$i++) {
2469                            print $Reactants->[$i]->{"DATABASE"}->[0]." started\n";
2470                            $self->find_minimal_pathways($media,$Reactants->[$i]->{"DATABASE"}->[0],$additionalexchange);
2471                            print $Reactants->[$i]->{"DATABASE"}->[0]." done\n";
2472                    }
2473                    return;
2474          }          }
2475    
2476          #Setting additional exchange fluxes          #Adding additional drains
2477          my $additionalexchange = $self->config("default exchange fluxes")->[0];          if (($objective eq "cpd15665" || $objective eq "cpd15667" || $objective eq "cpd15668" || $objective eq "cpd15669") && $additionalexchange !~ m/cpd15666/) {
         if ($objective eq "cpd15665" || $objective eq "cpd15667" || $objective eq "cpd15668" || $objective eq "cpd15669") {  
2478                  $additionalexchange .= ";cpd15666[c]:0:100";                  $additionalexchange .= ";cpd15666[c]:0:100";
2479          } elsif ($objective eq "cpd11493") {          } elsif ($objective eq "cpd11493" && $additionalexchange !~ m/cpd12370/) {
2480                  $additionalexchange .= ";cpd12370[c]:0:100";                  $additionalexchange .= ";cpd12370[c]:0:100";
2481          } elsif ($objective eq "cpd00166") {          } elsif ($objective eq "cpd00166" && $additionalexchange !~ m/cpd01997/) {
2482                  $additionalexchange .= ";cpd01997[c]:0:100;cpd03422[c]:0:100";                  $additionalexchange .= ";cpd01997[c]:0:100;cpd03422[c]:0:100";
2483          }          }
2484    
2485          #Running MFAToolkit          #Running MFAToolkit
2486          my $filename = $self->figmodel()->filename();          my $filename = $self->figmodel()->filename();
2487          my $command = $self->figmodel()->GenerateMFAToolkitCommandLineCall($filename,$self->id(),$media,["MFA"],{"Recursive MILP solution limit" => $solutionnum,"Generate pathways to objective" => 1,"MFASolver" => "CPLEX","objective" => $objectivestring,"exchange species" => $additionalexchange},"MinimalPathways-".$media."-".$self->id().$self->selected_version().".txt",undef,$self->selected_version());          my $command;
2488            if (defined($AllReversible) && $AllReversible == 1) {
2489                    $command = $self->figmodel()->GenerateMFAToolkitCommandLineCall($filename,$self->id(),$media,["ProductionMFA"],{"Make all reactions reversible in MFA"=>1, "Recursive MILP solution limit" => $solutionnum,"Generate pathways to objective" => 1,"MFASolver" => "CPLEX","objective" => $objectivestring,"exchange species" => $additionalexchange},"MinimalPathways-".$media."-".$self->id().$self->selected_version().".txt",undef,$self->selected_version());
2490            } else {
2491                    $command = $self->figmodel()->GenerateMFAToolkitCommandLineCall($filename,$self->id(),$media,["ProductionMFA"],{"Make all reactions reversible in MFA"=>0, "Recursive MILP solution limit" => $solutionnum,"Generate pathways to objective" => 1,"MFASolver" => "CPLEX","objective" => $objectivestring,"exchange species" => $additionalexchange},"MinimalPathways-".$media."-".$self->id().$self->selected_version().".txt",undef,$self->selected_version());
2492            }
2493          system($command);          system($command);
2494    
2495          #Loading problem report          #Loading problem report
# Line 1972  Line 2497 
2497          #Clearing output          #Clearing output
2498          $self->figmodel()->clearing_output($filename,"MinimalPathways-".$media."-".$self->id()."-".$objective.".txt");          $self->figmodel()->clearing_output($filename,"MinimalPathways-".$media."-".$self->id()."-".$objective.".txt");
2499          if (!defined($results)) {          if (!defined($results)) {
2500                    print STDERR $objective." pathway results not found!\n";
2501                  return;                  return;
2502          }          }
2503    
# Line 1983  Line 2509 
2509                  @Array = /\d+:([^\|]+)\|/g;                  @Array = /\d+:([^\|]+)\|/g;
2510          }          }
2511    
2512          # Storing data in a figmodel table          #Writing output to file
2513          my $TableObject;          $self->figmodel()->database()->print_array_to_file($self->directory()."MinimalPathways-".$media."-".$objective."-".$self->id()."-".$AllReversible."-".$self->selected_version().".txt",[join("|",@Array)]);
         if (-e $self->directory()."MinimalPathways-".$media."-".$self->id().$self->selected_version().".txt") {  
                 $TableObject->load_table($self->directory()."MinimalPathways-".$media."-".$self->id().$self->selected_version().".txt",";","|",0,["OBJECTIVE"]);  
         } else {  
                 $TableObject = FIGMODELTable->new(["OBJECTIVE","REACTIONS"],$self->directory()."MinimalPathways-".$media."-".$self->id().$self->selected_version().".txt",["OBJECTIVE"],";","|",undef);  
         }  
         my $tablerow = $TableObject->get_row_by_key($objective,"OBJECTIVE",1);  
         push(@{$tablerow->{"REACTIONS"}},@Array);  
         $TableObject->save();  
2514  }  }
2515    
2516  =head3 calculate_growth  =head3 find_minimal_pathways
2517  Definition:  Definition:
2518          string::growth = FIGMODELmodel->calculate_growth(string:media);          int::status = FIGMODEL->find_minimal_pathways(string::media,string::objective);
2519  Description:  Description:
2520          Calculating growth in the input media          Runs microarray analysis attempting to turn off genes that are inactive in the microarray
2521  =cut  =cut
2522  sub calculate_growth {  sub find_minimal_pathways_two {
2523          my ($self,$Media) = @_;          my ($self,$media,$objective,$solutionnum,$AllReversible,$additionalexchange) = @_;
2524          my $UniqueFilename = $self->figmodel()->filename();  
2525          system($self->figmodel()->GenerateMFAToolkitCommandLineCall($UniqueFilename,$self->id(),$Media,["ProductionMFA"],{"optimize metabolite production if objective is zero" => 1},$self->id()."-".$Media."-GrowthTest.txt",undef,$self->selected_version()));          #Setting default media
2526          my $ProblemReport = $self->figmodel()->LoadProblemReport($UniqueFilename);          if (!defined($media)) {
2527          my $Result;                  $media = "Complete";
         if (defined($ProblemReport)) {  
                 my $Row = $ProblemReport->get_row(0);  
                 if (defined($Row) && defined($Row->{"Objective"}->[0])) {  
                         if ($Row->{"Objective"}->[0] < 0.00000001) {  
                                 $Result = "NOGROWTH:".$Row->{"Individual metabolites with zero production"}->[0];  
                         } else {  
                                 $Result = $Row->{"Objective"}->[0];  
2528                          }                          }
2529    
2530            #Setting default solution number
2531            if (!defined($solutionnum)) {
2532                    $solutionnum = "5";
2533                  }                  }
2534    
2535            #Setting additional exchange fluxes
2536            if (!defined($additionalexchange) || length($additionalexchange) == 0) {
2537                    if ($self->id() eq "iAF1260") {
2538                            $additionalexchange = "cpd03422[c]:-100:100;cpd01997[c]:-100:100;cpd11416[c]:-100:0;cpd15378[c]:-100:0;cpd15486[c]:-100:0";
2539                    } else {
2540                            $additionalexchange = $self->figmodel()->config("default exchange fluxes")->[0];
2541          }          }
         return $Result;  
2542  }  }
2543    
2544  =head3 classify_model_reactions          #Translating objective
2545  Definition:          my $objectivestring;
2546          (FIGMODELTable:Reaction classes,FIGMODELTable:Compound classes) = FIGMODELmodel->classify_model_reactions(string:media);          if ($objective eq "ALL") {
2547  Description:                  #Getting the list of universal building blocks
2548          This function uses the MFAToolkit to minimize and maximize the flux through every reaction in the input model during minimal growth on the input media.                  my $buildingblocks = $self->config("universal building blocks");
2549          The results are returned in a hash of strings where the keys are the reaction IDs and the strings are structured as follows: "Class;Min flux;Max flux".                  my @objectives = keys(%{$buildingblocks});
2550          Possible values for "Class" include:                  #Getting the nonuniversal building blocks
2551          1.) Positive: these reactions are essential in the forward direction.                  my $otherbuildingblocks = $self->config("nonuniversal building blocks");
2552          2.) Negative: these reactions are essential in the reverse direction.                  my @array = keys(%{$otherbuildingblocks});
2553          3.) Positive variable: these reactions are nonessential, but they only ever proceed in the forward direction.                  if (defined($self->get_biomass()) && defined($self->figmodel()->get_reaction($self->get_biomass()->{"LOAD"}->[0]))) {
2554          4.) Negative variable: these reactions are nonessential, but they only ever proceed in the reverse direction.                          my $equation = $self->figmodel()->get_reaction($self->get_biomass()->{"LOAD"}->[0])->{"EQUATION"}->[0];
2555          5.) Variable: these reactions are nonessential and proceed in the forward or reverse direction.                          if (defined($equation)) {
2556          6.) Blocked: these reactions never carry any flux at all in the media condition tested.                                  for (my $i=0; $i < @array; $i++) {
2557          7.) Dead: these reactions are disconnected from the network.                                          if (CORE::index($equation,$array[$i]) > 0) {
2558  =cut                                                  push(@objectives,$array[$i]);
 sub classify_model_reactions {  
         my ($self,$Media) = @_;  
   
         #Getting unique file for printing model output  
         my $UniqueFilename = $self->figmodel()->filename();  
         #Running the MFAToolkit  
         system($self->figmodel()->GenerateMFAToolkitCommandLineCall($UniqueFilename,$self->id(),$Media,["ProductionMFA"],{"identify dead ends" => 1,"find tight bounds" => 1,"MFASolver" => "GLPK"},"Classify-".$self->id().$self->selected_version()."-".$UniqueFilename.".log",undef,$self->selected_version()));  
         #Reading in the output bounds file  
         my ($ReactionTB,$CompoundTB,$DeadCompounds,$DeadEndCompounds,$DeadReactions);  
         if (-e $self->config("MFAToolkit output directory")->[0].$UniqueFilename."/MFAOutput/TightBoundsReactionData0.txt") {  
                 $ReactionTB = $self->figmodel()->database()->load_table($self->config("MFAToolkit output directory")->[0].$UniqueFilename."/MFAOutput/TightBoundsReactionData0.txt",";","|",1,["DATABASE ID"]);  
         }  
         if (-e $self->config("MFAToolkit output directory")->[0].$UniqueFilename."/MFAOutput/TightBoundsCompoundData0.txt") {  
                 $CompoundTB = $self->figmodel()->database()->load_table($self->config("MFAToolkit output directory")->[0].$UniqueFilename."/MFAOutput/TightBoundsCompoundData0.txt",";","|",1,["DATABASE ID"]);  
2559          }          }
         if (-e $self->config("MFAToolkit output directory")->[0].$UniqueFilename."/DeadReactions.txt") {  
                 $DeadReactions = $self->figmodel()->put_array_in_hash($self->figmodel()->database()->load_single_column_file($self->config("MFAToolkit output directory")->[0].$UniqueFilename."/DeadReactions.txt",""));  
2560          }          }
         if (-e $self->config("MFAToolkit output directory")->[0].$UniqueFilename."/DeadMetabolites.txt") {  
                 $DeadCompounds = $self->figmodel()->put_array_in_hash($self->figmodel()->database()->load_single_column_file($self->config("MFAToolkit output directory")->[0].$UniqueFilename."/DeadMetabolites.txt",""));  
2561          }          }
         if (-e $self->config("MFAToolkit output directory")->[0].$UniqueFilename."/DeadEndMetabolites.txt") {  
                 $DeadEndCompounds = $self->figmodel()->put_array_in_hash($self->figmodel()->database()->load_single_column_file($self->config("MFAToolkit output directory")->[0].$UniqueFilename."/DeadEndMetabolites.txt",""));  
2562          }          }
2563          if (!defined($ReactionTB) && !defined($CompoundTB)) {                  for (my $i=0; $i < @objectives; $i++) {
2564                  print STDERR "FIGMODEL:ClassifyModelReactions: Classification file not found when classifying reactions in ".$self->id().$self->selected_version()." with ".$Media." media. Most likely the model did not grow.\n";                          $self->find_minimal_pathways($media,$objectives[$i]);
2565                  return (undef,undef);                  }
2566                    return;
2567            } elsif ($objective eq "ENERGY") {
2568                    $objectivestring = "MAX;FLUX;rxn00062;c;1";
2569            } elsif ($objective =~ m/cpd\d\d\d\d\d/) {
2570                    if ($objective =~ m/\[(\w)\]/) {
2571                            $objectivestring = "MIN;DRAIN_FLUX;".$objective.";".$1.";1";
2572                            $additionalexchange .= ";".$objective."[".$1."]:-100:0";
2573                    } else {
2574                            $objectivestring = "MIN;DRAIN_FLUX;".$objective.";c;1";
2575                            $additionalexchange .= ";".$objective."[c]:-100:0";
2576                    }
2577            } elsif ($objective =~ m/(rxn\d\d\d\d\d)/) {
2578                    my ($Reactants,$Products) = $self->figmodel()->GetReactionSubstrateData($objective);
2579                    for (my $i=0; $i < @{$Products};$i++) {
2580                            my $temp = $Products->[$i]->{"DATABASE"}->[0];
2581                            if ($additionalexchange !~ m/$temp/) {
2582                                    #$additionalexchange .= ";".$temp."[c]:-100:0";
2583                            }
2584                    }
2585                    for (my $i=0; $i < @{$Reactants};$i++) {
2586                            print $Reactants->[$i]->{"DATABASE"}->[0]." started\n";
2587                            $self->find_minimal_pathways($media,$Reactants->[$i]->{"DATABASE"}->[0],$additionalexchange);
2588                            print $Reactants->[$i]->{"DATABASE"}->[0]." done\n";
2589                    }
2590                    return;
2591            }
2592    
2593            #Adding additional drains
2594            if (($objective eq "cpd15665" || $objective eq "cpd15667" || $objective eq "cpd15668" || $objective eq "cpd15669") && $additionalexchange !~ m/cpd15666/) {
2595                    $additionalexchange .= ";cpd15666[c]:0:100";
2596            } elsif ($objective eq "cpd11493" && $additionalexchange !~ m/cpd12370/) {
2597                    $additionalexchange .= ";cpd12370[c]:0:100";
2598            } elsif ($objective eq "cpd00166" && $additionalexchange !~ m/cpd01997/) {
2599                    $additionalexchange .= ";cpd01997[c]:0:100;cpd03422[c]:0:100";
2600            }
2601    
2602            #Running MFAToolkit
2603            my $filename = $self->figmodel()->filename();
2604            my $command;
2605            if (defined($AllReversible) && $AllReversible == 1) {
2606                    $command = $self->figmodel()->GenerateMFAToolkitCommandLineCall($filename,$self->id(),$media,["ProductionMFA"],{"use simple variable and constraint names"=>1,"Make all reactions reversible in MFA"=>1, "Recursive MILP solution limit" => $solutionnum,"Generate pathways to objective" => 1,"MFASolver" => "SCIP","objective" => $objectivestring,"exchange species" => $additionalexchange},"MinimalPathways-".$media."-".$self->id().$self->selected_version().".txt",undef,$self->selected_version());
2607            } else {
2608                    $command = $self->figmodel()->GenerateMFAToolkitCommandLineCall($filename,$self->id(),$media,["ProductionMFA"],{"use simple variable and constraint names"=>1,"Make all reactions reversible in MFA"=>0, "Recursive MILP solution limit" => $solutionnum,"Generate pathways to objective" => 1,"MFASolver" => "SCIP","objective" => $objectivestring,"exchange species" => $additionalexchange},"MinimalPathways-".$media."-".$self->id().$self->selected_version().".txt",undef,$self->selected_version());
2609            }
2610            print $command."\n";
2611            system($command);
2612    
2613            #Loading problem report
2614            my $results = $self->figmodel()->LoadProblemReport($filename);
2615            #Clearing output
2616            $self->figmodel()->clearing_output($filename,"MinimalPathways-".$media."-".$self->id()."-".$objective.".txt");
2617            if (!defined($results)) {
2618                    print STDERR $objective." pathway results not found!\n";
2619                    return;
2620            }
2621    
2622            #Parsing output
2623            my @Array;
2624            my $row = $results->get_row(1);
2625            if (defined($row->{"Notes"}->[0])) {
2626                    $_ = $row->{"Notes"}->[0];
2627                    @Array = /\d+:([^\|]+)\|/g;
2628            }
2629    
2630            #Writing output to file
2631            $self->figmodel()->database()->print_array_to_file($self->directory()."MinimalPathways-".$media."-".$objective."-".$self->id()."-".$AllReversible."-".$self->selected_version().".txt",[join("|",@Array)]);
2632    }
2633    
2634    sub combine_minimal_pathways {
2635            my ($self) = @_;
2636    
2637            my $tbl;
2638            if (-e $self->directory()."MinimalPathwayTable-".$self->id().$self->selected_version().".tbl") {
2639                    $tbl = FIGMODELTable::load_table($self->directory()."MinimalPathwayTable-".$self->id().$self->selected_version().".tbl",";","|",0,["Objective","Media","Reversible"]);
2640            } else {
2641                    $tbl = FIGMODELTable->new(["Objective","Media","Reactions","Reversible","Shortest path","Number of essentials","Essentials","Length"],$self->directory()."MinimalPathwayTable-".$self->id().$self->selected_version().".tbl",["Objective","Media","Reversible"],";","|");
2642            }
2643            my @files = glob($self->directory()."MinimalPathways-*");
2644            for (my $i=0; $i < @files;$i++) {
2645                    if ($files[$i] =~ m/MinimalPathways\-(\S+)\-(cpd\d\d\d\d\d)\-(\w+)\-(\d)\-/ || $files[$i] =~ m/MinimalPathways\-(\S+)\-(ENERGY)\-(\w+)\-(\d)\-/) {
2646                            my $reactions = $self->figmodel()->database()->load_single_column_file($files[$i],"");
2647                            if (defined($reactions) && @{$reactions} > 0 && length($reactions->[0]) > 0) {
2648                                    my $newrow = {"Objective"=>[$2],"Media"=>[$1],"Reversible"=>[$4]};
2649                                    my $row = $tbl->get_table_by_key($newrow->{"Objective"}->[0],"Objective")->get_table_by_key($newrow->{"Media"}->[0],"Media")->get_row_by_key($newrow->{"Reversible"}->[0],"Reversible");
2650                                    if (!defined($row)) {
2651                                            $row = $tbl->add_row($newrow);
2652                                    }
2653                                    $row->{Reactions} = $self->figmodel()->database()->load_single_column_file($files[$i],"");
2654                                    delete($row->{"Shortest path"});
2655                                    delete($row->{"Number of essentials"});
2656                                    delete($row->{"Essentials"});
2657                                    delete($row->{"Length"});
2658                                    for (my $j=0; $j < @{$row->{Reactions}}; $j++) {
2659                                            my @array = split(/,/,$row->{Reactions}->[$j]);
2660                                            $row->{"Length"}->[$j] = @array;
2661                                            if (!defined($row->{"Shortest path"}->[0]) || $row->{"Length"}->[$j] < $row->{"Shortest path"}->[0]) {
2662                                                    $row->{"Shortest path"}->[0] = $row->{"Length"}->[$j];
2663                                            }
2664                                            $row->{"Number of essentials"}->[0] = 0;
2665                                            for (my $k=0; $k < @array;$k++) {
2666                                                    if ($array[$k] =~ m/(rxn\d\d\d\d\d)/) {
2667                                                            my $class = $self->get_reaction_class($1,1);
2668                                                            my $temp = $row->{Media}->[0].":Essential";
2669                                                            if ($class =~ m/$temp/) {
2670                                                                    $row->{"Number of essentials"}->[$j]++;
2671                                                                    if (!defined($row->{"Essentials"}->[$j]) && length($row->{"Essentials"}->[$j]) > 0) {
2672                                                                            $row->{"Essentials"}->[$j] = $array[$k];
2673                                                                    } else {
2674                                                                            $row->{"Essentials"}->[$j] .= ",".$array[$k];
2675                                                                    }
2676                                                            }
2677                                                    }
2678                                            }
2679                                    }
2680                            }
2681                    }
2682            }
2683            $tbl->save();
2684    }
2685    
2686    =head3 calculate_growth
2687    Definition:
2688            string::growth = FIGMODELmodel->calculate_growth(string:media);
2689    Description:
2690            Calculating growth in the input media
2691    =cut
2692    sub calculate_growth {
2693            my ($self,$Media,$outputDirectory,$InParameters,$saveLPFile) = @_;
2694            #Setting the Media
2695            if (!defined($Media) || length($Media) == 0) {
2696                    $Media = $self->autocompleteMedia();
2697            }
2698            #Setting parameters for the run
2699            my $DefaultParameters = $self->figmodel()->defaultParameters();
2700            if (defined($InParameters)) {
2701                    my @parameters = keys(%{$InParameters});
2702                    for (my $i=0; $i < @parameters; $i++) {
2703                            $DefaultParameters->{$parameters[$i]} = $InParameters->{$parameters[$i]};
2704                    }
2705            }
2706            $DefaultParameters->{"optimize metabolite production if objective is zero"} = 1;
2707            #Setting filenames
2708            my $UniqueFilename = $self->figmodel()->filename();
2709            if (!defined($outputDirectory)) {
2710                    $outputDirectory = $self->config("database message file directory")->[0];
2711            }
2712            my $fluxFilename = $outputDirectory."Fluxes-".$self->id()."-".$Media.".txt";
2713            my $cpdFluxFilename = $outputDirectory."CompoundFluxes-".$self->id()."-".$Media.".txt";
2714            #Running FBA
2715            #print $self->figmodel()->GenerateMFAToolkitCommandLineCall($UniqueFilename,$self->id(),$Media,["ProductionMFA"],$DefaultParameters,$self->id()."-".$Media."-GrowthTest.txt",undef,$self->selected_version())."\n";
2716            system($self->figmodel()->GenerateMFAToolkitCommandLineCall($UniqueFilename,$self->id(),$Media,["ProductionMFA"],$DefaultParameters,$self->id()."-".$Media."-GrowthTest.txt",undef,$self->selected_version()));
2717            #Saving LP file if requested
2718            if (defined($saveLPFile) && $saveLPFile == 1 && -e $self->figmodel()->{"MFAToolkit output directory"}->[0].$UniqueFilename."/CurrentProblem.lp") {
2719                    system("cp ".$self->figmodel()->config("MFAToolkit output directory")->[0].$UniqueFilename."/CurrentProblem.lp ".$self->directory().$self->id().".lp");
2720            }
2721            my $ProblemReport = $self->figmodel()->LoadProblemReport($UniqueFilename);
2722            my $Result;
2723            if (defined($ProblemReport)) {
2724                    my $Row = $ProblemReport->get_row(0);
2725                    if (defined($Row) && defined($Row->{"Objective"}->[0])) {
2726                            if ($Row->{"Objective"}->[0] < 0.00000001 || $Row->{"Objective"}->[0] == 1e7) {
2727                                    $Result = "NOGROWTH";
2728                                    if (defined($Row->{"Individual metabolites with zero production"}->[0]) && $Row->{"Individual metabolites with zero production"}->[0] =~ m/cpd\d\d\d\d\d/) {
2729                                            $Result .= ":".$Row->{"Individual metabolites with zero production"}->[0];
2730                                    }
2731                            } else {
2732                                    if (-e $self->figmodel()->config("MFAToolkit output directory")->[0].$UniqueFilename."/MFAOutput/SolutionReactionData0.txt") {
2733                                            system("cp ".$self->figmodel()->config("MFAToolkit output directory")->[0].$UniqueFilename."/MFAOutput/SolutionReactionData0.txt ".$fluxFilename);
2734                                            system("cp ".$self->figmodel()->config("MFAToolkit output directory")->[0].$UniqueFilename."/MFAOutput/SolutionCompoundData0.txt ".$cpdFluxFilename);
2735                                    }
2736                                    $Result = $Row->{"Objective"}->[0];
2737                            }
2738                    }
2739            }
2740            #Deleting files if necessary
2741            if ($self->figmodel()->config("preserve all log files")->[0] ne "yes") {
2742                    $self->figmodel()->cleardirectory($UniqueFilename);
2743                    unlink($self->figmodel()->config("database message file directory")->[0].$self->id()."-".$Media."-GrowthTest.txt");
2744            }
2745            #Returning result
2746            return $Result;
2747    }
2748    
2749    =head3 classify_model_reactions
2750    Definition:
2751            (FIGMODELTable:Reaction classes,FIGMODELTable:Compound classes) = FIGMODELmodel->classify_model_reactions(string:media);
2752    Description:
2753            This function uses the MFAToolkit to minimize and maximize the flux through every reaction in the input model during minimal growth on the input media.
2754            The results are returned in a hash of strings where the keys are the reaction IDs and the strings are structured as follows: "Class;Min flux;Max flux".
2755            Possible values for "Class" include:
2756            1.) Positive: these reactions are essential in the forward direction.
2757            2.) Negative: these reactions are essential in the reverse direction.
2758            3.) Positive variable: these reactions are nonessential, but they only ever proceed in the forward direction.
2759            4.) Negative variable: these reactions are nonessential, but they only ever proceed in the reverse direction.
2760            5.) Variable: these reactions are nonessential and proceed in the forward or reverse direction.
2761            6.) Blocked: these reactions never carry any flux at all in the media condition tested.
2762            7.) Dead: these reactions are disconnected from the network.
2763    =cut
2764    sub classify_model_reactions {
2765            my ($self,$Media,$SaveChanges) = @_;
2766    
2767            #Getting unique file for printing model output
2768            my $UniqueFilename = $self->figmodel()->filename();
2769            #Running the MFAToolkit
2770            system($self->figmodel()->GenerateMFAToolkitCommandLineCall($UniqueFilename,$self->id(),$Media,["ProductionMFA"],{"identify dead ends" => 1,"find tight bounds" => 1,"MFASolver" => "GLPK"},"Classify-".$self->id().$self->selected_version()."-".$UniqueFilename.".log",undef,$self->selected_version()));
2771            #Reading in the output bounds file
2772            my ($ReactionTB,$CompoundTB,$DeadCompounds,$DeadEndCompounds,$DeadReactions);
2773            if (-e $self->config("MFAToolkit output directory")->[0].$UniqueFilename."/MFAOutput/TightBoundsReactionData0.txt") {
2774                    $ReactionTB = $self->figmodel()->database()->load_table($self->config("MFAToolkit output directory")->[0].$UniqueFilename."/MFAOutput/TightBoundsReactionData0.txt",";","|",1,["DATABASE ID"]);
2775            }
2776            if (-e $self->config("MFAToolkit output directory")->[0].$UniqueFilename."/MFAOutput/TightBoundsCompoundData0.txt") {
2777                    $CompoundTB = $self->figmodel()->database()->load_table($self->config("MFAToolkit output directory")->[0].$UniqueFilename."/MFAOutput/TightBoundsCompoundData0.txt",";","|",1,["DATABASE ID"]);
2778            }
2779            if (-e $self->config("MFAToolkit output directory")->[0].$UniqueFilename."/DeadReactions.txt") {
2780                    $DeadReactions = $self->figmodel()->put_array_in_hash($self->figmodel()->database()->load_single_column_file($self->config("MFAToolkit output directory")->[0].$UniqueFilename."/DeadReactions.txt",""));
2781            }
2782            if (-e $self->config("MFAToolkit output directory")->[0].$UniqueFilename."/DeadMetabolites.txt") {
2783                    $DeadCompounds = $self->figmodel()->put_array_in_hash($self->figmodel()->database()->load_single_column_file($self->config("MFAToolkit output directory")->[0].$UniqueFilename."/DeadMetabolites.txt",""));
2784            }
2785            if (-e $self->config("MFAToolkit output directory")->[0].$UniqueFilename."/DeadEndMetabolites.txt") {
2786                    $DeadEndCompounds = $self->figmodel()->put_array_in_hash($self->figmodel()->database()->load_single_column_file($self->config("MFAToolkit output directory")->[0].$UniqueFilename."/DeadEndMetabolites.txt",""));
2787            }
2788            if (!defined($ReactionTB) && !defined($CompoundTB)) {
2789                    print STDERR "FIGMODEL:ClassifyModelReactions: Classification file not found when classifying reactions in ".$self->id().$self->selected_version()." with ".$Media." media. Most likely the model did not grow.\n";
2790                    return (undef,undef);
2791          }          }
2792    
2793          #Clearing output          #Clearing output
# Line 2123  Line 2849 
2849                                  $CpdRow->{MEDIA}->[$index] = $Media;                                  $CpdRow->{MEDIA}->[$index] = $Media;
2850                          }                          }
2851                  }                  }
2852                    if (!defined($SaveChanges) || $SaveChanges == 1) {
2853                  $cpdclasstable->save();                  $cpdclasstable->save();
2854          }          }
2855            }
2856          if (defined($ReactionTB)) {          if (defined($ReactionTB)) {
2857                  for (my $i=0; $i < $ReactionTB->size(); $i++) {                  for (my $i=0; $i < $ReactionTB->size(); $i++) {
2858                          my $Row = $ReactionTB->get_row($i);                          my $Row = $ReactionTB->get_row($i);
# Line 2179  Line 2907 
2907                                  $RxnRow->{MEDIA}->[$index] = $Media;                                  $RxnRow->{MEDIA}->[$index] = $Media;
2908                          }                          }
2909                  }                  }
2910                    if (!defined($SaveChanges) || $SaveChanges == 1) {
2911                  $rxnclasstable->save();                  $rxnclasstable->save();
2912          }          }
2913            }
2914          return ($rxnclasstable,$cpdclasstable);          return ($rxnclasstable,$cpdclasstable);
2915  }  }
2916    
# Line 2212  Line 2942 
2942    
2943          #Running simulations          #Running simulations
2944          system($self->config("mfalite executable")->[0]." ".$self->config("Reaction database directory")->[0]."masterfiles/MediaTable.txt ".$self->config("MFAToolkit output directory")->[0].$UniqueFilename."/Jobfile.txt ".$self->config("MFAToolkit output directory")->[0].$UniqueFilename."/Output.txt");          system($self->config("mfalite executable")->[0]." ".$self->config("Reaction database directory")->[0]."masterfiles/MediaTable.txt ".$self->config("MFAToolkit output directory")->[0].$UniqueFilename."/Jobfile.txt ".$self->config("MFAToolkit output directory")->[0].$UniqueFilename."/Output.txt");
         print "simulation complete for ".$self->id().$self->selected_version()."\n";  
2945          #Parsing the results          #Parsing the results
2946          my $Results = $self->figmodel()->database()->load_table($self->config("MFAToolkit output directory")->[0].$UniqueFilename."/Output.txt",";","\\|",0,undef);          my $Results = $self->figmodel()->database()->load_table($self->config("MFAToolkit output directory")->[0].$UniqueFilename."/Output.txt",";","\\|",0,undef);
2947          if (!defined($Results)) {          if (!defined($Results)) {
# Line 2619  Line 3348 
3348                                          if (length($GapFillingRunSpecs) > 0) {                                          if (length($GapFillingRunSpecs) > 0) {
3349                                                  $GapFillingRunSpecs .= ";";                                                  $GapFillingRunSpecs .= ";";
3350                                          }                                          }
3351                                          $GapFillingRunSpecs .= $HeadingDataArray[2].":".$HeadingDataArray[1].".txt:".$HeadingDataArray[3];                                          $GapFillingRunSpecs .= $HeadingDataArray[2].":".$HeadingDataArray[1].":".$HeadingDataArray[3];
3352                                  } else {                                  } else {
3353                                          $SolutionExistedCount++;                                          $SolutionExistedCount++;
3354                                  }                                  }
# Line 2644  Line 3373 
3373          my $SolutionsFound = 0;          my $SolutionsFound = 0;
3374          my $GapFillingArray;          my $GapFillingArray;
3375          push(@{$GapFillingArray},split(/;/,$GapFillingRunSpecs));          push(@{$GapFillingArray},split(/;/,$GapFillingRunSpecs));
3376          $self->datagapfill($GapFillingArray);          my $GapFillingResults = $self->datagapfill($GapFillingArray,"GFS");
3377            if (defined($GapFillingResults)) {
3378                    $SolutionsFound = 1;
3379            }
3380    
3381          if (defined($RescuedPreviousResults) && @{$RescuedPreviousResults} > 0) {          if (defined($RescuedPreviousResults) && @{$RescuedPreviousResults} > 0) {
3382                  #Printing previous solutions to GFS file                  #Printing previous solutions to GFS file
# Line 2667  Line 3399 
3399          return $self->success();          return $self->success();
3400  }  }
3401    
3402    =head3 SolutionReconciliation
3403    Definition:
3404            FIGMODELmodel->SolutionReconciliation();
3405    Description:
3406            This is a wrapper for running the solution reconciliation algorithm on any model in the database.
3407            The algorithm performs a reconciliation of any gap filling solutions to identify the combination of solutions that results in the optimal model.
3408            This function prints out one output file in the Model directory: ReconciliationOutput.txt: this is a summary of the results of the reconciliation analysis
3409    =cut
3410    
3411    sub SolutionReconciliation {
3412            my ($self,$GapFill,$Stage) = @_;
3413    
3414            #Setting the output filenames
3415            my $OutputFilename;
3416            my $OutputFilenameTwo;
3417            if ($GapFill == 1) {
3418                    $OutputFilename = $self->directory().$self->id().$self->selected_version()."-GFReconciliation.txt";
3419                    $OutputFilenameTwo = $self->directory().$self->id().$self->selected_version()."-GFSRS.txt";
3420            } else {
3421                    $OutputFilename = $self->directory().$self->id().$self->selected_version()."-GGReconciliation.txt";
3422                    $OutputFilenameTwo = $self->directory().$self->id().$self->selected_version()."-GGSRS.txt";
3423            }
3424    
3425            #In stage one, we run the reconciliation and create a test file to check combined solution performance
3426            if (!defined($Stage) || $Stage == 1) {
3427                    my $GrowMatchTable = $self->figmodel()->database()->LockDBTable("GROWMATCH TABLE");
3428                    my $Row = $GrowMatchTable->get_row_by_key($self->genome(),"ORGANISM",1);
3429                    $Row->{"GF RECONCILATION TIMING"}->[0] = time()."-";
3430                    $GrowMatchTable->save();
3431                    $self->figmodel()->database()->UnlockDBTable("GROWMATCH TABLE");
3432    
3433                    #Getting a unique filename
3434                    my $UniqueFilename = $self->figmodel()->filename();
3435    
3436                    #Copying over the necessary files
3437                    if ($GapFill == 1) {
3438                            if (!-e $self->directory().$self->id().$self->selected_version()."-GFEM.txt") {
3439                                    print STDERR "FIGMODEL:SolutionReconciliation:".$self->directory().$self->id().$self->selected_version()."-GFEM.txt file not found. Could not reconcile!";
3440                                    return 0;
3441                            }
3442                            if (!-e $self->directory().$self->id().$self->selected_version()."-OPEM.txt") {
3443                                    print STDERR "FIGMODEL:SolutionReconciliation:".$self->directory().$self->id().$self->selected_version()."-OPEM.txt file not found. Could not reconcile!";
3444                                    return 0;
3445                            }
3446                            system("cp ".$self->directory().$self->id().$self->selected_version()."-GFEM.txt ".$self->figmodel()->config("MFAToolkit input files")->[0].$UniqueFilename."-GFEM.txt");
3447                            system("cp ".$self->directory().$self->id().$self->selected_version()."-OPEM.txt ".$self->figmodel()->config("MFAToolkit input files")->[0].$UniqueFilename."-OPEM.txt");
3448                            #Backing up and deleting the existing reconciliation file
3449                            if (-e $OutputFilename) {
3450                                    system("cp ".$OutputFilename." ".$self->directory().$self->id().$self->selected_version()."-OldGFReconciliation.txt");
3451                                    unlink($OutputFilename);
3452                            }
3453                    } else {
3454                            if (!-e $self->directory().$self->id().$self->selected_version()."-GGEM.txt") {
3455                                    print STDERR "FIGMODEL:SolutionReconciliation:".$self->directory().$self->id().$self->selected_version()."-GGEM.txt file not found. Could not reconcile!";
3456                                    return 0;
3457                            }
3458                            if (!-e $self->directory().$self->id().$self->selected_version()."-GGOPEM.txt") {
3459                                    print STDERR "FIGMODEL:SolutionReconciliation:".$self->directory().$self->id().$self->selected_version()."-GGOPEM.txt file not found. Could not reconcile!";
3460                                    return 0;
3461                            }
3462                            system("cp ".$self->directory().$self->id().$self->selected_version()."-GGEM.txt ".$self->figmodel()->config("MFAToolkit input files")->[0].$UniqueFilename."-GGEM.txt");
3463                            system("cp ".$self->directory().$self->id().$self->selected_version()."-GGOPEM.txt ".$self->figmodel()->config("MFAToolkit input files")->[0].$UniqueFilename."-OPEM.txt");
3464                            #Backing up and deleting the existing reconciliation file
3465                            if (-e $OutputFilename) {
3466                                    system("cp ".$OutputFilename." ".$self->directory().$self->id().$self->selected_version()."-OldGGReconciliation.txt");
3467                                    unlink($OutputFilename);
3468                            }
3469                    }
3470    
3471                    #Running the reconciliation
3472                    system($self->figmodel()->GenerateMFAToolkitCommandLineCall($UniqueFilename,$self->id(),"NONE",["SolutionReconciliation"],{"Solution data for model optimization" => $UniqueFilename},"Reconciliation".$UniqueFilename.".log",undef,$self->selected_version()));
3473                    $GrowMatchTable = $self->figmodel()->database()->LockDBTable("GROWMATCH TABLE");
3474                    $Row = $GrowMatchTable->get_row_by_key($self->genome(),"ORGANISM",1);
3475                    $Row->{"GF RECONCILATION TIMING"}->[0] .= time();
3476                    $GrowMatchTable->save();
3477                    $self->figmodel()->database()->UnlockDBTable("GROWMATCH TABLE");
3478    
3479                    #Loading the problem report from the reconciliation run
3480                    my $ReconciliatonOutput = $self->figmodel()->LoadProblemReport($UniqueFilename);
3481                    print $UniqueFilename."\n";
3482                    #Clearing output files
3483                    $self->figmodel()->clearing_output($UniqueFilename,"Reconciliation".$UniqueFilename.".log");
3484                    $ReconciliatonOutput->save("/home/chenry/Test.txt");
3485    
3486                    #Checking the a problem report was found and was loaded
3487                    if (!defined($ReconciliatonOutput) || $ReconciliatonOutput->size() < 1 || !defined($ReconciliatonOutput->get_row(0)->{"Notes"}->[0])) {
3488                            print STDERR "FIGMODEL:SolutionReconciliation: MFAToolkit output from SolutionReconciliation of ".$self->id()." not found!\n\n";
3489                            return 0;
3490                    }
3491    
3492                    #Processing the solutions
3493                    my $SolutionCount = 0;
3494                    my $ReactionSetHash;
3495                    my $SingleReactionHash;
3496                    my $ReactionDataHash;
3497                    for (my $n=0; $n < $ReconciliatonOutput->size(); $n++) {
3498                            if (defined($ReconciliatonOutput->get_row($n)->{"Notes"}->[0]) && $ReconciliatonOutput->get_row($n)->{"Notes"}->[0] =~ m/^Recursive\sMILP\s([^;]+)/) {
3499                                    #Breaking up the solution into reaction sets
3500                                    my @ReactionSets = split(/\|/,$1);
3501                                    #Creating reaction lists for each set
3502                                    my $SolutionHash;
3503                                    for (my $i=0; $i < @ReactionSets; $i++) {
3504                                            if (length($ReactionSets[$i]) > 0) {
3505                                                    my @Alternatives = split(/:/,$ReactionSets[$i]);
3506                                                    for (my $j=1; $j < @Alternatives; $j++) {
3507                                                            if (length($Alternatives[$j]) > 0) {
3508                                                                    push(@{$SolutionHash->{$Alternatives[$j]}},$Alternatives[0]);
3509                                                            }
3510                                                    }
3511                                                    if (@Alternatives == 1) {
3512                                                            $SingleReactionHash->{$Alternatives[0]}->{$SolutionCount} = 1;
3513                                                            if (!defined($SingleReactionHash->{$Alternatives[0]}->{"COUNT"})) {
3514                                                                    $SingleReactionHash->{$Alternatives[0]}->{"COUNT"} = 0;
3515                                                            }
3516                                                            $SingleReactionHash->{$Alternatives[0]}->{"COUNT"}++;
3517                                                    }
3518                                            }
3519                                    }
3520                                    #Identifying reactions sets and storing the sets in the reactions set hash
3521                                    foreach my $Solution (keys(%{$SolutionHash})) {
3522                                            my $SetKey = join(",",sort(@{$SolutionHash->{$Solution}}));
3523                                            if (!defined($ReactionSetHash->{$SetKey}->{$SetKey}->{$SolutionCount})) {
3524                                                    $ReactionSetHash->{$SetKey}->{$SetKey}->{$SolutionCount} = 1;
3525                                                    if (!defined($ReactionSetHash->{$SetKey}->{$SetKey}->{"COUNT"})) {
3526                                                            $ReactionSetHash->{$SetKey}->{$SetKey}->{"COUNT"} = 0;
3527                                                    }
3528                                                    $ReactionSetHash->{$SetKey}->{$SetKey}->{"COUNT"}++;
3529                                            }
3530                                            $ReactionSetHash->{$SetKey}->{$Solution}->{$SolutionCount} = 1;
3531                                            if (!defined($ReactionSetHash->{$SetKey}->{$Solution}->{"COUNT"})) {
3532                                                    $ReactionSetHash->{$SetKey}->{$Solution}->{"COUNT"} = 0;
3533                                            }
3534                                            $ReactionSetHash->{$SetKey}->{$Solution}->{"COUNT"}++;
3535                                    }
3536                                    $SolutionCount++;
3537                            }
3538                    }
3539    
3540                    #Handling the scenario where no solutions were found
3541                    if ($SolutionCount == 0) {
3542                            print STDERR "FIGMODEL:SolutionReconciliation: Reconciliation unsuccessful. No solution found.\n\n";
3543                            return 0;
3544                    }
3545    
3546                    #Printing results without solution performance figures. Also printing solution test file
3547                    open (RECONCILIATION, ">$OutputFilename");
3548                    #Printing the file heading
3549                    print RECONCILIATION "DATABASE;DEFINITION;REVERSIBLITY;DELTAG;DIRECTION;NUMBER OF SOLUTIONS";
3550                    for (my $i=0; $i < $SolutionCount; $i++) {
3551                            print RECONCILIATION ";Solution ".$i;
3552                    }
3553                    print RECONCILIATION "\n";
3554                    #Printing the singlet reactions first
3555                    my $Solutions;
3556                    print RECONCILIATION "SINGLET REACTIONS\n";
3557                    my @SingletReactions = keys(%{$SingleReactionHash});
3558                    for (my $j=0; $j < $SolutionCount; $j++) {
3559                            $Solutions->[$j]->{"BASE"} = $j;
3560                    }
3561                    for (my $i=0; $i < @SingletReactions; $i++) {
3562                            my $ReactionData;
3563                            if (defined($ReactionDataHash->{$SingletReactions[$i]})) {
3564                                    $ReactionData = $ReactionDataHash->{$SingletReactions[$i]};
3565                            } else {
3566                                    my $Direction = substr($SingletReactions[$i],0,1);
3567                                    if ($Direction eq "+") {
3568                                            $Direction = "=>";
3569                                    } else {
3570                                            $Direction = "<=";
3571                                    }
3572                                    my $Reaction = substr($SingletReactions[$i],1);
3573                                    $ReactionData = FIGMODELObject->load($self->figmodel()->config("reaction directory")->[0].$Reaction,"\t");
3574                                    $ReactionData->{"DIRECTIONS"}->[0] = $Direction;
3575                                    $ReactionData->{"REACTIONS"}->[0] = $Reaction;
3576                                    if (!defined($ReactionData->{"DEFINITION"}->[0])) {
3577                                            $ReactionData->{"DEFINITION"}->[0] = "UNKNOWN";
3578                                    }
3579                                    if (!defined($ReactionData->{"THERMODYNAMIC REVERSIBILITY"}->[0])) {
3580                                            $ReactionData->{"THERMODYNAMIC REVERSIBILITY"}->[0] = "UNKNOWN";
3581                                    }
3582                                    if (!defined($ReactionData->{"DELTAG"}->[0])) {
3583                                            $ReactionData->{"DELTAG"}->[0] = "UNKNOWN";
3584                                    }
3585                                    $ReactionDataHash->{$SingletReactions[$i]} = $ReactionData;
3586                            }
3587                            print RECONCILIATION $ReactionData->{"REACTIONS"}->[0].";".$ReactionData->{"DEFINITION"}->[0].";".$ReactionData->{"THERMODYNAMIC REVERSIBILITY"}->[0].";".$ReactionData->{"DELTAG"}->[0].";".$ReactionData->{"DIRECTIONS"}->[0].";".$SingleReactionHash->{$SingletReactions[$i]}->{"COUNT"};
3588                            for (my $j=0; $j < $SolutionCount; $j++) {
3589                                    print RECONCILIATION ";";
3590                                    if (defined($SingleReactionHash->{$SingletReactions[$i]}->{$j})) {
3591                                            $Solutions->[$j]->{$SingletReactions[$i]} = 1;
3592                                            $Solutions->[$j]->{"BASE"} = $j;
3593                                            print RECONCILIATION "|".$j."|";
3594                                    }
3595                            }
3596                            print RECONCILIATION "\n";
3597                    }
3598                    #Printing the reaction sets with alternatives
3599                    print RECONCILIATION "Reaction sets with alternatives\n";
3600                    my @ReactionSets = keys(%{$ReactionSetHash});
3601                    foreach my $ReactionSet (@ReactionSets) {
3602                            my $NewSolutions;
3603                            my $BaseReactions;
3604                            my $AltList = [$ReactionSet];
3605                            push(@{$AltList},keys(%{$ReactionSetHash->{$ReactionSet}}));
3606                            for (my $j=0; $j < @{$AltList}; $j++) {
3607                                    my $CurrentNewSolutions;
3608                                    my $Index;
3609                                    if ($j == 0) {
3610                                            print RECONCILIATION "NEW SET\n";
3611                                    } elsif ($AltList->[$j] ne $ReactionSet) {
3612                                            print RECONCILIATION "ALTERNATIVE SET\n";
3613                                            #For each base solution in which this set is represented, we copy the base solution to the new solution
3614                                            my $NewSolutionCount = 0;
3615                                            for (my $k=0; $k < $SolutionCount; $k++) {
3616                                                    if (defined($ReactionSetHash->{$ReactionSet}->{$AltList->[$j]}->{$k})) {
3617                                                            if (defined($Solutions)) {
3618                                                                    $Index->{$k} = @{$Solutions} + $NewSolutionCount;
3619                                                            } else {
3620                                                                    $Index->{$k} = $NewSolutionCount;
3621                                                            }
3622                                                            if (defined($NewSolutions) && @{$NewSolutions} > 0) {
3623                                                                    $Index->{$k} += @{$NewSolutions};
3624                                                            }
3625                                                            $CurrentNewSolutions->[$NewSolutionCount] = {};
3626                                                            foreach my $Reaction (keys(%{$Solutions->[$k]})) {
3627                                                                    $CurrentNewSolutions->[$NewSolutionCount]->{$Reaction} = $Solutions->[$k]->{$Reaction};
3628                                                            }
3629                                                            $NewSolutionCount++;
3630                                                    }
3631                                            }
3632                                    }
3633                                    if ($j == 0 || $AltList->[$j] ne $ReactionSet) {
3634                                            my @SingletReactions = split(/,/,$AltList->[$j]);
3635                                            for (my $i=0; $i < @SingletReactions; $i++) {
3636                                                    #Adding base reactions to base solutions and set reactions the new solutions
3637                                                    if ($j == 0) {
3638                                                            push(@{$BaseReactions},$SingletReactions[$i]);
3639                                                    } else {
3640                                                            for (my $k=0; $k < @{$CurrentNewSolutions}; $k++) {
3641                                                                    $CurrentNewSolutions->[$k]->{$SingletReactions[$i]} = 1;
3642                                                            }
3643                                                    }
3644                                                    #Getting reaction data and printing reaction in output file
3645                                                    my $ReactionData;
3646                                                    if (defined($ReactionDataHash->{$SingletReactions[$i]})) {
3647                                                            $ReactionData = $ReactionDataHash->{$SingletReactions[$i]};
3648                                                    } else {
3649                                                            my $Direction = substr($SingletReactions[$i],0,1);
3650                                                            if ($Direction eq "+") {
3651                                                                    $Direction = "=>";
3652                                                            } else {
3653                                                                    $Direction = "<=";
3654                                                            }
3655                                                            my $Reaction = substr($SingletReactions[$i],1);
3656                                                            $ReactionData = FIGMODELObject->load($self->figmodel()->config("reaction directory")->[0].$Reaction,"\t");
3657                                                            $ReactionData->{"DIRECTIONS"}->[0] = $Direction;
3658                                                            $ReactionData->{"REACTIONS"}->[0] = $Reaction;
3659                                                            if (!defined($ReactionData->{"DEFINITION"}->[0])) {
3660                                                                    $ReactionData->{"DEFINITION"}->[0] = "UNKNOWN";
3661                                                            }
3662                                                            if (!defined($ReactionData->{"THERMODYNAMIC REVERSIBILITY"}->[0])) {
3663                                                                    $ReactionData->{"THERMODYNAMIC REVERSIBILITY"}->[0] = "UNKNOWN";
3664                                                            }
3665                                                            if (!defined($ReactionData->{"DELTAG"}->[0])) {
3666                                                                    $ReactionData->{"DELTAG"}->[0] = "UNKNOWN";
3667                                                            }
3668                                                            $ReactionDataHash->{$SingletReactions[$i]} = $ReactionData;
3669                                                    }
3670                                                    print RECONCILIATION $ReactionData->{"REACTIONS"}->[0].";".$ReactionData->{"DEFINITION"}->[0].";".$ReactionData->{"THERMODYNAMIC REVERSIBILITY"}->[0].";".$ReactionData->{"DELTAG"}->[0].";".$ReactionData->{"DIRECTIONS"}->[0].";".$ReactionSetHash->{$ReactionSet}->{$AltList->[$j]}->{"COUNT"};
3671                                                    for (my $k=0; $k < $SolutionCount; $k++) {
3672                                                            print RECONCILIATION ";";
3673                                                            if (defined($ReactionSetHash->{$ReactionSet}->{$AltList->[$j]}->{$k})) {
3674                                                                    if ($j == 0) {
3675                                                                            print RECONCILIATION "|".$k."|";
3676                                                                    } else {
3677                                                                            print RECONCILIATION "|".$Index->{$k}."|";
3678                                                                    }
3679                                                            }
3680                                                    }
3681                                                    print RECONCILIATION "\n";
3682                                            }
3683                                            #Adding the current new solutions to the new solutions array
3684                                            if (defined($CurrentNewSolutions) && @{$CurrentNewSolutions} > 0) {
3685                                                    push(@{$NewSolutions},@{$CurrentNewSolutions});
3686                                            }
3687                                    }
3688                            }
3689                            #Adding the base reactions to all existing solutions
3690                            for (my $j=0; $j < @{$Solutions}; $j++) {
3691                                    if (defined($ReactionSetHash->{$ReactionSet}->{$ReactionSet}->{$Solutions->[$j]->{"BASE"}})) {
3692                                            foreach my $SingleReaction (@{$BaseReactions}) {
3693                                                    $Solutions->[$j]->{$SingleReaction} = 1;
3694                                            }
3695                                    }
3696                            }
3697                            #Adding the new solutions to the set of existing solutions
3698                            push(@{$Solutions},@{$NewSolutions});
3699                    }
3700                    close(RECONCILIATION);
3701                    #Now printing a file that defines all of the solutions in a format the testsolutions function understands
3702                    open (RECONCILIATION, ">$OutputFilenameTwo");
3703                    print RECONCILIATION "Experiment;Solution index;Solution cost;Solution reactions\n";
3704                    for (my $i=0; $i < @{$Solutions}; $i++) {
3705                            delete($Solutions->[$i]->{"BASE"});
3706                            print RECONCILIATION "SR".$i.";".$i.";10;".join(",",keys(%{$Solutions->[$i]}))."\n";
3707                    }
3708                    close(RECONCILIATION);
3709    
3710                    $GrowMatchTable = $self->figmodel()->database()->LockDBTable("GROWMATCH TABLE");
3711                    $Row = $GrowMatchTable->get_row_by_key($self->genome(),"ORGANISM",1);
3712                    $Row->{"GF RECON TESTING TIMING"}->[0] = time()."-";
3713                    $Row->{"GF RECON SOLUTIONS"}->[0] = @{$Solutions};
3714                    $GrowMatchTable->save();
3715                    $self->figmodel()->database()->UnlockDBTable("GROWMATCH TABLE");
3716    
3717                    #Scheduling the solution testing
3718                    if ($GapFill == 1) {
3719                            system($self->figmodel()->config("scheduler executable")->[0]." \"add:testsolutions?".$self->id().$self->selected_version()."?-1?GFSR:BACK:fast:QSUB\"");
3720                    } else {
3721                            system($self->figmodel()->config("scheduler executable")->[0]." \"add:testsolutions?".$self->id().$self->selected_version()."?-1?GGSR:BACK:fast:QSUB\"");
3722                    }
3723            } else {
3724                    #Reading in the solution testing results
3725                    my $Data;
3726                    if ($GapFill == 1) {
3727                            $Data = $self->figmodel()->database()->load_single_column_file($self->directory().$self->id().$self->selected_version()."-GFSREM.txt","");
3728                    } else {
3729                            $Data = $self->figmodel()->database()->load_single_column_file($self->directory().$self->id().$self->selected_version()."-GGSREM.txt","");
3730                    }
3731    
3732                    #Reading in the preliminate reconciliation report
3733                    my $OutputData = $self->figmodel()->database()->load_single_column_file($OutputFilename,"");
3734                    #Replacing the file tags with actual performance data
3735                    my $Count = 0;
3736                    for (my $i=0; $i < @{$Data}; $i++) {
3737                            if ($Data->[$i] =~ m/^SR(\d+);.+;(\d+\/\d+);/) {
3738                                    my $Index = $1;
3739                                    my $Performance = $Index."/".$2;
3740                                    for (my $j=0; $j < @{$OutputData}; $j++) {
3741                                            $OutputData->[$j] =~ s/\|$Index\|/$Performance/g;
3742                                    }
3743                            }
3744                    }
3745                    $self->figmodel()->database()->print_array_to_file($OutputFilename,$OutputData);
3746    
3747                    my $GrowMatchTable = $self->figmodel()->database()->LockDBTable("GROWMATCH TABLE");
3748                    my $Row = $GrowMatchTable->get_row_by_key($self->genome(),"ORGANISM",1);
3749                    $Row->{"GF RECON TESTING TIMING"}->[0] .= time();
3750                    $GrowMatchTable->save();
3751                    $self->figmodel()->database()->UnlockDBTable("GROWMATCH TABLE");
3752            }
3753    
3754            return 1;
3755    }
3756    
3757  =head3 BuildSpecificBiomassReaction  =head3 BuildSpecificBiomassReaction
3758  Definition:  Definition:
3759          FIGMODELmodel->BuildSpecificBiomassReaction();          FIGMODELmodel->BuildSpecificBiomassReaction();
# Line 2679  Line 3766 
3766          my $OrganismID = $self->genome();          my $OrganismID = $self->genome();
3767          #Checking for a biomass override          #Checking for a biomass override
3768          if (defined($self->config("biomass reaction override")->{$OrganismID})) {          if (defined($self->config("biomass reaction override")->{$OrganismID})) {
3769                  $biomassrxn = $self->config("biomass reaction override")->{$OrganismID};                  my $biomassID = $self->config("biomass reaction override")->{$OrganismID};
3770                  print "Overriding biomass template and selecting ".$biomassrxn." for ".$OrganismID.".\n";                  my $tbl = $self->database()->get_table("BIOMASS",1);
3771                    $biomassrxn = $tbl->get_row_by_key($biomassID,"DATABASE");
3772                    print "Overriding biomass template and selecting ".$biomassID." for ".$OrganismID.".\n";
3773          } else {#Creating biomass reaction from the template          } else {#Creating biomass reaction from the template
3774                  #Getting the genome stats                  #Getting the genome stats
3775                  my $genomestats = $self->figmodel()->get_genome_stats($self->genome());                  my $genomestats = $self->figmodel()->get_genome_stats($self->genome());
# Line 2971  Line 4060 
4060    
4061                  #Adding the biomass equation to the biomass table                  #Adding the biomass equation to the biomass table
4062                  my $NewRow = $self->figmodel()->add_biomass_reaction($Equation,$self->id(),"Template:".$self->genome());                  my $NewRow = $self->figmodel()->add_biomass_reaction($Equation,$self->id(),"Template:".$self->genome());
4063                  $biomassrxn = $NewRow->{DATABASE}->[0];                  $biomassrxn = $NewRow;
                 print $biomassrxn."\n";  
4064          }          }
4065          print $biomassrxn."\n";          return $biomassrxn;
         my $BiomassRow = $self->figmodel()->add_model_to_biomass_reaction($biomassrxn,$self->id());  
         return $BiomassRow;  
4066  }  }
4067    
4068  =head3 PrintSBMLFile  =head3 PrintSBMLFile
# Line 2989  Line 4075 
4075          my($self) = @_;          my($self) = @_;
4076    
4077          #Opening the SBML file for printing          #Opening the SBML file for printing
4078          my $Filename = $self->config("SBML files")->[0].$self->id().".xml";          my $Filename = $self->directory().$self->id().".xml";
         if ($self->owner() ne "master") {  
                 if (!-d $self->config("SBML files")->[0].$self->owner()."/") {  
                         system("mkdir ".$self->config("SBML files")->[0].$self->owner()."/");  
                 }  
                 $Filename = $self->config("SBML files")->[0].$self->owner()."/".$self->id().".xml";  
         }  
4079          if (!open (SBMLOUTPUT, ">$Filename")) {          if (!open (SBMLOUTPUT, ">$Filename")) {
4080                  return;                  return;
4081          }          }
4082    
4083          #Loading and parsing the model data          #Loading and parsing the model data
4084          my $ModelTable = $self->reaction_table();          my $mdlTbl = $self->reaction_table();
4085          if (!defined($ModelTable) || !defined($ModelTable->{"array"})) {          if (!defined($mdlTbl) || !defined($mdlTbl->{"array"})) {
4086                  print "Failed to load ".$self->id()."\n";                  return $self->fail();
                 return;  
4087          }          }
4088            my $rxnTbl = $self->figmodel()->database()->get_table("REACTIONS");
4089            my $bioTbl = $self->figmodel()->database()->get_table("BIOMASS");
4090            my $cpdTbl = $self->figmodel()->database()->get_table("COMPOUNDS");
4091            my $cmpTbl = $self->figmodel()->database()->get_table("COMPARTMENTS");
4092    
4093          #Adding intracellular metabolites that also need exchange fluxes to the exchange hash          #Adding intracellular metabolites that also need exchange fluxes to the exchange hash
4094          my $ExchangeHash = {"cpd11416" => "c"};          my $ExchangeHash = {"cpd11416" => "c"};
   
4095          my %CompartmentsPresent;          my %CompartmentsPresent;
4096          $CompartmentsPresent{"c"} = 1;          $CompartmentsPresent{"c"} = 1;
4097          my %CompoundList;          my %CompoundList;
4098          my @ReactionList;          my @ReactionList;
4099          my $ReactionTable = $self->figmodel()->database()->GetDBTable("REACTIONS");          for (my $i=0; $i < $mdlTbl->size(); $i++) {
4100          for (my $i=0; $i < $ModelTable->size(); $i++) {                  my $Reaction = $mdlTbl->get_row($i)->{"LOAD"}->[0];
4101                  my $Reaction = $ModelTable->get_row($i)->{"LOAD"}->[0];                  my $row = $rxnTbl->get_row_by_key($Reaction,"DATABASE");
4102                  if (defined($ReactionTable->get_row_by_key($Reaction,"DATABASE")) && defined($ReactionTable->get_row_by_key($Reaction,"DATABASE")->{"EQUATION"}->[0])) {                  if (!defined($row)) {
4103                            $row = $bioTbl->get_row_by_key($Reaction,"DATABASE");
4104                            if (!defined($row)) {
4105                                    next;
4106                            }
4107                    }
4108                    if (!defined($row->{"EQUATION"}->[0])) {
4109                            next;
4110                    }
4111                          push(@ReactionList,$Reaction);                          push(@ReactionList,$Reaction);
4112                          $_ = $ReactionTable->get_row_by_key($Reaction,"DATABASE")->{"EQUATION"}->[0];                  $_ = $row->{"EQUATION"}->[0];
4113                          my @MatchArray = /(cpd\d\d\d\d\d)/g;                          my @MatchArray = /(cpd\d\d\d\d\d)/g;
4114                          for (my $j=0; $j < @MatchArray; $j++) {                          for (my $j=0; $j < @MatchArray; $j++) {
4115                                  $CompoundList{$MatchArray[$j]}->{"c"} = 1;                                  $CompoundList{$MatchArray[$j]}->{"c"} = 1;
4116                          }                          }
4117                          $_ = $ReactionTable->get_row_by_key($Reaction,"DATABASE")->{"EQUATION"}->[0];                  $_ = $row->{"EQUATION"}->[0];
4118                          @MatchArray = /(cpd\d\d\d\d\d\[\D\])/g;                          @MatchArray = /(cpd\d\d\d\d\d\[\D\])/g;
4119                          for (my $j=0; $j < @MatchArray; $j++) {                          for (my $j=0; $j < @MatchArray; $j++) {
4120                                  if ($MatchArray[$j] =~ m/(cpd\d\d\d\d\d)\[(\D)\]/) {                                  if ($MatchArray[$j] =~ m/(cpd\d\d\d\d\d)\[(\D)\]/) {
# Line 3033  Line 4123 
4123                                  }                                  }
4124                          }                          }
4125                  }                  }
         }  
4126    
4127          #Printing header to SBML file          #Printing header to SBML file
4128          my $ModelName = $self->id();          my $ModelName = $self->id().$self->selected_version();
4129          $ModelName =~ s/\./_/;          $ModelName =~ s/\./_/;
4130          print SBMLOUTPUT '<?xml version="1.0" encoding="UTF-8"?>'."\n";          print SBMLOUTPUT '<?xml version="1.0" encoding="UTF-8"?>'."\n";
4131      print SBMLOUTPUT '<sbml xmlns="http://www.sbml.org/sbml/level2" level="2" version="1" xmlns:html="http://www.w3.org/1999/xhtml">' . "\n";      print SBMLOUTPUT '<sbml xmlns="http://www.sbml.org/sbml/level2" level="2" version="1" xmlns:html="http://www.w3.org/1999/xhtml">' . "\n";
4132      if (defined($self->figmodel()->database()->GetDBTable("MODEL STATS")->{$self->id()}->[0]->{"Organism name"}->[0])) {          if (defined($self->name())) {
4133          print SBMLOUTPUT '<model id="'.$ModelName.'" name="'.$self->figmodel()->database()->GetDBTable("MODEL STATS")->{$self->id()}->[0]->{"Organism name"}->[0].' SEED model">'."\n";                  print SBMLOUTPUT '<model id="'.$ModelName.'" name="'.$self->name().' SEED model">'."\n";
4134      } else {      } else {
4135          print SBMLOUTPUT '<model id="'.$ModelName.'" name="'.$self->id().' SEED model">'."\n";                  print SBMLOUTPUT '<model id="'.$ModelName.'" name="'.$self->id().$self->selected_version().' SEED model">'."\n";
4136      }      }
4137    
4138          #Printing the unit data          #Printing the unit data
# Line 3060  Line 4149 
4149      #Printing compartments for SBML file      #Printing compartments for SBML file
4150      print SBMLOUTPUT '<listOfCompartments>'."\n";      print SBMLOUTPUT '<listOfCompartments>'."\n";
4151      foreach my $Compartment (keys(%CompartmentsPresent)) {      foreach my $Compartment (keys(%CompartmentsPresent)) {
4152          if (defined($self->figmodel()->database()->GetDBTable("COMPARTMENTS")->{$Compartment}->[0]->{"Name"}->[0])) {                  my $row = $cmpTbl->get_row_by_key($Compartment,"Abbreviation");
4153                  my @OutsideList = split(/\//,$self->figmodel()->database()->GetDBTable("COMPARTMENTS")->{$Compartment}->[0]->{"Outside"}->[0]);                  if (!defined($row) && !defined($row->{"Name"}->[0])) {
4154                            next;
4155                    }
4156                    my @OutsideList = split(/\//,$row->{"Outside"}->[0]);
4157                  my $Printed = 0;                  my $Printed = 0;
4158                  foreach my $Outside (@OutsideList) {                  foreach my $Outside (@OutsideList) {
4159                                  if (defined($CompartmentsPresent{$Outside}) && defined($self->figmodel()->database()->GetDBTable("COMPARTMENTS")->{$Outside}->[0]->{"Name"}->[0])) {                          if (defined($CompartmentsPresent{$Outside}) && defined($row->{"Name"}->[0])) {
4160                                  print SBMLOUTPUT '<compartment id="'.$self->figmodel()->database()->GetDBTable("COMPARTMENTS")->{$Compartment}->[0]->{"Name"}->[0].'" outside="'.$self->figmodel()->database()->GetDBTable("COMPARTMENTS")->{$Outside}->[0]->{"Name"}->[0].'"/>'."\n";                                  print SBMLOUTPUT '<compartment id="'.$row->{"Name"}->[0].'" outside="'.$row->{"Name"}->[0].'"/>'."\n";
4161                                  $Printed = 1;                                  $Printed = 1;
4162                                  last;                                  last;
4163                          }                          }
4164                  }                  }
4165                  if ($Printed eq 0) {                  if ($Printed eq 0) {
4166                          print SBMLOUTPUT '<compartment id="'.$self->figmodel()->database()->GetDBTable("COMPARTMENTS")->{$Compartment}->[0]->{"Name"}->[0].'"/>'."\n";                          print SBMLOUTPUT '<compartment id="'.$row->{"Name"}->[0].'"/>'."\n";
                         }  
4167          }          }
4168      }      }
4169      print SBMLOUTPUT '</listOfCompartments>'."\n";      print SBMLOUTPUT '</listOfCompartments>'."\n";
# Line 3080  Line 4171 
4171      #Printing the list of metabolites involved in the model      #Printing the list of metabolites involved in the model
4172          print SBMLOUTPUT '<listOfSpecies>'."\n";          print SBMLOUTPUT '<listOfSpecies>'."\n";
4173      foreach my $Compound (keys(%CompoundList)) {      foreach my $Compound (keys(%CompoundList)) {
4174                    my $row = $cpdTbl->get_row_by_key($Compound,"DATABASE");
4175                    if (!defined($row)) {
4176                            next;
4177                    }
4178          my $Name = $Compound;          my $Name = $Compound;
4179                  my $Formula = "";                  my $Formula = "";
4180                  if (defined($self->figmodel()->database()->GetDBTable("COMPOUNDS")->{$Compound}->[0]->{"FORMULA"}->[0])) {                  if (defined($row->{"FORMULA"}->[0])) {
4181                          $Formula = $self->figmodel()->database()->GetDBTable("COMPOUNDS")->{$Compound}->[0]->{"FORMULA"}->[0];                          $Formula = $row->{"FORMULA"}->[0];
4182                  }                  }
4183                  if (defined($self->figmodel()->database()->GetDBTable("COMPOUNDS")->{$Compound}->[0]->{"NAME"}->[0])) {                  if (defined($row->{"NAME"}->[0])) {
4184                          $Name = $self->figmodel()->database()->GetDBTable("COMPOUNDS")->{$Compound}->[0]->{"NAME"}->[0];                          $Name = $row->{"NAME"}->[0];
4185                          $Name =~ s/\s/_/;                          $Name =~ s/\s/_/;
4186                          $Name .= "_".$Formula;                          $Name .= "_".$Formula;
4187                  }                  }
4188                  $Name =~ s/[<>;&\*]//;                  $Name =~ s/[<>;&\*]//;
4189                  my $Charge = 0;                  my $Charge = 0;
4190                  if (defined($self->figmodel()->database()->GetDBTable("COMPOUNDS")->{$Compound}->[0]->{"CHARGE"}->[0])) {                  if (defined($row->{"CHARGE"}->[0])) {
4191                          $Charge = $self->figmodel()->database()->GetDBTable("COMPOUNDS")->{$Compound}->[0]->{"CHARGE"}->[0];                          $Charge = $row->{"CHARGE"}->[0];
4192                  }                  }
4193                  foreach my $Compartment (keys(%{$CompoundList{$Compound}})) {                  foreach my $Compartment (keys(%{$CompoundList{$Compound}})) {
4194                  if ($Compartment eq "e") {                  if ($Compartment eq "e") {
4195                          $ExchangeHash->{$Compound} = "e";                          $ExchangeHash->{$Compound} = "e";
4196                  }                  }
4197                  print SBMLOUTPUT '<species id="'.$Compound.'_'.$Compartment.'" name="'.$Name.'" compartment="'.$self->figmodel()->database()->GetDBTable("COMPARTMENTS")->{$Compartment}->[0]->{"Name"}->[0].'" charge="'.$Charge.'" boundaryCondition="false"/>'."\n";                          my $cmprow = $cmpTbl->get_row_by_key($Compartment,"Abbreviation");
4198                            print SBMLOUTPUT '<species id="'.$Compound.'_'.$Compartment.'" name="'.$Name.'" compartment="'.$cmprow->{"Name"}->[0].'" charge="'.$Charge.'" boundaryCondition="false"/>'."\n";
4199          }          }
4200      }      }
4201    
4202          #Printing the boundary species          #Printing the boundary species
4203          foreach my $Compound (keys(%{$ExchangeHash})) {          foreach my $Compound (keys(%{$ExchangeHash})) {
4204                  my $Name = $Compound;                  my $Name = $Compound;
4205                  my $Formula = "";                  my $Formula = "";
4206                  if (defined($self->figmodel()->database()->GetDBTable("COMPOUNDS")->{$Compound}->[0]->{"FORMULA"}->[0])) {                  my $row = $cpdTbl->get_row_by_key($Compound,"DATABASE");
4207                          $Formula = $self->figmodel()->database()->GetDBTable("COMPOUNDS")->{$Compound}->[0]->{"FORMULA"}->[0];                  if (!defined($row)) {
4208                            next;
4209                  }                  }
4210                  if (defined($self->figmodel()->database()->GetDBTable("COMPOUNDS")->{$Compound}->[0]->{"NAME"}->[0])) {                  if (defined($row->{"FORMULA"}->[0])) {
4211                          $Name = $self->figmodel()->database()->GetDBTable("COMPOUNDS")->{$Compound}->[0]->{"NAME"}->[0];                          $Formula = $row->{"FORMULA"}->[0];
4212                    }
4213                    if (defined($row->{"NAME"}->[0])) {
4214                            $Name = $row->{"NAME"}->[0];
4215                          $Name =~ s/\s/_/;                          $Name =~ s/\s/_/;
4216                          $Name .= "_".$Formula;                          $Name .= "_".$Formula;
4217                  }                  }
4218                  $Name =~ s/[<>;&\*]//;                  $Name =~ s/[<>;&\*]//;
4219                  my $Charge = 0;                  my $Charge = 0;
4220                  if (defined($self->figmodel()->database()->GetDBTable("COMPOUNDS")->{$Compound}->[0]->{"CHARGE"}->[0])) {                  if (defined($row->{"CHARGE"}->[0])) {
4221                          $Charge = $self->figmodel()->database()->GetDBTable("COMPOUNDS")->{$Compound}->[0]->{"CHARGE"}->[0];                          $Charge = $row->{"CHARGE"}->[0];
4222                  }                  }
4223                  print SBMLOUTPUT '<species id="'.$Compound.'_b" name="'.$Name.'" compartment="Extracellular" charge="'.$Charge.'" boundaryCondition="true"/>'."\n";                  print SBMLOUTPUT '<species id="'.$Compound.'_b" name="'.$Name.'" compartment="Extracellular" charge="'.$Charge.'" boundaryCondition="true"/>'."\n";
4224          }          }
# Line 3126  Line 4227 
4227      #Printing the list of reactions involved in the model      #Printing the list of reactions involved in the model
4228          my $ObjectiveCoef;          my $ObjectiveCoef;
4229      print SBMLOUTPUT '<listOfReactions>'."\n";      print SBMLOUTPUT '<listOfReactions>'."\n";
4230    
4231          foreach my $Reaction (@ReactionList) {          foreach my $Reaction (@ReactionList) {
4232          $ObjectiveCoef = "0.0";          $ObjectiveCoef = "0.0";
4233                  if (defined($self->figmodel()->database()->GetDBTable("REACTIONS")->{$Reaction}->[0]->{"EQUATION"}->[0])) {                  my $mdlrow = $mdlTbl->get_row_by_key($Reaction,"LOAD");
4234                    my $Reaction = $mdlrow->{"LOAD"}->[0];
4235                    my $row = $rxnTbl->get_row_by_key($Reaction,"DATABASE");
4236                    if (!defined($row)) {
4237                            $row = $bioTbl->get_row_by_key($Reaction,"DATABASE");
4238                            if (!defined($row)) {
4239                                    next;
4240                            }
4241                    }
4242                    if (!defined($row->{"EQUATION"}->[0])) {
4243                            next;
4244                    }
4245                  if ($Reaction =~ m/^bio/) {                  if ($Reaction =~ m/^bio/) {
4246                                  $ObjectiveCoef = "1.0";                                  $ObjectiveCoef = "1.0";
4247                          }                          }
4248                          my $LowerBound = -10000;                          my $LowerBound = -10000;
4249                  my $UpperBound = 10000;                  my $UpperBound = 10000;
4250                          my ($Reactants,$Products) = $self->figmodel()->GetReactionSubstrateData($Reaction);                  my ($Reactants,$Products) = $self->figmodel()->GetReactionSubstrateDataFromEquation($row->{"EQUATION"}->[0]);
4251                  my $Name = $Reaction;                  my $Name = $Reaction;
4252                  if (defined($self->figmodel()->database()->GetDBTable("REACTIONS")->{$Reaction}->[0]->{"NAME"}->[0])) {                  if (defined($row->{"NAME"}->[0])) {
4253                          $Name = $self->figmodel()->database()->GetDBTable("REACTIONS")->{$Reaction}->[0]->{"NAME"}->[0];                          $Name = $row->{"NAME"}->[0];
4254                                  $Name =~ s/[<>;&]//g;                                  $Name =~ s/[<>;&]//g;
4255                  }                  }
4256                  my $Reversibility = "true";                  my $Reversibility = "true";
4257                  if (defined($ModelTable->{$Reaction}->[0]->{"DIRECTIONALITY"}->[0])) {                  if (defined($mdlrow->{"DIRECTIONALITY"}->[0])) {
4258                          if ($ModelTable->{$Reaction}->[0]->{"DIRECTIONALITY"}->[0] ne "<=>") {                          if ($mdlrow->{"DIRECTIONALITY"}->[0] ne "<=>") {
4259                                  $LowerBound = 0;                                  $LowerBound = 0;
4260                                          $Reversibility = "false";                                          $Reversibility = "false";
4261                          }                          }
4262                          if ($ModelTable->{$Reaction}->[0]->{"DIRECTIONALITY"}->[0] eq "<=") {                          if ($mdlrow->{"DIRECTIONALITY"}->[0] eq "<=") {
4263                                  my $Temp = $Products;                                  my $Temp = $Products;
4264                                  $Products = $Reactants;                                  $Products = $Reactants;
4265                                  $Reactants = $Temp;                                  $Reactants = $Temp;
# Line 3155  Line 4268 
4268                          print SBMLOUTPUT '<reaction id="'.$Reaction.'" name="'.$Name.'" reversible="'.$Reversibility.'">'."\n";                          print SBMLOUTPUT '<reaction id="'.$Reaction.'" name="'.$Name.'" reversible="'.$Reversibility.'">'."\n";
4269                          print SBMLOUTPUT "<notes>\n";                          print SBMLOUTPUT "<notes>\n";
4270                          my $ECData = "";                          my $ECData = "";
4271                          if (defined($self->figmodel()->database()->GetDBTable("REACTIONS")->{$Reaction}->[0]->{"ENZYME"}->[0])) {                  if (defined($row->{"ENZYME"}->[0])) {
4272                                  $ECData = $self->figmodel()->database()->GetDBTable("REACTIONS")->{$Reaction}->[0]->{"ENZYME"}->[0];                          $ECData = $row->{"ENZYME"}->[0];
4273                          }                          }
4274                          my $SubsystemData = "";                          my $SubsystemData = "";
4275                          if (defined($ModelTable->{$Reaction}->[0]->{"SUBSYSTEM"}->[0])) {                  if (defined($mdlrow->{"SUBSYSTEM"}->[0])) {
4276                                  $SubsystemData = $ModelTable->{$Reaction}->[0]->{"SUBSYSTEM"}->[0];                          $SubsystemData = $mdlrow->{"SUBSYSTEM"}->[0];
4277                          }                          }
4278                          my $GeneAssociation = "";                          my $GeneAssociation = "";
4279                          my $ProteinAssociation = "";                          my $ProteinAssociation = "";
4280                          if (defined($ModelTable->{$Reaction}->[0]->{"ASSOCIATED PEG"}->[0])) {                  if (defined($mdlrow->{"ASSOCIATED PEG"}->[0])) {
4281                                  if (@{$ModelTable->{$Reaction}->[0]->{"ASSOCIATED PEG"}} == 1 && $ModelTable->{$Reaction}->[0]->{"ASSOCIATED PEG"}->[0] !~ m/\+/) {                          if (@{$mdlrow->{"ASSOCIATED PEG"}} == 1 && $mdlrow->{"ASSOCIATED PEG"}->[0] !~ m/\+/) {
4282                                          $GeneAssociation = $ModelTable->{$Reaction}->[0]->{"ASSOCIATED PEG"}->[0];                                  $GeneAssociation = $mdlrow->{"ASSOCIATED PEG"}->[0];
4283                                  } else {                                  } else {
4284                                          if (@{$ModelTable->{$Reaction}->[0]->{"ASSOCIATED PEG"}} > 1) {                                  if (@{$mdlrow->{"ASSOCIATED PEG"}} > 1) {
4285                                                  $GeneAssociation = "( ";                                                  $GeneAssociation = "( ";
4286                                          }                                          }
4287                                          for (my $i=0; $i < @{$ModelTable->{$Reaction}->[0]->{"ASSOCIATED PEG"}}; $i++) {                                  for (my $i=0; $i < @{$mdlrow->{"ASSOCIATED PEG"}}; $i++) {
4288                                                  if ($i > 0) {                                                  if ($i > 0) {
4289                                                          $GeneAssociation .= " )  or  ( ";                                                          $GeneAssociation .= " )  or  ( ";
4290                                                  }                                                  }
4291                                                  $GeneAssociation .= $ModelTable->{$Reaction}->[0]->{"ASSOCIATED PEG"}->[$i];                                          $GeneAssociation .= $mdlrow->{"ASSOCIATED PEG"}->[$i];
4292                                          }                                          }
4293                                          if (@{$ModelTable->{$Reaction}->[0]->{"ASSOCIATED PEG"}} > 1) {                                  if (@{$mdlrow->{"ASSOCIATED PEG"}} > 1) {
4294                                                  $GeneAssociation .= " )";                                                  $GeneAssociation .= " )";
4295                                          }                                          }
4296                                  }                                  }
# Line 3186  Line 4299 
4299                                          $GeneAssociation = "( ".$GeneAssociation." )";                                          $GeneAssociation = "( ".$GeneAssociation." )";
4300                                  }                                  }
4301                                  $ProteinAssociation = $GeneAssociation;                                  $ProteinAssociation = $GeneAssociation;
4302                                  if (defined($self->figmodel()->database()->GetDBTable("MODEL STATS")->{$self->id()}->[0]->{"Genome ID"}->[0])) {                          if (defined($self->genome())) {
4303                                          $ProteinAssociation = $self->figmodel()->translate_gene_to_protein($ModelTable->{$Reaction}->[0]->{"ASSOCIATED PEG"}->[0],$self->figmodel()->database()->GetDBTable("MODEL STATS")->{$self->id()}->[0]->{"Genome ID"}->[0]);                                  $ProteinAssociation = $self->figmodel()->translate_gene_to_protein($mdlrow->{"ASSOCIATED PEG"}->[0],$self->genome());
4304                                  }                                  }
4305                          }                          }
4306                          print SBMLOUTPUT "<html:p>GENE_ASSOCIATION:".$GeneAssociation."</html:p>\n";                          print SBMLOUTPUT "<html:p>GENE_ASSOCIATION:".$GeneAssociation."</html:p>\n";
# Line 3218  Line 4331 
4331              print SBMLOUTPUT "</kineticLaw>\n";              print SBMLOUTPUT "</kineticLaw>\n";
4332                          print SBMLOUTPUT '</reaction>'."\n";                          print SBMLOUTPUT '</reaction>'."\n";
4333                  }                  }
         }  
4334    
4335          my @ExchangeList = keys(%{$ExchangeHash});          my @ExchangeList = keys(%{$ExchangeHash});
4336          foreach my $ExCompound (@ExchangeList) {          foreach my $ExCompound (@ExchangeList) {
4337                  my $ExCompoundName = $ExCompound;                  my $ExCompoundName = $ExCompound;
4338                  my $Row = $self->figmodel()->database()->GetDBTable("COMPOUNDS")->get_row_by_key($ExCompound,"DATABASE");                  my $Row = $cpdTbl->get_row_by_key($ExCompound,"DATABASE");
4339                  if (defined($Row) && defined($Row->{"NAME"}->[0])) {                  if (defined($Row) && defined($Row->{"NAME"}->[0])) {
4340                          $ExCompoundName = $Row->{"NAME"}->[0];                          $ExCompoundName = $Row->{"NAME"}->[0];
4341                          $ExCompoundName =~ s/[<>;&]//g;                          $ExCompoundName =~ s/[<>;&]//g;
# Line 3263  Line 4375 
4375          close(SBMLOUTPUT);          close(SBMLOUTPUT);
4376  }  }
4377    
4378    =head3 PrintModelSimpleReactionTable
4379    Definition:
4380            success()/fail() FIGMODELmodel->PrintModelSimpleReactionTable();
4381    Description:
4382            Prints the table of model data
4383    =cut
4384    sub PrintModelSimpleReactionTable {
4385            my ($self) = @_;
4386    
4387            my $rxntbl = $self->reaction_table();
4388            my $tbl = $self->create_table_prototype("ModelSimpleReactionTable");
4389            for (my $i=0; $i < $rxntbl->size(); $i++) {
4390                    my $row = $rxntbl->get_row($i);
4391                    $row->{DATABASE} = $row->{LOAD};
4392                    $tbl->add_row($row);
4393            }
4394            $tbl->save();
4395    }
4396    
4397  =head3 PrintModelLPFile  =head3 PrintModelLPFile
4398  Definition:  Definition:
4399          success()/fail() FIGMODELmodel->PrintModelLPFile();          success()/fail() FIGMODELmodel->PrintModelLPFile();
# Line 3287  Line 4418 
4418          $self->figmodel()->clearing_output($UniqueFilename,"FBA-".$self->id().$self->selected_version().".lp");          $self->figmodel()->clearing_output($UniqueFilename,"FBA-".$self->id().$self->selected_version().".lp");
4419  }  }
4420    
4421    =head3 patch_model
4422 &