[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.22, Mon Jul 26 04:51:24 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                    print STDERR "KeyTable:".$filename.".\n";
461                    if (-e $filename) {
462                            $self->{"_".$name} = $self->figmodel()->database()->load_table($filename,$columnDelim,$itemDelim,$tbldef->{headingline}->[0],$tbldef->{hashcolumns});
463                    } else {
464                            if (defined($tbldef->{prefix})) {
465                                    $self->{"_".$name} = FIGMODELTable->new($tbldef->{columns},$filename,$tbldef->{hashcolumns},$columnDelim,$itemDelim,join(@{$tbldef->{prefix}},"\n"));
466                            } else {
467                                    $self->{"_".$name} = FIGMODELTable->new($tbldef->{columns},$filename,$tbldef->{hashcolumns},$columnDelim,$itemDelim);
468                            }
469                    }
470            }
471            return $self->{"_".$name};
472    }
473    
474    =head3 create_table_prototype
475    
476    Definition:
477            FIGMODELTable::table = FIGMODELmodel->create_table_prototype(string::table);
478    Description:
479            Returns a empty FIGMODELTable with all the metadata associated with the input table name
480    
481    =cut
482    sub create_table_prototype {
483            my ($self,$TableName) = @_;
484            #Checking if the table definition exists in the FIGMODELconfig file
485            my $tbldef = $self->figmodel()->config($TableName);
486            if (!defined($tbldef)) {
487                    $self->figmodel()->error_message("FIGMODELdatabase:create_table_prototype:Definition not found for ".$TableName);
488                    return undef;
489            }
490            #Checking that this is a database table
491            if (!defined($tbldef->{tabletype}) || $tbldef->{tabletype}->[0] ne "ModelTable") {
492                    $self->figmodel()->error_message("FIGMODELdatabase:create_table_prototype:".$TableName." is not a model table!");
493                    return undef;
494            }
495            #Setting default values for table parameters
496            my $prefix;
497            if (defined($tbldef->{prefix})) {
498                    $prefix = join("\n",@{$self->config($TableName)->{prefix}})."\n";
499            }
500            my $itemDelim = "|";
501            if (defined($tbldef->{itemdelimiter}->[0])) {
502                    $itemDelim = $tbldef->{itemdelimiter}->[0];
503                    if ($itemDelim eq "SC") {
504                            $itemDelim = ";";
505                    }
506            }
507            my $columnDelim = "\t";
508            if (defined($tbldef->{columndelimiter}->[0])) {
509                    $columnDelim = $tbldef->{columndelimiter}->[0];
510                    if ($columnDelim eq "SC") {
511                            $columnDelim = ";";
512                    }
513            }
514            my $suffix = ".tbl";
515            if (defined($tbldef->{filename_suffix}->[0])) {
516                    $suffix = $tbldef->{filename_suffix}->[0];
517            }
518            my $filename = $self->directory().$TableName."-".$self->id().$self->selected_version().$suffix;
519            if (defined($tbldef->{filename_prefix}->[0])) {
520                    if ($tbldef->{filename_prefix}->[0] eq "NONE") {
521                            $filename = $self->directory().$self->id().$self->selected_version().$suffix;
522                    } else {
523                            $filename = $self->directory().$tbldef->{filename_prefix}->[0]."-".$self->id().$self->selected_version().$suffix;
524                    }
525            }
526            #Creating the table prototype
527            my $tbl = FIGMODELTable->new($tbldef->{columns},$filename,$tbldef->{hashcolumns},$columnDelim,$itemDelim,$prefix);
528            return $tbl;
529    }
530    
531  =head3 get_reaction_number  =head3 get_reaction_number
532  Definition:  Definition:
533          int = FIGMODELmodel->get_reaction_number();          int = FIGMODELmodel->get_reaction_number();
# Line 374  Line 536 
536  =cut  =cut
537  sub get_reaction_number {  sub get_reaction_number {
538          my ($self) = @_;          my ($self) = @_;
   
539          if (!defined($self->reaction_table())) {          if (!defined($self->reaction_table())) {
540                  return 0;                  return 0;
541          }          }
   
542          return $self->reaction_table()->size();          return $self->reaction_table()->size();
543  }  }
544    
# Line 389  Line 549 
549          Returns FIGMODELTable with the reaction list for the model          Returns FIGMODELTable with the reaction list for the model
550  =cut  =cut
551  sub reaction_table {  sub reaction_table {
552          my ($self) = @_;          my ($self,$clear) = @_;
553            if (defined($clear) && $clear == 1) {
554                    delete $self->{_reaction_table};
555            }
556            if (!defined($self->{_reaction_table})) {
557                    $self->{_reaction_table} = $self->load_model_table("ModelReactions",$clear);
558                    my $classTbl = $self->reaction_class_table();
559                    if (defined($classTbl)) {
560                            for (my $i=0; $i < $classTbl->size(); $i++) {
561                                    my $row = $classTbl->get_row($i);
562                                    if (defined($row->{REACTION})) {
563                                            my $rxnRow = $self->{_reaction_table}->get_row_by_key($row->{"REACTION"}->[0],"LOAD");
564                                            if (defined($row->{MEDIA})) {
565                                                    for (my $j=0; $j < @{$row->{MEDIA}};$j++) {
566                                                            my $class = "Active <=>";
567                                                            if ($row->{CLASS}->[$j] eq "Positive") {
568                                                                    $class = "Essential =>";
569                                                            } elsif ($row->{CLASS}->[$j] eq "Negative") {
570                                                                    $class = "Essential <=";
571                                                            } elsif ($row->{CLASS}->[$j] eq "Blocked") {
572                                                                    $class = "Inactive";
573                                                            } elsif ($row->{CLASS}->[$j] eq "Positive variable") {
574                                                                    $class = "Active =>";
575                                                            } elsif ($row->{CLASS}->[$j] eq "Negative variable") {
576                                                                    $class = "Active <=";
577                                                            } elsif ($row->{CLASS}->[$j] eq "Variable") {
578                                                                    $class = "Active <=>";
579                                                            } elsif ($row->{CLASS}->[$j] eq "Dead") {
580                                                                    $class = "Dead";
581                                                            }
582                                                            push(@{$rxnRow->{PREDICTIONS}},$row->{MEDIA}->[$j].":".$class);
583                                                    }
584                                            }
585                                    }
586                            }
587                    }
588            }
589            return $self->{_reaction_table};
590    }
591    
592          if (!defined($self->{_reaction_data})) {  =head3 essentials_table
593                  $self->{_reaction_data} = $self->figmodel()->database()->GetDBModel($self->id());  Definition:
594            FIGMODELTable = FIGMODELmodel->essentials_table();
595    Description:
596            Returns FIGMODELTable with the essential genes for the model
597    =cut
598    sub essentials_table {
599            my ($self,$clear) = @_;
600            my $tbl = $self->load_model_table("ModelEssentialGenes",$clear);
601            return $tbl;
602          }          }
603    
604          return $self->{_reaction_data};  =head3 model_history
605    Definition:
606            FIGMODELTable = FIGMODELmodel->model_history();
607    Description:
608            Returns FIGMODELTable with the history of model changes
609    =cut
610    sub model_history {
611            my ($self,$clear) = @_;
612            return $self->load_model_table("ModelHistory",$clear);
613  }  }
614    
615  =head3 reaction_class_table  =head3 feature_table
616  Definition:  Definition:
617          FIGMODELTable = FIGMODELmodel->reaction_class_table();          FIGMODELTable = FIGMODELmodel->feature_table();
618  Description:  Description:
619          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
620  =cut  =cut
621  sub reaction_class_table {  sub feature_table {
622          my ($self) = @_;          my ($self) = @_;
623    
624          if (!defined($self->{_reaction_class_table})) {          if (!defined($self->{_feature_data})) {
625                  if (-e $self->directory()."ReactionClassification-".$self->id().$self->selected_version().".tbl") {                  #Getting the genome feature list
626                          $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());
627                    if (!defined($FeatureTable)) {
628                            print STDERR "FIGMODELmodel:feature_table:Could not get features for genome ".$self->genome()." in database!";
629                            return undef;
630                    }
631                    #Getting the reaction table for the model
632                    my $rxnTable = $self->reaction_table();
633                    if (!defined($rxnTable)) {
634                            print STDERR "FIGMODELmodel:feature_table:Could not get reaction table for model ".$self->id()." in database!";
635                            return undef;
636                    }
637                    #Cloning the feature table
638                    $self->{_feature_data} = $FeatureTable->clone_table_def();
639                    $self->{_feature_data}->add_headings(($self->id()."REACTIONS",$self->id()."PREDICTIONS"));
640                    for (my $i=0; $i < $rxnTable->size(); $i++) {
641                            my $Row = $rxnTable->get_row($i);
642                            if (defined($Row) && defined($Row->{"ASSOCIATED PEG"})) {
643                                    foreach my $GeneSet (@{$Row->{"ASSOCIATED PEG"}}) {
644                                            my $temp = $GeneSet;
645                                            $temp =~ s/\+/|/g;
646                                            $temp =~ s/\sAND\s/|/gi;
647                                            $temp =~ s/\sOR\s/|/gi;
648                                            $temp =~ s/[\(\)\s]//g;
649                                            my @GeneList = split(/\|/,$temp);
650                                            foreach my $Gene (@GeneList) {
651                                                    my $FeatureRow = $self->{_feature_data}->get_row_by_key("fig|".$self->genome().".".$Gene,"ID");
652                                                    if (!defined($FeatureRow)) {
653                                                            $FeatureRow = $FeatureTable->get_row_by_key("fig|".$self->genome().".".$Gene,"ID");
654                                                            if (defined($FeatureRow)) {
655                                                                    $self->{_feature_data}->add_row($FeatureRow);
656                                                            }
657                                                    }
658                                                    if (defined($FeatureRow)) {
659                                                            $self->{_feature_data}->add_data($FeatureRow,$self->id()."REACTIONS",$Row->{"LOAD"}->[0],1);
660                                                    }
661                                            }
662                                    }
663                            }
664                    }
665                    #Loading predictions
666                    my $esstbl = $self->essentials_table();
667                    for (my $i=0; $i < $self->{_feature_data}->size(); $i++) {
668                            my $Row = $self->{_feature_data}->get_row($i);
669                            if ($Row->{ID}->[0] =~ m/(peg\.\d+)/) {
670                                    my $gene = $1;
671                                    my @rows = $esstbl->get_rows_by_key($gene,"ESSENTIAL GENES");
672                                    my $mediahash;
673                                    for (my $j=0; $j < $esstbl->size(); $j++) {
674                                            $mediahash->{$esstbl->get_row($j)->{MEDIA}->[0]} = 0;
675                                    }
676                                    for (my $j=0; $j < @rows; $j++) {
677                                            $mediahash->{$rows[$j]->{MEDIA}->[0]} = 1;
678                                    }
679                                    my @mediaList = keys(%{$mediahash});
680                                    for (my $j=0; $j < @mediaList; $j++) {
681                                            if ($mediahash->{$mediaList[$j]} == 1) {
682                                                    push(@{$Row->{$self->id()."PREDICTIONS"}},$mediaList[$j].":essential");
683                  } else {                  } else {
684                          $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");
685                                            }
686                                    }
687                            }
688                    }
689                  }                  }
690            return $self->{_feature_data};
691          }          }
692    
693          return $self->{_reaction_class_table};  =head3 reaction_class_table
694    Definition:
695            FIGMODELTable = FIGMODELmodel->reaction_class_table();
696    Description:
697            Returns FIGMODELTable with the reaction class data, and creates the table file  if it does not exist
698    =cut
699    sub reaction_class_table {
700            my ($self,$clear) = @_;
701            return $self->load_model_table("ModelReactionClasses",$clear);
702  }  }
703    
704  =head3 compound_class_table  =head3 compound_class_table
# Line 425  Line 708 
708          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
709  =cut  =cut
710  sub compound_class_table {  sub compound_class_table {
711          my ($self) = @_;          my ($self,$clear) = @_;
712            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);  
                 }  
713          }          }
714    
715          return $self->{_compound_class_table};  =head3 get_essential_genes
716    Definition:
717            [string::peg ID] = FIGMODELmodel->get_essential_genes(string::media condition);
718    Description:
719            Returns an reference to an array of the predicted essential genes during growth in the input media condition
720    =cut
721    sub get_essential_genes {
722            my ($self,$media) = @_;
723            my $tbl = $self->essentials_table();
724            my $row = $tbl->get_row_by_key($media,"MEDIA");
725            if (defined($row)) {
726                    return $row->{"ESSENTIAL GENES"};
727            }
728            return undef;
729  }  }
730    
731  =head3 compound_table  =head3 compound_table
# Line 448  Line 738 
738          my ($self) = @_;          my ($self) = @_;
739    
740          if (!defined($self->{_compound_table})) {          if (!defined($self->{_compound_table})) {
741                  $self->{_compound_table} = $self->figmodel()->database()->GetDBModelCompounds($self->id());                  $self->{_compound_table} = $self->create_table_prototype("ModelCompounds");
742                    #Loading the reactions
743                    my $ReactionTable = $self->figmodel()->database()->get_table("REACTIONS");
744                    my $BiomassTable = $self->figmodel()->database()->get_table("BIOMASS");
745                    #Loading the model
746                    my $ModelTable = $self->reaction_table();
747                    #Checking that the tables were loaded
748                    if (!defined($ModelTable) || !defined($ReactionTable)) {
749                            return undef;
750                    }
751                    #Finding the biomass reaction
752                    for (my $i=0; $i < $ModelTable->size(); $i++) {
753                            my $ID = $ModelTable->get_row($i)->{"LOAD"}->[0];
754                            my $Row = $ReactionTable->get_row_by_key($ID,"DATABASE");
755                            my $IsBiomass = 0;
756                            if (!defined($Row)) {
757                                    $Row = $BiomassTable->get_row_by_key($ID,"DATABASE");
758                                    $IsBiomass = 1;
759                            }
760                            if (defined($Row->{"EQUATION"}->[0])) {
761                                    $_ = $Row->{"EQUATION"}->[0];
762                                    my @OriginalArray = /(cpd\d\d\d\d\d[\[\w]*)/g;
763                                    foreach my $Compound (@OriginalArray) {
764                                            my $ID = substr($Compound,0,8);
765                                            my $NewRow = $self->{_compound_table}->get_row_by_key($ID,"DATABASE",1);
766                                            if ($IsBiomass == 1) {
767                                                    $self->{_compound_table}->add_data($NewRow,"BIOMASS",$Row->{"DATABASE"}->[0],1);
768                                            }
769                                            if (length($Compound) > 8) {
770                                                    #print $Compound."\t".$Row->{"EQUATION"}->[0]."\t".$Row->{"DATABASE"}->[0]."\n";
771                                                    my $Compartment = substr($Compound,8,1);
772                                                    $self->{_compound_table}->add_data($NewRow,"COMPARTMENTS",$Compartment,1);
773                                                    $self->{_compound_table}->add_data($NewRow,"TRANSPORTERS",$Row->{"DATABASE"}->[0],1);
774                                            }
775                                    }
776                            }
777                    }
778          }          }
779    
780          return $self->{_compound_table};          return $self->{_compound_table};
# Line 456  Line 782 
782    
783  =head3 get_compound_data  =head3 get_compound_data
784  Definition:  Definition:
785          string = FIGMODELmodel->get_compound_data(string::compound ID);          {string:key=>[string]:values} = FIGMODELmodel->get_compound_data(string::compound ID);
786  Description:  Description:
787          Returns model compound data          Returns model compound data
788  =cut  =cut
# Line 467  Line 793 
793                  return undef;                  return undef;
794          }          }
795          if ($compound =~ m/^\d+$/) {          if ($compound =~ m/^\d+$/) {
796                  $self->compound_table()->get_row($compound);                  return $self->compound_table()->get_row($compound);
797          }          }
798          return $self->compound_table()->get_row_by_key($compound,"DATABASE");          return $self->compound_table()->get_row_by_key($compound,"DATABASE");
799  }  }
800    
801    =head3 get_feature_data
802    Definition:
803            {string:key=>[string]:values} = FIGMODELmodel->get_feature_data(string::feature ID);
804    Description:
805            Returns model feature data
806    =cut
807    sub get_feature_data {
808            my ($self,$feature) = @_;
809            if (!defined($self->feature_table())) {
810                    return undef;
811            }
812            if ($feature =~ m/^\d+$/) {
813                    return $self->feature_table()->get_row($feature);
814            }
815            if ($feature =~ m/(peg\.\d+)/) {
816                    $feature = $1;
817            }
818            return $self->feature_table()->get_row_by_key("fig|".$self->genome().".".$feature,"ID");
819    }
820    
821  =head3 genome  =head3 genome
822  Definition:  Definition:
823          string = FIGMODELmodel->genome();          string = FIGMODELmodel->genome();
# Line 480  Line 826 
826  =cut  =cut
827  sub genome {  sub genome {
828          my ($self) = @_;          my ($self) = @_;
829          return $self->{_data}->{genome}->[0];          return $self->{_data}->genome();
830  }  }
831    
832  =head3 source  =head3 source
# Line 491  Line 837 
837  =cut  =cut
838  sub source {  sub source {
839          my ($self) = @_;          my ($self) = @_;
840          return $self->{_data}->{source}->[0];          return $self->{_data}->source();
841  }  }
842    
843  =head3 rights  =head3 rights
# Line 502  Line 848 
848  =cut  =cut
849  sub rights {  sub rights {
850          my ($self,$username) = @_;          my ($self,$username) = @_;
   
851          if ($self->public()) {          if ($self->public()) {
852                  return 1;                  return 1;
853          }          }
# Line 510  Line 855 
855                  return 0;                  return 0;
856          }          }
857          if (!defined($self->{_userrights}->{$username})) {          if (!defined($self->{_userrights}->{$username})) {
858                  if (defined($self->{_data}->{master})) {                  $self->{_userrights}->{$self->{_data}->owner()} = 1;
859                          for (my $i=0; $i < @{$self->{_data}->{master}};$i++) {                  my @users = split(/\|/,$self->{_data}->users());
860                                  $self->{_userrights}->{$self->{_data}->{master}->[$i]} = 1;                  for (my $i=0; $i < @users;$i++) {
861                          }                          $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;  
                         }  
862                  }                  }
863          }          }
864          return $self->{_userrights}->{$username};          return $self->{_userrights}->{$username};
# Line 532  Line 872 
872  =cut  =cut
873  sub public {  sub public {
874          my ($self) = @_;          my ($self) = @_;
875            if ($self->{_data}->users() eq "all") {
876          if (!defined($self->{_public})) {                  return 1;
                 $self->{_public} = 0;  
                 if (defined($self->{_data}->{users}->[0]) && $self->{_data}->{users}->[0] eq "all") {  
                         $self->{_public} = 1;  
                 }  
877          }          }
878          return $self->{_public};          return 0;
879  }  }
880    
881  =head3 directory  =head3 directory
# Line 558  Line 894 
894                  }                  }
895                  my $source = $self->source();                  my $source = $self->source();
896                  if ($source =~ /^MGRAST/) {                  if ($source =~ /^MGRAST/) {
897                          $self->{_directory} = $self->figmodel()->config("organism directory")->[0].$userdirectory.$self->genome()."/";                          $self->{_directory} = $self->figmodel()->config("mgrast model directory")->[0].$userdirectory.$self->genome()."/";
898                  } elsif ($source =~ /^RAST/) {                  } elsif ($source =~ /^RAST/) {
899                          $self->{_directory} = $self->figmodel()->config("organism directory")->[0].$userdirectory.$self->genome()."/";                          $self->{_directory} = $self->figmodel()->config("organism directory")->[0].$userdirectory.$self->genome()."/";
900                  } elsif ($source =~ /^SEED/) {                  } elsif ($source =~ /^SEED/) {
# Line 587  Line 923 
923          return $self->directory().$self->id().$self->selected_version().".txt";          return $self->directory().$self->id().$self->selected_version().".txt";
924  }  }
925    
 =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};  
         }  
 }  
   
926  =head3 version  =head3 version
927  Definition:  Definition:
928          string = FIGMODELmodel->version();          string = FIGMODELmodel->version();
# Line 638  Line 934 
934    
935          if (!defined($self->{_version})) {          if (!defined($self->{_version})) {
936                  if (!defined($self->{_selectedversion})) {                  if (!defined($self->{_selectedversion})) {
937                          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];  
                         }  
938                  } else {                  } else {
939                          $self->{_version} = $self->{_selectedversion};                          $self->{_version} = $self->{_selectedversion};
940                  }                  }
# Line 671  Line 965 
965  =cut  =cut
966  sub modification_time {  sub modification_time {
967          my ($self) = @_;          my ($self) = @_;
968          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};  
969  }  }
970    
971  =head3 gene_reactions  =head3 gene_reactions
# Line 695  Line 976 
976  =cut  =cut
977  sub gene_reactions {  sub gene_reactions {
978          my ($self) = @_;          my ($self) = @_;
979            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};  
980  }  }
981    
982  =head3 total_compounds  =head3 total_compounds
# Line 714  Line 987 
987  =cut  =cut
988  sub total_compounds {  sub total_compounds {
989          my ($self) = @_;          my ($self) = @_;
990            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};  
991  }  }
992    
993  =head3 gapfilling_reactions  =head3 gapfilling_reactions
# Line 733  Line 998 
998  =cut  =cut
999  sub gapfilling_reactions {  sub gapfilling_reactions {
1000          my ($self) = @_;          my ($self) = @_;
1001            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};  
1002  }  }
1003    
1004  =head3 total_reactions  =head3 total_reactions
# Line 752  Line 1009 
1009  =cut  =cut
1010  sub total_reactions {  sub total_reactions {
1011          my ($self) = @_;          my ($self) = @_;
1012            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};  
1013  }  }
1014    
1015  =head3 model_genes  =head3 model_genes
# Line 771  Line 1020 
1020  =cut  =cut
1021  sub model_genes {  sub model_genes {
1022          my ($self) = @_;          my ($self) = @_;
1023            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};  
1024  }  }
1025    
1026  =head3 class  =head3 class
# Line 790  Line 1031 
1031  =cut  =cut
1032  sub class {  sub class {
1033          my ($self) = @_;          my ($self) = @_;
1034            return $self->{_data}->cellwalltype();
1035    }
1036    
1037          if (!defined($self->{_class})) {  sub autocompleteMedia {
1038                  if ($self->source() =~ /^MGRAST/) {          my ($self,$newMedia) = @_;
1039                          $self->{_class} = "Other";          return $self->{_data}->autoCompleteMedia($newMedia);
1040                  } elsif (defined($self->stats())) {  }
1041                          $self->{_class} = $self->stats()->{Class}->[0];  
1042    sub biomassReaction {
1043            my ($self,$newBiomass) = @_;
1044            if (!defined($newBiomass)) {
1045                    return $self->{_data}->biomassReaction();
1046            } else {
1047                    #Figuring out what the old biomass is
1048                    my $oldBiomass = $self->{_data}->biomassReaction();
1049                    if ($newBiomass ne $oldBiomass) {
1050                            #Figuring out if the new biomass exists
1051                            my $handle = $self->database()->get_object_manager("bof");
1052                            my $objects = $handle->get_objects({"DATABASE" => [$newBiomass]});
1053                            if (!defined($objects) || !defined($objects->[0])) {
1054                                    print STDERR "Could not find new biomass reaction ".$newBiomass."\n";
1055                                    return $oldBiomass;
1056                            }
1057                            #Changing the biomass reaction in the model file
1058                            my $rxnTbl = $self->reaction_table();
1059                            for (my $i=0; $i < $rxnTbl->size(); $i++) {
1060                                    my $row = $rxnTbl->get_row($i);
1061                                    if ($row->{LOAD}->[0] =~ m/^bio/) {
1062                                            $row->{LOAD}->[0] = $newBiomass;
1063                                    }
1064                            }
1065                            $rxnTbl->save();
1066                            #Changing the biomass reaction in the database
1067                            return  $self->{_data}->biomassReaction($newBiomass);
1068                  }                  }
1069          }          }
         return $self->{_class};  
1070  }  }
1071    
1072  =head3 taxonomy  =head3 taxonomy
# Line 866  Line 1134 
1134                          if (defined($self->mgdata())) {                          if (defined($self->mgdata())) {
1135                                  $self->{_genome_genes} = $self->mgdata()->genome_contig_count;                                  $self->{_genome_genes} = $self->mgdata()->genome_contig_count;
1136                          }                          }
1137                  } elsif (defined($self->stats())) {                  } else {
1138                          $self->{_genome_genes} = $self->stats()->{'Total genes'}->[0];                          $self->{_genome_genes} = $self->figmodel()->get_genome_stats($self->genome())->{"TOTAL GENES"}->[0];
1139                  }                  }
1140          }          }
1141    
# Line 884  Line 1152 
1152    
1153          #Assuming complete media if none is provided          #Assuming complete media if none is provided
1154          if (!defined($Media)) {          if (!defined($Media)) {
1155                  $Media = "Complete";                  $Media = $self->autocompleteMedia();
1156          }          }
1157    
1158          #Predicting essentiality          #Predicting essentiality
1159          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]);
1160          #Checking that the table is defined and the output file exists          #Checking that the table is defined and the output file exists
1161          if (defined($result) && defined($result->get_row(0)->{"ESSENTIALGENES"})) {          if (defined($result) && defined($result->get_row(0)->{"ESSENTIALGENES"})) {
1162                  $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();
1163                    my $row = $tbl->get_row_by_key($Media,"MEDIA",1);
1164                    $row->{"ESSENTIAL GENES"} = $result->get_row(0)->{"ESSENTIALGENES"};
1165                    $tbl->save();
1166            } else {
1167                    $self->figmodel()->error_message("FIGMODELmodel:run_default_model_predictions:could not identify essential reactions for model ".$self->id().$self->selected_version().".");
1168                    return $self->figmodel()->fail();
1169          }          }
1170    
1171          #Classifying reactions and compounds          #Classifying reactions and compounds
1172          my $tbl = $self->classify_model_reactions($Media);          my $tbl = $self->classify_model_reactions($Media);
1173            if (!defined($tbl)) {
1174                    $self->figmodel()->error_message("FIGMODELmodel:run_default_model_predictions:could not classify reactions for model ".$self->id().$self->selected_version().".");
1175                    return $self->figmodel()->fail();
1176            }
1177          $tbl->save();          $tbl->save();
1178    
1179          return $self->figmodel()->success();          return $self->figmodel()->success();
1180  }  }
1181    
 =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();  
         }  
 }  
   
1182  =head3 update_stats_for_gap_filling  =head3 update_stats_for_gap_filling
1183  Definition:  Definition:
1184          {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 1186 
1186  =cut  =cut
1187  sub update_stats_for_gap_filling {  sub update_stats_for_gap_filling {
1188          my ($self,$gapfilltime) = @_;          my ($self,$gapfilltime) = @_;
1189            $self->{_data}->autoCompleteTime($gapfilltime);
1190          #preserving the stats for the now obselete model          $self->{_data}->autocompleteDate(time());
1191          $self->save_obsolete_stats();          $self->{_data}->modificationDate(time());
1192          my $stats = $self->update_model_stats(0);          my $version = $self->{_data}->autocompleteVersion();
1193          $stats->{"Gap filling time"}->[0] = $gapfilltime;          $self->{_data}->autocompleteVersion($version+1);
1194          $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;  
1195  }  }
1196    
1197  =head3 update_stats_for_build  =head3 update_stats_for_build
# Line 948  Line 1201 
1201  =cut  =cut
1202  sub update_stats_for_build {  sub update_stats_for_build {
1203          my ($self) = @_;          my ($self) = @_;
1204            $self->{_data}->builtDate(time());
1205          #preserving the stats for the now obselete model          $self->{_data}->modificationDate(time());
1206          $self->save_obsolete_stats();          my $version = $self->{_data}->version();
1207          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;  
1208  }  }
1209    
1210  =head3 update_model_stats  =head3 update_model_stats
# Line 979  Line 1223 
1223          }          }
1224          my $cpdtbl = $self->compound_table();          my $cpdtbl = $self->compound_table();
1225    
1226          #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];  
         }  
   
1227          my %GeneHash;          my %GeneHash;
1228          my %NonpegHash;          my %NonpegHash;
1229          my %CompoundHash;          my %CompoundHash;
1230            my $spontaneousReactions = 0;
1231            my $gapFillReactions = 0;
1232            my $biologReactions = 0;
1233            my $transporters = 0;
1234            my $autoCompleteReactions = 0;
1235            my $associatedSubsystemGenes = 0;
1236          for (my $i=0; $i < $rxntbl->size(); $i++) {          for (my $i=0; $i < $rxntbl->size(); $i++) {
1237                  my $Row = $rxntbl->get_row($i);                  my $Row = $rxntbl->get_row($i);
1238                  if (defined($Row) && defined($Row->{"ASSOCIATED PEG"})) {                  if (defined($Row) && defined($Row->{"ASSOCIATED PEG"})) {
# Line 1037  Line 1240 
1240                          if (defined($ReactionRow->{"EQUATION"}->[0])) {                          if (defined($ReactionRow->{"EQUATION"}->[0])) {
1241                                  #Checking for extracellular metabolites which indicate that this is a transporter                                  #Checking for extracellular metabolites which indicate that this is a transporter
1242                                  if ($ReactionRow->{"EQUATION"}->[0] =~ m/\[e\]/) {                                  if ($ReactionRow->{"EQUATION"}->[0] =~ m/\[e\]/) {
1243                                          $CurrentStats->{"Transport reaction"}->[0]++;                                          $transporters++;
1244                                  }                                  }
1245                          }                          }
1246                          #Identifying spontaneous/biolog/gapfilling/gene associated reactions                          #Identifying spontaneous/biolog/gapfilling/gene associated reactions
1247                          if ($Row->{"ASSOCIATED PEG"}->[0] =~ m/BIOLOG/i) {                          if ($Row->{"ASSOCIATED PEG"}->[0] =~ m/BIOLOG/i) {
1248                                  $CurrentStats->{"Biolog gap filling reactions"}->[0]++;                                  $biologReactions++;
1249                            } elsif ($Row->{"ASSOCIATED PEG"}->[0] =~ m/GROW/i) {
1250                                    $gapFillReactions++;
1251                          } elsif ($Row->{"ASSOCIATED PEG"}->[0] =~ m/SPONTANEOUS/i) {                          } elsif ($Row->{"ASSOCIATED PEG"}->[0] =~ m/SPONTANEOUS/i) {
1252                                  $CurrentStats->{"Spontaneous"}->[0]++;                                  $spontaneousReactions++;
1253                          } 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) {
1254                                  $CurrentStats->{"Gap filling reactions"}->[0]++;                                  $autoCompleteReactions++;
1255                          } else {                          } else {
1256                                  foreach my $GeneSet (@{$Row->{"ASSOCIATED PEG"}}) {                                  foreach my $GeneSet (@{$Row->{"ASSOCIATED PEG"}}) {
1257                                          my @GeneList = split(/\+/,$GeneSet);                                          $_ = $GeneSet;
1258                                            my @GeneList = /(peg\.\d+)/g;
1259                                          foreach my $Gene (@GeneList) {                                          foreach my $Gene (@GeneList) {
1260                                                  if ($Gene =~ m/(peg\.\d+)/) {                                                  if ($Gene =~ m/(peg\.\d+)/) {
1261                                                          $GeneHash{$1} = 1;                                                          $GeneHash{$1} = 1;
# Line 1063  Line 1269 
1269          }          }
1270          my @genes = keys(%GeneHash);          my @genes = keys(%GeneHash);
1271          my @othergenes = keys(%NonpegHash);          my @othergenes = keys(%NonpegHash);
         $CurrentStats->{"Genes with reactions"}->[0] = @genes + @othergenes;  
1272    
1273          #Updating the stats stored in the table          #Setting the reaction count
1274          $self->figmodel()->database()->update_row("MODEL STATS",$CurrentStats,"Model ID");          $self->{_data}->reactions($rxntbl->size());
1275          $self->{_stats} = $CurrentStats;          #Setting the metabolite count
1276          return $CurrentStats;          $self->{_data}->compounds($cpdtbl->size());
1277            #Setting the gene count
1278            my $geneCount = @genes + @othergenes;
1279            $self->{_data}->associatedGenes($geneCount);
1280            #Setting remaining stats
1281            $self->{_data}->spontaneousReactions($spontaneousReactions);
1282            $self->{_data}->gapFillReactions($gapFillReactions);
1283            $self->{_data}->biologReactions($biologReactions);
1284            $self->{_data}->transporters($transporters);
1285            $self->{_data}->autoCompleteReactions($autoCompleteReactions);
1286            $self->{_data}->associatedSubsystemGenes($associatedSubsystemGenes);
1287            #Setting the model class
1288            my $class = "";
1289            for (my $i=0; $i < @{$self->figmodel()->config("class list")}; $i++) {
1290                    if (defined($self->figmodel()->config($self->figmodel()->config("class list")->[$i]))) {
1291                            if (defined($self->figmodel()->config($self->figmodel()->config("class list")->[$i])->{$self->id()})) {
1292                                    $class = $self->figmodel()->config("class list")->[$i];
1293                                    last;
1294                            }
1295                            if ($class eq "" && defined($self->figmodel()->config($self->figmodel()->config("class list")->[$i])->{$self->genome()})) {
1296                                    $class = $self->figmodel()->config("class list")->[$i];
1297                            }
1298                    }
1299            }
1300            if ($class eq "") {
1301                    $class = $self->figmodel()->get_genome_stats($self->genome())->{CLASS}->[0];
1302            }
1303            if ($class eq "") {
1304                    $class = "unknown";
1305            }
1306            $self->{_data}->cellwalltype($class);
1307  }  }
1308    
1309  =head3 GapFillModel  =head3 GapFillModel
# Line 1088  Line 1323 
1323          my $UniqueFilename = $self->figmodel()->filename();          my $UniqueFilename = $self->figmodel()->filename();
1324          my $StartTime = time();          my $StartTime = time();
1325    
1326          #Archiving the existing model          #Reading original reaction table
1327          $self->ArchiveModel();          my $OriginalRxn = $self->reaction_table();
1328            #Clearing the table
1329            $self->reaction_table(1);
1330    
1331          #Removing any gapfilling reactions that may be currently present in the model          #Removing any gapfilling reactions that may be currently present in the model
1332          if (!defined($donotclear) || $donotclear != 1) {          if (!defined($donotclear) || $donotclear != 1) {
1333                  my $ModelTable = $self->reaction_table();                  my $ModelTable = $self->reaction_table();
1334                  for (my $i=0; $i < $ModelTable->size(); $i++) {                  for (my $i=0; $i < $ModelTable->size(); $i++) {
1335                          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/) {
1336                                  $ModelTable->delete_row($i);                                  $ModelTable->delete_row($i);
1337                                  $i--;                                  $i--;
1338                          }                          }
# Line 1104  Line 1341 
1341          }          }
1342    
1343          #Calling the MFAToolkit to run the gap filling optimization          #Calling the MFAToolkit to run the gap filling optimization
1344          my $MinimalMediaTable = $self->figmodel()->database()->GetDBTable("MINIMAL MEDIA TABLE");          my $Media = $self->autocompleteMedia();
1345          my $Media = "Complete";          if ($Media eq "Complete") {
1346          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));
1347                  $Media = $MinimalMediaTable->get_row_by_key($self->genome(),"Organism")->{"Minimal media"}->[0];          } else {
1348                  #Loading media, changing bounds, saving media as a test media                  #Loading media, changing bounds, saving media as a test media
1349                  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"]);
1350                  for (my $i=0; $i < $MediaTable->size(); $i++) {                  for (my $i=0; $i < $MediaTable->size(); $i++) {
# Line 1119  Line 1356 
1356                          }                          }
1357                  }                  }
1358                  $MediaTable->save($self->config("Media directory")->[0].$UniqueFilename."TestMedia.txt");                  $MediaTable->save($self->config("Media directory")->[0].$UniqueFilename."TestMedia.txt");
1359                  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";
1360                    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));
1361                  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));  
1362          }          }
1363    
1364          #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
1365          my $SolutionData = $self->figmodel()->LoadProblemReport($UniqueFilename);          my $SolutionData = $self->figmodel()->LoadProblemReport($UniqueFilename);
1366    
1367          #Clearing the mfatoolkit output and log file          #Clearing the mfatoolkit output and log file
1368          $self->figmodel()->clearing_output($UniqueFilename,"GapFill".$self->id().".log");          $self->figmodel()->clearing_output($UniqueFilename,"GapFill".$self->id().".log");
1369          if (!defined($SolutionData) || $SolutionData->size() == 0) {          if (!defined($SolutionData) || $SolutionData->size() == 0) {
# Line 1134  Line 1371 
1371                  $self->figmodel()->error_message("FIGMODEL:GapFillModel: Gap filling report not found!");                  $self->figmodel()->error_message("FIGMODEL:GapFillModel: Gap filling report not found!");
1372                  return $self->fail();                  return $self->fail();
1373          }          }
         $SolutionData->save("/home/chenry/Solution.txt");  
1374    
1375          #Looking for the last printed recursive MILP solution          #Looking for the last printed recursive MILP solution
1376          for (my $i=($SolutionData->size()-1); $i >=0; $i--) {          for (my $i=($SolutionData->size()-1); $i >=0; $i--) {
1377                  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/) {
1378                          my $AllSolutions = substr($SolutionData->get_row($i)->{"Notes"}->[0],15);                          my $AllSolutions = substr($SolutionData->get_row($i)->{"Notes"}->[0],15);
                         print "Solution:".$AllSolutions."\n";  
1379                          my @TempThree = split(/\|/,$AllSolutions);                          my @TempThree = split(/\|/,$AllSolutions);
1380                          if (@TempThree > 0 && $TempThree[0] =~ m/.+:(.+)/) {                          if (@TempThree > 0 && $TempThree[0] =~ m/.+:(.+)/) {
1381                                  my @TempFour = split(/,/,$1);                                  my @TempFour = split(/,/,$1);
# Line 1163  Line 1398 
1398                                                  push(@{$ReactionList},$ID);                                                  push(@{$ReactionList},$ID);
1399                                          }                                          }
1400                                  }                                  }
1401                                  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);  
1402                          }                          }
1403                          last;                          last;
1404                  }                  }
1405          }          }
1406    
1407          #Updating model stats with gap filling results          #Updating model stats with gap filling results
1408          my $ElapsedTime = time() - $StartTime;          my $ElapsedTime = time() - $StartTime;
1409          $self->figmodel()->ClearDBModel($self->id(),1);          $self->reaction_table(1);
1410            $self->calculate_model_changes($OriginalRxn,"AUTOCOMPLETION");
1411    
1412          #Determining why each gap filling reaction was added          #Determining why each gap filling reaction was added
1413          $self->figmodel()->IdentifyDependancyOfGapFillingReactions($self->id(),$Media);          $self->figmodel()->IdentifyDependancyOfGapFillingReactions($self->id(),$Media);
1414          if (!defined($donotclear) || $donotclear != 1) {          if (!defined($donotclear) || $donotclear != 1) {
                 $self->figmodel()->AddBiologTransporters($self->id());  
1415                  if ($self->id() !~ m/MGRast/) {                  if ($self->id() !~ m/MGRast/) {
1416                          $self->update_stats_for_gap_filling($ElapsedTime);                          $self->update_stats_for_gap_filling($ElapsedTime);
1417                  }                  }
# Line 1191  Line 1427 
1427          return $self->success();          return $self->success();
1428  }  }
1429    
1430    =head3 calculate_model_changes
1431    Definition:
1432            FIGMODELmodel->calculate_model_changes(FIGMODELTable:original reaction table,string:modification cause);
1433    Description:
1434    
1435    =cut
1436    
1437    sub calculate_model_changes {
1438            my ($self,$originalReactions,$cause,$tbl,$version) = @_;
1439            my $modTime = time();
1440            if (!defined($version)) {
1441                    $version = $self->selected_version();
1442            }
1443            my $user = $self->figmodel()->user();
1444            #Getting the history table
1445            my $histTbl = $self->model_history();
1446            #Checking for differences
1447            if (!defined($tbl)) {
1448                    $tbl = $self->reaction_table();
1449            }
1450            for (my $i=0; $i < $tbl->size(); $i++) {
1451                    my $row = $tbl->get_row($i);
1452                    my $orgRow = $originalReactions->get_row_by_key($row->{LOAD}->[0],"LOAD");
1453                    if (!defined($orgRow)) {
1454                            $histTbl->add_row({Reaction => [$row->{LOAD}->[0]], DirectionChange => $row->{DIRECTIONALITY}, GeneChange => $row->{"ASSOCIATED PEG"}, Action => ["ADDED"], ModificationTime => [$modTime], ModifcationCause => [$cause], User => [$user], Version => [$version]});
1455                    } else {
1456                            my $geneChanges;
1457                            my $directionChange;
1458                            if ($orgRow->{"DIRECTIONALITY"}->[0] ne $row->{"DIRECTIONALITY"}->[0]) {
1459                                    $directionChange = $orgRow->{"DIRECTIONALITY"}->[0]." to ".$row->{"DIRECTIONALITY"}->[0];
1460                            }
1461                            for (my $j=0; $j < @{$row->{"ASSOCIATED PEG"}}; $j++) {
1462                                    my $match = 0;
1463                                    if (defined($orgRow->{"ASSOCIATED PEG"})) {
1464                                            for (my $k=0; $k < @{$orgRow->{"ASSOCIATED PEG"}}; $k++) {
1465                                                    if ($row->{"ASSOCIATED PEG"}->[$j] eq $orgRow->{"ASSOCIATED PEG"}->[$k]) {
1466                                                            $match = 1;
1467                                                    }
1468                                            }
1469                                    }
1470                                    if ($match == 0) {
1471                                            push(@{$geneChanges},"Added ".$row->{"ASSOCIATED PEG"}->[$j]);
1472                                    }
1473                            }
1474                            if (defined($orgRow->{"ASSOCIATED PEG"})) {
1475                                    for (my $k=0; $k < @{$orgRow->{"ASSOCIATED PEG"}}; $k++) {
1476                                            my $match = 0;
1477                                            if (defined($row->{"ASSOCIATED PEG"})) {
1478                                                    for (my $j=0; $j < @{$row->{"ASSOCIATED PEG"}}; $j++) {
1479                                                            if ($row->{"ASSOCIATED PEG"}->[$j] eq $orgRow->{"ASSOCIATED PEG"}->[$k]) {
1480                                                                    $match = 1;
1481                                                            }
1482                                                    }
1483                                            }
1484                                            if ($match == 0) {
1485                                                    push(@{$geneChanges},"Removed ".$orgRow->{"ASSOCIATED PEG"}->[$k]);
1486                                            }
1487                                    }
1488                            }
1489                            if ((defined($directionChange) && length($directionChange) > 0) || defined($geneChanges) && @{$geneChanges} > 0) {
1490                                    $histTbl->add_row({Reaction => [$row->{LOAD}->[0]], DirectionChange => [$directionChange], GeneChange => $geneChanges, Action => ["CHANGE"], ModificationTime => [$modTime], ModifcationCause => [$cause], User => [$user], Version => [$version]});
1491                            }
1492                    }
1493            }
1494            #Looking for removed reactions
1495            for (my $i=0; $i < $originalReactions->size(); $i++) {
1496                    my $row = $originalReactions->get_row($i);
1497                    my $orgRow = $tbl->get_row_by_key($row->{LOAD}->[0],"LOAD");
1498                    if (!defined($orgRow)) {
1499                            $histTbl->add_row({Reaction => [$row->{LOAD}->[0]], DirectionChange => $row->{DIRECTIONALITY}, GeneChange => $row->{"ASSOCIATED PEG"}, Action => ["REMOVED"], ModificationTime => [$modTime], ModifcationCause => [$cause], User => [$user], Version => [$version]});
1500                    }
1501            }
1502            $histTbl->save();
1503    }
1504    
1505    =head3 GapGenModel
1506    Definition:
1507            FIGMODELmodel->GapGenModel();
1508    Description:
1509            Runs the gap generation algorithm to correct a single false positive prediction. Results are loaded into a table.
1510    =cut
1511    
1512    sub GapGenModel {
1513            my ($self,$Media,$KOList,$NoKOList,$Experiment,$SolutionLimit) = @_;
1514    
1515            #Enforcing nonoptional arguments
1516            if (!defined($Media)) {
1517                    return undef;
1518            }
1519            if (!defined($KOList)) {
1520                    $KOList->[0] = "none";
1521            }
1522            if (!defined($NoKOList)) {
1523                    $NoKOList->[0] = "none";
1524            }
1525            if (!defined($Experiment)) {
1526                    $Experiment= "ReactionKO";
1527            }
1528            if (!defined($SolutionLimit)) {
1529                    $SolutionLimit = "10";
1530            }
1531    
1532            #Translating the KO lists into arrays
1533            if (ref($KOList) ne "ARRAY") {
1534                    my $temp = $KOList;
1535                    $KOList = ();
1536                    push(@{$KOList},split(/[,;]/,$temp));
1537            }
1538            my $noKOHash;
1539            if (defined($NoKOList) && ref($NoKOList) ne "ARRAY") {
1540                    my $temp = $NoKOList;
1541                    $NoKOList = ();
1542                    push(@{$NoKOList},split(/[,;]/,$temp));
1543                    foreach my $rxn (@{$NoKOList}) {
1544                            $noKOHash->{$rxn} = 1;
1545                    }
1546            }
1547    
1548            #Checking if solutions exist for the input parameters
1549            $self->aquireModelLock();
1550            my $tbl = $self->load_model_table("GapGenSolutions");
1551            my $solutionRow = $tbl->get_table_by_key($Experiment,"Experiment")->get_table_by_key($Media,"Media")->get_row_by_key(join(",",@{$KOList}),"KOlist");
1552            my $solutions;
1553            if (defined($solutionRow)) {
1554                    #Checking if any solutions conform to the no KO list
1555                    foreach my $solution (@{$solutionRow->{Solutions}}) {
1556                            my @reactions = split(/,/,$solution);
1557                            my $include = 1;
1558                            foreach my $rxn (@reactions) {
1559                                    if ($rxn =~ m/(rxn\d\d\d\d\d)/) {
1560                                            if (defined($noKOHash->{$1})) {
1561                                                    $include = 0;
1562                                            }
1563                                    }
1564                            }
1565                            if ($include == 1) {
1566                                    push(@{$solutions},$solution);
1567                            }
1568                    }
1569            } else {
1570                    $solutionRow = {Media => [$Media],Experiment => [$Experiment],KOlist => [join(",",@{$KOList})]};
1571                    $tbl->add_row($solutionRow);
1572                    $self->figmodel()->database()->save_table($tbl);
1573            }
1574            $self->releaseModelLock();
1575    
1576            #Returning solution list of solutions were found
1577            if (defined($solutions) && @{$solutions} > 0) {
1578                    return $solutions;
1579            }
1580    
1581            #Getting unique filename
1582            my $Filename = $self->figmodel()->filename();
1583    
1584            #Running the gap generation
1585            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));
1586            my $ProblemReport = $self->figmodel()->LoadProblemReport($Filename);
1587            if (!defined($ProblemReport)) {
1588                    $self->figmodel()->error_message("FIGMODEL:GapGenerationAlgorithm;No problem report;".$Filename.";".$self->id().$self->selected_version().";".$Media.";".$KOList.";".$NoKOList);
1589                    return undef;
1590            }
1591    
1592            #Clearing the output folder and log file
1593            $self->figmodel()->clearing_output($Filename,"Gapgeneration-".$self->id().$self->selected_version()."-".$Filename.".log");
1594    
1595            #Saving the solution
1596            $self->aquireModelLock();
1597            $tbl = $self->load_model_table("GapGenSolutions");
1598            $solutionRow = $tbl->get_table_by_key($Experiment,"Experiment")->get_table_by_key($Media,"Media")->get_row_by_key(join(",",@{$KOList}),"KOlist");
1599            for (my $j=0; $j < $ProblemReport->size(); $j++) {
1600                    if ($ProblemReport->get_row($j)->{"Notes"}->[0] =~ m/^Recursive\sMILP\s([^)]+)/) {
1601                            my @SolutionList = split(/\|/,$1);
1602                            for (my $k=0; $k < @SolutionList; $k++) {
1603                                    if ($SolutionList[$k] =~ m/(\d+):(.+)/) {
1604                                            push(@{$solutionRow->{Solutions}},$2);
1605                                            push(@{$solutions},$2);
1606                                    }
1607                            }
1608                    }
1609            }
1610            $self->figmodel()->database()->save_table($tbl);
1611            $self->releaseModelLock();
1612    
1613            return $solutions;
1614    }
1615    
1616  =head3 datagapfill  =head3 datagapfill
1617  Definition:  Definition:
1618          success()/fail() = FIGMODELmodel->datagapfill();          success()/fail() = FIGMODELmodel->datagapfill();
# Line 1201  Line 1623 
1623          my ($self,$GapFillingRunSpecs,$TansferFileSuffix) = @_;          my ($self,$GapFillingRunSpecs,$TansferFileSuffix) = @_;
1624          my $UniqueFilename = $self->figmodel()->filename();          my $UniqueFilename = $self->figmodel()->filename();
1625          if (defined($GapFillingRunSpecs) && @{$GapFillingRunSpecs} > 0) {          if (defined($GapFillingRunSpecs) && @{$GapFillingRunSpecs} > 0) {
                 print "Gap filling specs:\n".join("\n",@{$GapFillingRunSpecs})."\n\n";  
1626                  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));
   
1627                  #Checking that the solution exists                  #Checking that the solution exists
1628                  if (!-e $self->config("MFAToolkit output directory")->[0].$UniqueFilename."/GapFillingSolutionTable.txt") {                  if (!-e $self->config("MFAToolkit output directory")->[0].$UniqueFilename."/GapFillingSolutionTable.txt") {
1629                          $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 1633 
1633                  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);
1634                  if (defined($TansferFileSuffix)) {                  if (defined($TansferFileSuffix)) {
1635                          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");  
1636                  }                  }
   
1637                  #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
1638                  $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");
1639                  return $GapFillingRunSpecs;                  return $GapFillResultTable;
1640          }          }
1641          if (defined($TansferFileSuffix)) {          if (defined($TansferFileSuffix)) {
1642                  $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 1702 
1702                          push(@{$DirectionArray},$SolutionHash{$ReactionList[$k]});                          push(@{$DirectionArray},$SolutionHash{$ReactionList[$k]});
1703                  }                  }
1704                  print "Integrating solution!\n";                  print "Integrating solution!\n";
1705                  $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);
1706                  my $model = $self->get_model($self->id().$TempVersion);                  $self->PrintModelLPFile();
                 $model->PrintModelLPFile();  
1707                  #Running the model against all available experimental data                  #Running the model against all available experimental data
1708                  print "Running test model!\n";                  print "Running test model!\n";
1709                  my ($FalsePostives,$FalseNegatives,$CorrectNegatives,$CorrectPositives,$Errorvector,$HeadingVector) = $self->RunAllStudiesWithDataFast("All");                  my ($FalsePostives,$FalseNegatives,$CorrectNegatives,$CorrectPositives,$Errorvector,$HeadingVector) = $self->RunAllStudiesWithDataFast("All");
# Line 1322  Line 1739 
1739  =cut  =cut
1740  sub status {  sub status {
1741          my ($self) = @_;          my ($self) = @_;
1742          return $self->{_data}->{status}->[0];          return $self->{_data}->status();
1743  }  }
1744    
1745  =head3 message  =head3 message
# Line 1333  Line 1750 
1750  =cut  =cut
1751  sub message {  sub message {
1752          my ($self) = @_;          my ($self) = @_;
1753          return $self->{_data}->{message}->[0];          return $self->{_data}->message();
1754  }  }
1755    
1756  =head3 set_status  =head3 set_status
# Line 1348  Line 1765 
1765  =cut  =cut
1766  sub set_status {  sub set_status {
1767          my ($self,$NewStatus,$Message) = @_;          my ($self,$NewStatus,$Message) = @_;
1768            $self->{_data}->status($NewStatus);
1769          #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");  
1770          return $self->config("SUCCESS")->[0];          return $self->config("SUCCESS")->[0];
1771  }  }
1772    
# Line 1367  Line 1781 
1781  sub CreateSingleGenomeReactionList {  sub CreateSingleGenomeReactionList {
1782          my ($self,$RunGapFilling) = @_;          my ($self,$RunGapFilling) = @_;
1783    
1784            #Creating directory
1785            if ($self->owner() ne "master" && !-d $self->figmodel()->config("organism directory")->[0].$self->owner()."/") {
1786                    system("mkdir ".$self->figmodel()->config("organism directory")->[0].$self->owner()."/");
1787            } elsif ($self->owner() eq "master" && !-d $self->figmodel()->config("organism directory")->[0].$self->genome()."/") {
1788                    system("mkdir ".$self->figmodel()->config("organism directory")->[0].$self->genome()."/");
1789            }
1790            if ($self->owner() ne "master" && !-d $self->figmodel()->config("organism directory")->[0].$self->owner()."/".$self->genome()."/") {
1791                    system("mkdir ".$self->figmodel()->config("organism directory")->[0].$self->owner()."/".$self->genome()."/");
1792            }
1793    
1794          #Getting genome stats          #Getting genome stats
1795          my $genomestats = $self->figmodel()->get_genome_stats($self->genome());          my $genomestats = $self->figmodel()->get_genome_stats($self->genome());
1796          my $FeatureTable = $self->figmodel()->GetGenomeFeatureTable($self->genome());          my $FeatureTable = $self->figmodel()->GetGenomeFeatureTable($self->genome());
# Line 1381  Line 1805 
1805          }          }
1806          #Setting up needed variables          #Setting up needed variables
1807          my $OriginalModelTable = undef;          my $OriginalModelTable = undef;
1808          #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) {  
1809                  $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");  
1810                  return $self->fail();                  return $self->fail();
1811          }elsif ($Row->{status}->[0] == 1) {          }elsif ($self->status() == 1) {
1812                  $OriginalModelTable = $self->reaction_table();                  $OriginalModelTable = $self->reaction_table();
1813                  $self->ArchiveModel();                  $self->set_status(0,"Rebuilding preliminary reconstruction");
                 $Row->{status}->[0] = 0;  
                 $Row->{message}->[0] = "Rebuilding preliminary reconstruction";  
1814          } else {          } else {
1815                  $Row->{status}->[0] = 0;                  $self->set_status(0,"Preliminary reconstruction");
                 $Row->{message}->[0] = "Preliminary reconstruction";  
1816          }          }
         #Updating the status table  
         $self->figmodel()->database()->save_table($ModelTable);  
         $self->figmodel()->database()->UnlockDBTable("MODELS");  
1817          #Sorting GenomeData by gene location on the chromosome          #Sorting GenomeData by gene location on the chromosome
1818            my $ftrTbl = $self->figmodel()->database()->get_table("ROLERXNMAPPING");
1819          $FeatureTable->sort_rows("MIN LOCATION");          $FeatureTable->sort_rows("MIN LOCATION");
1820          my ($ComplexHash,$SuggestedMappings,$UnrecognizedReactions,$ReactionHash);          my ($ComplexHash,$SuggestedMappings,$UnrecognizedReactions,$ReactionHash);
1821          my %LastGenePosition;          my %LastGenePosition;
# Line 1476  Line 1887 
1887                          }                          }
1888                  }                  }
1889          }          }
   
1890          #Creating nonadjacent complexes          #Creating nonadjacent complexes
1891          my @ReactionList = keys(%{$ReactionHash});          my @ReactionList = keys(%{$ReactionHash});
1892          foreach my $Reaction (@ReactionList) {          foreach my $Reaction (@ReactionList) {
# Line 1582  Line 1992 
1992                  $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"]});
1993          }          }
1994    
1995            #Getting feature rows for features that are lumped
1996            my @rows = $ftrTbl->get_rows_by_key("2","MASTER");
1997            for (my $i=0; $i < @rows; $i++) {
1998                    my $rxn = $rows[$i]->{REACTION}->[0];
1999                    my $role = $rows[$i]->{ROLE}->[0];
2000                    my @orgrows = $FeatureTable->get_rows_by_key($role,"ROLES");
2001                    my $genes;
2002                    for (my $j=0; $j < @orgrows; $j++) {
2003                            if ($orgrows[$j]->{ID}->[0] =~ m/(peg\.\d+)/) {
2004                                    push(@{$genes},$1);
2005                            }
2006                    }
2007                    if (defined($genes) && @{$genes} > 0) {
2008                            my $row = $NewModelTable->get_row_by_key($rxn,"LOAD");
2009                            my $newGeneAssociations;
2010                            for (my $k=0; $k < @{$genes}; $k++) {
2011                                    for (my $j=0; $j < @{$row->{"ASSOCIATED PEG"}}; $j++) {
2012                                            my $peg = $genes->[$k];
2013                                            if ($row->{"ASSOCIATED PEG"}->[$j] !~ m/$peg/) {
2014                                                    push(@{$newGeneAssociations},$row->{"ASSOCIATED PEG"}->[$j]."+".$peg);
2015                                            }
2016                                    }
2017                            }
2018                            $row->{"ASSOCIATED PEG"} = $newGeneAssociations;
2019                    }
2020            }
2021    
2022          #Adding the spontaneous and universal reactions          #Adding the spontaneous and universal reactions
2023          foreach my $ReactionID (@{$self->config("spontaneous reactions")}) {          foreach my $ReactionID (@{$self->config("spontaneous reactions")}) {
2024                  #Getting the thermodynamic reversibility from the database                  #Getting the thermodynamic reversibility from the database
# Line 1601  Line 2038 
2038          }          }
2039    
2040          #Checking if a biomass reaction already exists          #Checking if a biomass reaction already exists
2041          my $BiomassReactionRow = $self->figmodel()->database()->get_row_by_key("BIOMASS TABLE",$self->id(),"MODELS");          my $BiomassReactionRow = $self->BuildSpecificBiomassReaction();
         if (!defined($BiomassReactionRow)) {  
                 $BiomassReactionRow = $self->BuildSpecificBiomassReaction();  
2042                  if (!defined($BiomassReactionRow)) {                  if (!defined($BiomassReactionRow)) {
2043                          $self->set_status(-2,"Preliminary reconstruction failed: could not generate biomass reaction");                          $self->set_status(-2,"Preliminary reconstruction failed: could not generate biomass reaction");
2044                          $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()."!");
2045                          return $self->fail();                          return $self->fail();
2046                  }                  }
         }  
2047          my $ReactionList = $BiomassReactionRow->{"ESSENTIAL REACTIONS"};          my $ReactionList = $BiomassReactionRow->{"ESSENTIAL REACTIONS"};
2048          push(@{$ReactionList},$BiomassReactionRow->{DATABASE}->[0]);          push(@{$ReactionList},$BiomassReactionRow->{DATABASE}->[0]);
2049    
# Line 1641  Line 2075 
2075                  }                  }
2076          }          }
2077    
2078            #If an original model exists, we copy the gap filling solution from that model
2079            if (defined($OriginalModelTable)) {
2080                    for (my $i=0; $i < $OriginalModelTable->size(); $i++) {
2081                            if ($OriginalModelTable->get_row($i)->{"ASSOCIATED PEG"}->[0] =~ m/GAP/ && $OriginalModelTable->get_row($i)->{"ASSOCIATED PEG"}->[0] ne "INITIAL GAP FILLING") {
2082                                    my $Row = $NewModelTable->get_row_by_key($OriginalModelTable->get_row($i)->{"LOAD"}->[0],"LOAD");
2083                                    if (!defined($Row)) {
2084                                            $NewModelTable->add_row($OriginalModelTable->get_row($i));
2085                                    }
2086                            }
2087                    }
2088            }
2089    
2090          #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
2091          if (defined($OriginalModelTable)) {          if (defined($OriginalModelTable)) {
2092                  my $PerfectMatch = 1;                  my $PerfectMatch = 1;
# Line 1700  Line 2146 
2146          #Saving the new model to file          #Saving the new model to file
2147          $self->set_status(1,"Preliminary reconstruction complete");          $self->set_status(1,"Preliminary reconstruction complete");
2148          $self->figmodel()->database()->save_table($NewModelTable);          $self->figmodel()->database()->save_table($NewModelTable);
2149          $self->{_reaction_data} = $NewModelTable;          $self->reaction_table(1);
         #Clearing the previous model from the cache  
         $self->figmodel()->ClearDBModel($self->id(),1);  
2150          #Updating the model stats table          #Updating the model stats table
2151          $self->update_stats_for_build();          $self->update_stats_for_build();
2152          $self->PrintSBMLFile();          $self->PrintSBMLFile();
2153            if (defined($OriginalModelTable)) {
2154                    $self->calculate_model_changes($OriginalModelTable,"REBUILD");
2155            }
2156    
2157          #Adding model to gapfilling queue          #Adding model to gapfilling queue
2158          if (defined($RunGapFilling) && $RunGapFilling == 1) {          if (defined($RunGapFilling) && $RunGapFilling == 1) {
# Line 1724  Line 2171 
2171    
2172  sub CreateMetaGenomeReactionList {  sub CreateMetaGenomeReactionList {
2173          my ($self) = @_;          my ($self) = @_;
   
2174          #Checking if the metagenome file exists          #Checking if the metagenome file exists
2175          if (!-e $self->config("raw MGRAST directory")->[0].$self->genome().".summary") {          if (!-e $self->config("raw MGRAST directory")->[0].$self->genome().".summary") {
2176                  $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());
2177                    return $self->fail();
2178          }          }
2179          #Loading metagenome data          #Loading metagenome data
2180          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");
2181          if (!defined($MGRASTData)) {          if (!defined($MGRASTData)) {
2182                  $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());
2183                    return $self->fail();
2184          }          }
   
2185          #Setting up needed variables          #Setting up needed variables
2186          my $OriginalModelTable = undef;          my $OriginalModelTable = undef;
   
2187          #Checking status          #Checking status
2188          if ($self->status() < 0) {          if ($self->status() < 0) {
2189                  $self->set_status(0,"Preliminary reconstruction");                  $self->set_status(0,"Preliminary reconstruction");
# Line 1749  Line 2195 
2195                  $self->ArchiveModel();                  $self->ArchiveModel();
2196                  $self->set_status(0,"Rebuilding preliminary reconstruction");                  $self->set_status(0,"Rebuilding preliminary reconstruction");
2197          }          }
2198            #Creating a hash of escores and pegs associated with each role
2199            my $rolePegHash;
2200            my $roleEscores;
2201            for (my $i=0; $i < @{$MGRASTData};$i++) {
2202                    #MD5,PEG,number of sims,role,sim e-scores,max escore,min escore,ave escore,stdev escore,ave exponent,stddev exponent
2203                    $rolePegHash->{$MGRASTData->[$i]->[3]}->{substr($MGRASTData->[$i]->[1],4)} = 1;
2204                    push(@{$roleEscores->{$MGRASTData->[$i]->[3]}},split(/;/,$MGRASTData->[$i]->[4]));
2205            }
2206          #Getting the reaction table          #Getting the reaction table
2207          my $ReactionTable = $self->figmodel()->database()->GetDBTable("REACTIONS");          my $ReactionTable = $self->figmodel()->database()->get_table("REACTIONS");
2208          #Creating model table          #Creating model table
2209          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");
2210          for (my $i=0; $i < @{$MGRASTData};$i++) {          print $ModelTable->filename();
2211                  #MD5,PEG,number of sims,role,sim e-scores          my @roles = keys(%{$rolePegHash});
2212                  my $Role = $MGRASTData->[$i]->[3];          for (my $i=0; $i < @roles; $i++) {
2213                  my $MD5 = $MGRASTData->[$i]->[0];                  my $min = -1;
2214                  my $peg = $MGRASTData->[$i]->[1];                  my $max = -1;
2215                  my $sims = $MGRASTData->[$i]->[4];                  my $count = @{$roleEscores->{$roles[$i]}};
2216                  $sims =~ s/;/,/g;                  my $ave = 0;
2217                    my $stdev = 0;
2218                    my $aveexp = 0;
2219                    my $stdevexp = 0;
2220                    for (my $j=0; $j < @{$roleEscores->{$roles[$i]}}; $j++) {
2221                            if ($roleEscores->{$roles[$i]} < $min || $min == -1) {
2222                                    $min = $roleEscores->{$roles[$i]};
2223                            }
2224                            if ($roleEscores->{$roles[$i]} > $max || $max == -1) {
2225                                    $max = $roleEscores->{$roles[$i]};
2226                            }
2227                            $ave += $roleEscores->{$roles[$i]}->[$j];
2228                            if ($roleEscores->{$roles[$i]}->[$j] =~ m/e(-\d+$)/) {
2229                                    $aveexp += $1;
2230                            }
2231                    }
2232                    $ave = $ave/$count;
2233                    $aveexp = $aveexp/$count;
2234                    for (my $j=0; $j < @{$roleEscores->{$roles[$i]}}; $j++) {
2235                            $stdev += ($roleEscores->{$roles[$i]}->[$j]-$ave)*($roleEscores->{$roles[$i]}->[$j]-$ave);
2236                            if ($roleEscores->{$roles[$i]}->[$j] =~ m/e(-\d+$)/) {
2237                                    $stdevexp += ($1-$aveexp)*($1-$aveexp);
2238                            }
2239                    }
2240                    $stdev = sqrt($stdev/$count);
2241                    $stdevexp = sqrt($stdevexp/$count);
2242                  #Checking for subsystems                  #Checking for subsystems
2243                  my $GeneSubsystems = $self->figmodel()->subsystems_of_role($Role);                  my $GeneSubsystems = $self->figmodel()->subsystems_of_role($roles[$i]);
2244                  #Checking if there are reactions associated with this role                  #Checking if there are reactions associated with this role
2245                  my $ReactionHashArrayRef = $self->figmodel()->reactions_of_role($Role);                  my $ReactionHashArrayRef = $self->figmodel()->reactions_of_role($roles[$i]);
2246                  if ($ReactionHashArrayRef != 0) {                  if ($ReactionHashArrayRef != 0) {
2247                          foreach my $Mapping (@{$ReactionHashArrayRef}) {                          foreach my $Mapping (@{$ReactionHashArrayRef}) {
2248                                  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 2254 
2254                                                                  $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"]};
2255                                                                  $ModelTable->add_row($ReactionRow);                                                                  $ModelTable->add_row($ReactionRow);
2256                                                          }                                                          }
2257                                                          push(@{$ReactionRow->{"ASSOCIATED PEG"}},substr($peg,4));                                                          my %pegHash = %{$rolePegHash->{$roles[$i]}};
2258                                                          push(@{$ReactionRow->{"REFERENCE"}},$MD5.":".$Role);                                                          if (defined($ReactionRow->{"ASSOCIATED PEG"})) {
2259                                                          push(@{$ReactionRow->{"CONFIDENCE"}},$sims);                                                                  for (my $j=0; $j < @{$ReactionRow->{"ASSOCIATED PEG"}}; $j++) {
2260                                                                            $pegHash{$ReactionRow->{"ASSOCIATED PEG"}->[$j]} = 1;
2261                                                                    }
2262                                                            }
2263                                                            delete $ReactionRow->{"ASSOCIATED PEG"};
2264                                                            push(@{$ReactionRow->{"ASSOCIATED PEG"}},keys(%pegHash));
2265                                                            push(@{$ReactionRow->{"REFERENCE"}},$count.":".$ave.":".$stdev.":".$aveexp.":".$stdevexp.":".$min.":".$max);
2266                                                          if (defined($GeneSubsystems)) {                                                          if (defined($GeneSubsystems)) {
2267                                                                  push(@{$ReactionRow->{"SUBSYSTEM"}},@{$GeneSubsystems});                                                                  push(@{$ReactionRow->{"SUBSYSTEM"}},@{$GeneSubsystems});
2268                                                          }                                                          }
# Line 1823  Line 2306 
2306          }          }
2307    
2308          #Clearing the previous model from the cache          #Clearing the previous model from the cache
2309          $self->figmodel()->ClearDBModel($self->id(),1);          $self->figmodel()->database()->ClearDBModel($self->id(),1);
2310          $ModelTable->save();          $ModelTable->save();
2311    
2312          return $self->success();          return $self->success();
# Line 1839  Line 2322 
2322  sub ArchiveModel {  sub ArchiveModel {
2323          my ($self) = @_;          my ($self) = @_;
2324    
         #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();  
         }  
   
2325          #Checking that the model file exists          #Checking that the model file exists
2326          if (!(-e $self->filename())) {          if (!(-e $self->filename())) {
2327                  $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 2372 
2372          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
2373  =cut  =cut
2374  sub run_microarray_analysis {  sub run_microarray_analysis {
2375          my ($self,$media,$jobid,$index,$genecall) = @_;          my ($self,$media,$label,$index,$genecall) = @_;
2376          $genecall =~ s/_/:/g;          $genecall =~ s/_/:/g;
2377          $genecall =~ s/\//;/g;          $genecall =~ s/\//;/g;
2378          #print "\n\n".$genecall."\n\n";          my $uniqueFilename = $self->figmodel()->filename();
2379          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";  
2380          system($command);          system($command);
2381          #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";
2382            if (-e $filename) {
2383                    my $output = $self->figmodel()->database()->load_single_column_file($filename);
2384                    if (defined($output->[0])) {
2385                            my @array = split(/;/,$output->[0]);
2386                            $self->figmodel()->clearing_output($uniqueFilename,"MicroarrayAnalysis-".$uniqueFilename.".txt");
2387                            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]);
2388                    }
2389                    print STDERR $filename." is empty!";
2390            }
2391            print STDERR $filename." not found!";
2392            $self->figmodel()->clearing_output($uniqueFilename,"MicroarrayAnalysis-".$uniqueFilename.".txt");
2393    
2394            return undef;
2395  }  }
2396    
2397  =head3 find_minimal_pathways  =head3 find_minimal_pathways
# Line 1912  Line 2401 
2401          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
2402  =cut  =cut
2403  sub find_minimal_pathways {  sub find_minimal_pathways {
2404          my ($self,$media,$objective,$solutionnum) = @_;          my ($self,$media,$objective,$solutionnum,$AllReversible,$additionalexchange) = @_;
2405    
2406          #Setting default media          #Setting default media
2407          if (!defined($media)) {          if (!defined($media)) {
# Line 1924  Line 2413 
2413                  $solutionnum = "5";                  $solutionnum = "5";
2414          }          }
2415    
2416            #Setting additional exchange fluxes
2417            if (!defined($additionalexchange) || length($additionalexchange) == 0) {
2418                    if ($self->id() eq "iAF1260") {
2419                            $additionalexchange = "cpd03422[c]:-100:100;cpd01997[c]:-100:100;cpd11416[c]:-100:0;cpd15378[c]:-100:0;cpd15486[c]:-100:0";
2420                    } else {
2421                            $additionalexchange = $self->figmodel()->config("default exchange fluxes")->[0];
2422                    }
2423            }
2424    
2425          #Translating objective          #Translating objective
2426          my $objectivestring;          my $objectivestring;
2427          if ($objective eq "ALL") {          if ($objective eq "ALL") {
# Line 1944  Line 2442 
2442                          }                          }
2443                  }                  }
2444                  for (my $i=0; $i < @objectives; $i++) {                  for (my $i=0; $i < @objectives; $i++) {
2445                          $self->find_minimal_pathways($media,$objectives[$i])                          $self->find_minimal_pathways($media,$objectives[$i]);
2446                  }                  }
2447                    return;
2448          } elsif ($objective eq "ENERGY") {          } elsif ($objective eq "ENERGY") {
2449                  $objectivestring = "MAX;FLUX;rxn00062;c;1";                  $objectivestring = "MAX;FLUX;rxn00062;c;1";
2450          } elsif ($objective =~ m/cpd\d\d\d\d\d/) {          } elsif ($objective =~ m/cpd\d\d\d\d\d/) {
2451                    if ($objective =~ m/\[(\w)\]/) {
2452                            $objectivestring = "MIN;DRAIN_FLUX;".$objective.";".$1.";1";
2453                            $additionalexchange .= ";".$objective."[".$1."]:-100:0";
2454                    } else {
2455                  $objectivestring = "MIN;DRAIN_FLUX;".$objective.";c;1";                  $objectivestring = "MIN;DRAIN_FLUX;".$objective.";c;1";
2456                            $additionalexchange .= ";".$objective."[c]:-100:0";
2457                    }
2458            } elsif ($objective =~ m/(rxn\d\d\d\d\d)/) {
2459                    my ($Reactants,$Products) = $self->figmodel()->GetReactionSubstrateData($objective);
2460                    for (my $i=0; $i < @{$Products};$i++) {
2461                            my $temp = $Products->[$i]->{"DATABASE"}->[0];
2462                            if ($additionalexchange !~ m/$temp/) {
2463                                    #$additionalexchange .= ";".$temp."[c]:-100:0";
2464                            }
2465                    }
2466                    for (my $i=0; $i < @{$Reactants};$i++) {
2467                            print $Reactants->[$i]->{"DATABASE"}->[0]." started\n";
2468                            $self->find_minimal_pathways($media,$Reactants->[$i]->{"DATABASE"}->[0],$additionalexchange);
2469                            print $Reactants->[$i]->{"DATABASE"}->[0]." done\n";
2470                    }
2471                    return;
2472          }          }
2473    
2474          #Setting additional exchange fluxes          #Adding additional drains
2475          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") {  
2476                  $additionalexchange .= ";cpd15666[c]:0:100";                  $additionalexchange .= ";cpd15666[c]:0:100";
2477          } elsif ($objective eq "cpd11493") {          } elsif ($objective eq "cpd11493" && $additionalexchange !~ m/cpd12370/) {
2478                  $additionalexchange .= ";cpd12370[c]:0:100";                  $additionalexchange .= ";cpd12370[c]:0:100";
2479          } elsif ($objective eq "cpd00166") {          } elsif ($objective eq "cpd00166" && $additionalexchange !~ m/cpd01997/) {
2480                  $additionalexchange .= ";cpd01997[c]:0:100;cpd03422[c]:0:100";                  $additionalexchange .= ";cpd01997[c]:0:100;cpd03422[c]:0:100";
2481          }          }
2482    
2483          #Running MFAToolkit          #Running MFAToolkit
2484          my $filename = $self->figmodel()->filename();          my $filename = $self->figmodel()->filename();
2485          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;
2486            if (defined($AllReversible) && $AllReversible == 1) {
2487                    $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());
2488            } else {
2489                    $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());
2490            }
2491          system($command);          system($command);
2492    
2493          #Loading problem report          #Loading problem report
# Line 1972  Line 2495 
2495          #Clearing output          #Clearing output
2496          $self->figmodel()->clearing_output($filename,"MinimalPathways-".$media."-".$self->id()."-".$objective.".txt");          $self->figmodel()->clearing_output($filename,"MinimalPathways-".$media."-".$self->id()."-".$objective.".txt");
2497          if (!defined($results)) {          if (!defined($results)) {
2498                    print STDERR $objective." pathway results not found!\n";
2499                  return;                  return;
2500          }          }
2501    
# Line 1983  Line 2507 
2507                  @Array = /\d+:([^\|]+)\|/g;                  @Array = /\d+:([^\|]+)\|/g;
2508          }          }
2509    
2510          # Storing data in a figmodel table          #Writing output to file
2511          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();  
2512  }  }
2513    
2514  =head3 calculate_growth  =head3 find_minimal_pathways
2515  Definition:  Definition:
2516          string::growth = FIGMODELmodel->calculate_growth(string:media);          int::status = FIGMODEL->find_minimal_pathways(string::media,string::objective);
2517  Description:  Description:
2518          Calculating growth in the input media          Runs microarray analysis attempting to turn off genes that are inactive in the microarray
2519  =cut  =cut
2520  sub calculate_growth {  sub find_minimal_pathways_two {
2521          my ($self,$Media) = @_;          my ($self,$media,$objective,$solutionnum,$AllReversible,$additionalexchange) = @_;
2522          my $UniqueFilename = $self->figmodel()->filename();  
2523          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
2524          my $ProblemReport = $self->figmodel()->LoadProblemReport($UniqueFilename);          if (!defined($media)) {
2525          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];  
2526                          }                          }
2527    
2528            #Setting default solution number
2529            if (!defined($solutionnum)) {
2530                    $solutionnum = "5";
2531                  }                  }
2532    
2533            #Setting additional exchange fluxes
2534            if (!defined($additionalexchange) || length($additionalexchange) == 0) {
2535                    if ($self->id() eq "iAF1260") {
2536                            $additionalexchange = "cpd03422[c]:-100:100;cpd01997[c]:-100:100;cpd11416[c]:-100:0;cpd15378[c]:-100:0;cpd15486[c]:-100:0";
2537                    } else {
2538                            $additionalexchange = $self->figmodel()->config("default exchange fluxes")->[0];
2539          }          }
         return $Result;  
2540  }  }
2541    
2542  =head3 classify_model_reactions          #Translating objective
2543  Definition:          my $objectivestring;
2544          (FIGMODELTable:Reaction classes,FIGMODELTable:Compound classes) = FIGMODELmodel->classify_model_reactions(string:media);          if ($objective eq "ALL") {
2545  Description:                  #Getting the list of universal building blocks
2546          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");
2547          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});
2548          Possible values for "Class" include:                  #Getting the nonuniversal building blocks
2549          1.) Positive: these reactions are essential in the forward direction.                  my $otherbuildingblocks = $self->config("nonuniversal building blocks");
2550          2.) Negative: these reactions are essential in the reverse direction.                  my @array = keys(%{$otherbuildingblocks});
2551          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]))) {
2552          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];
2553          5.) Variable: these reactions are nonessential and proceed in the forward or reverse direction.                          if (defined($equation)) {
2554          6.) Blocked: these reactions never carry any flux at all in the media condition tested.                                  for (my $i=0; $i < @array; $i++) {
2555          7.) Dead: these reactions are disconnected from the network.                                          if (CORE::index($equation,$array[$i]) > 0) {
2556  =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"]);  
2557          }          }
         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",""));  
2558          }          }
         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",""));  
2559          }          }
         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",""));  
2560          }          }
2561          if (!defined($ReactionTB) && !defined($CompoundTB)) {                  for (my $i=0; $i < @objectives; $i++) {
2562                  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]);
2563                  return (undef,undef);                  }
2564                    return;
2565            } elsif ($objective eq "ENERGY") {
2566                    $objectivestring = "MAX;FLUX;rxn00062;c;1";
2567            } elsif ($objective =~ m/cpd\d\d\d\d\d/) {
2568                    if ($objective =~ m/\[(\w)\]/) {
2569                            $objectivestring = "MIN;DRAIN_FLUX;".$objective.";".$1.";1";
2570                            $additionalexchange .= ";".$objective."[".$1."]:-100:0";
2571                    } else {
2572                            $objectivestring = "MIN;DRAIN_FLUX;".$objective.";c;1";
2573                            $additionalexchange .= ";".$objective."[c]:-100:0";
2574                    }
2575            } elsif ($objective =~ m/(rxn\d\d\d\d\d)/) {
2576                    my ($Reactants,$Products) = $self->figmodel()->GetReactionSubstrateData($objective);
2577                    for (my $i=0; $i < @{$Products};$i++) {
2578                            my $temp = $Products->[$i]->{"DATABASE"}->[0];
2579                            if ($additionalexchange !~ m/$temp/) {
2580                                    #$additionalexchange .= ";".$temp."[c]:-100:0";
2581                            }
2582                    }
2583                    for (my $i=0; $i < @{$Reactants};$i++) {
2584                            print $Reactants->[$i]->{"DATABASE"}->[0]." started\n";
2585                            $self->find_minimal_pathways($media,$Reactants->[$i]->{"DATABASE"}->[0],$additionalexchange);
2586                            print $Reactants->[$i]->{"DATABASE"}->[0]." done\n";
2587                    }
2588                    return;
2589            }
2590    
2591            #Adding additional drains
2592            if (($objective eq "cpd15665" || $objective eq "cpd15667" || $objective eq "cpd15668" || $objective eq "cpd15669") && $additionalexchange !~ m/cpd15666/) {
2593                    $additionalexchange .= ";cpd15666[c]:0:100";
2594            } elsif ($objective eq "cpd11493" && $additionalexchange !~ m/cpd12370/) {
2595                    $additionalexchange .= ";cpd12370[c]:0:100";
2596            } elsif ($objective eq "cpd00166" && $additionalexchange !~ m/cpd01997/) {
2597                    $additionalexchange .= ";cpd01997[c]:0:100;cpd03422[c]:0:100";
2598            }
2599    
2600            #Running MFAToolkit
2601            my $filename = $self->figmodel()->filename();
2602            my $command;
2603            if (defined($AllReversible) && $AllReversible == 1) {
2604                    $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());
2605            } else {
2606                    $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());
2607            }
2608            print $command."\n";
2609            system($command);
2610    
2611            #Loading problem report
2612            my $results = $self->figmodel()->LoadProblemReport($filename);
2613            #Clearing output
2614            $self->figmodel()->clearing_output($filename,"MinimalPathways-".$media."-".$self->id()."-".$objective.".txt");
2615            if (!defined($results)) {
2616                    print STDERR $objective." pathway results not found!\n";
2617                    return;
2618            }
2619    
2620            #Parsing output
2621            my @Array;
2622            my $row = $results->get_row(1);
2623            if (defined($row->{"Notes"}->[0])) {
2624                    $_ = $row->{"Notes"}->[0];
2625                    @Array = /\d+:([^\|]+)\|/g;
2626            }
2627    
2628            #Writing output to file
2629            $self->figmodel()->database()->print_array_to_file($self->directory()."MinimalPathways-".$media."-".$objective."-".$self->id()."-".$AllReversible."-".$self->selected_version().".txt",[join("|",@Array)]);
2630    }
2631    
2632    sub combine_minimal_pathways {
2633            my ($self) = @_;
2634    
2635            my $tbl;
2636            if (-e $self->directory()."MinimalPathwayTable-".$self->id().$self->selected_version().".tbl") {
2637                    $tbl = FIGMODELTable::load_table($self->directory()."MinimalPathwayTable-".$self->id().$self->selected_version().".tbl",";","|",0,["Objective","Media","Reversible"]);
2638            } else {
2639                    $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"],";","|");
2640            }
2641            my @files = glob($self->directory()."MinimalPathways-*");
2642            for (my $i=0; $i < @files;$i++) {
2643                    if ($files[$i] =~ m/MinimalPathways\-(\S+)\-(cpd\d\d\d\d\d)\-(\w+)\-(\d)\-/ || $files[$i] =~ m/MinimalPathways\-(\S+)\-(ENERGY)\-(\w+)\-(\d)\-/) {
2644                            my $reactions = $self->figmodel()->database()->load_single_column_file($files[$i],"");
2645                            if (defined($reactions) && @{$reactions} > 0 && length($reactions->[0]) > 0) {
2646                                    my $newrow = {"Objective"=>[$2],"Media"=>[$1],"Reversible"=>[$4]};
2647                                    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");
2648                                    if (!defined($row)) {
2649                                            $row = $tbl->add_row($newrow);
2650                                    }
2651                                    $row->{Reactions} = $self->figmodel()->database()->load_single_column_file($files[$i],"");
2652                                    delete($row->{"Shortest path"});
2653                                    delete($row->{"Number of essentials"});
2654                                    delete($row->{"Essentials"});
2655                                    delete($row->{"Length"});
2656                                    for (my $j=0; $j < @{$row->{Reactions}}; $j++) {
2657                                            my @array = split(/,/,$row->{Reactions}->[$j]);
2658                                            $row->{"Length"}->[$j] = @array;
2659                                            if (!defined($row->{"Shortest path"}->[0]) || $row->{"Length"}->[$j] < $row->{"Shortest path"}->[0]) {
2660                                                    $row->{"Shortest path"}->[0] = $row->{"Length"}->[$j];
2661                                            }
2662                                            $row->{"Number of essentials"}->[0] = 0;
2663                                            for (my $k=0; $k < @array;$k++) {
2664                                                    if ($array[$k] =~ m/(rxn\d\d\d\d\d)/) {
2665                                                            my $class = $self->get_reaction_class($1,1);
2666                                                            my $temp = $row->{Media}->[0].":Essential";
2667                                                            if ($class =~ m/$temp/) {
2668                                                                    $row->{"Number of essentials"}->[$j]++;
2669                                                                    if (!defined($row->{"Essentials"}->[$j]) && length($row->{"Essentials"}->[$j]) > 0) {
2670                                                                            $row->{"Essentials"}->[$j] = $array[$k];
2671                                                                    } else {
2672                                                                            $row->{"Essentials"}->[$j] .= ",".$array[$k];
2673                                                                    }
2674                                                            }
2675                                                    }
2676                                            }
2677                                    }
2678                            }
2679                    }
2680            }
2681            $tbl->save();
2682    }
2683    
2684    =head3 calculate_growth
2685    Definition:
2686            string::growth = FIGMODELmodel->calculate_growth(string:media);
2687    Description:
2688            Calculating growth in the input media
2689    =cut
2690    sub calculate_growth {
2691            my ($self,$Media,$outputDirectory,$InParameters,$saveLPFile) = @_;
2692            #Setting the Media
2693            if (!defined($Media) || length($Media) == 0) {
2694                    $Media = $self->autocompleteMedia();
2695            }
2696            #Setting parameters for the run
2697            my $DefaultParameters = $self->figmodel()->defaultParameters();
2698            if (defined($InParameters)) {
2699                    my @parameters = keys(%{$InParameters});
2700                    for (my $i=0; $i < @parameters; $i++) {
2701                            $DefaultParameters->{$parameters[$i]} = $InParameters->{$parameters[$i]};
2702                    }
2703            }
2704            $DefaultParameters->{"optimize metabolite production if objective is zero"} = 1;
2705            #Setting filenames
2706            my $UniqueFilename = $self->figmodel()->filename();
2707            if (!defined($outputDirectory)) {
2708                    $outputDirectory = $self->config("database message file directory")->[0];
2709            }
2710            my $fluxFilename = $outputDirectory."Fluxes-".$self->id()."-".$Media.".txt";
2711            my $cpdFluxFilename = $outputDirectory."CompoundFluxes-".$self->id()."-".$Media.".txt";
2712            #Running FBA
2713            #print $self->figmodel()->GenerateMFAToolkitCommandLineCall($UniqueFilename,$self->id(),$Media,["ProductionMFA"],$DefaultParameters,$self->id()."-".$Media."-GrowthTest.txt",undef,$self->selected_version())."\n";
2714            system($self->figmodel()->GenerateMFAToolkitCommandLineCall($UniqueFilename,$self->id(),$Media,["ProductionMFA"],$DefaultParameters,$self->id()."-".$Media."-GrowthTest.txt",undef,$self->selected_version()));
2715            #Saving LP file if requested
2716            if (defined($saveLPFile) && $saveLPFile == 1 && -e $self->figmodel()->{"MFAToolkit output directory"}->[0].$UniqueFilename."/CurrentProblem.lp") {
2717                    system("cp ".$self->figmodel()->config("MFAToolkit output directory")->[0].$UniqueFilename."/CurrentProblem.lp ".$self->directory().$self->id().".lp");
2718            }
2719            my $ProblemReport = $self->figmodel()->LoadProblemReport($UniqueFilename);
2720            my $Result;
2721            if (defined($ProblemReport)) {
2722                    my $Row = $ProblemReport->get_row(0);
2723                    if (defined($Row) && defined($Row->{"Objective"}->[0])) {
2724                            if ($Row->{"Objective"}->[0] < 0.00000001 || $Row->{"Objective"}->[0] == 1e7) {
2725                                    $Result = "NOGROWTH";
2726                                    if (defined($Row->{"Individual metabolites with zero production"}->[0]) && $Row->{"Individual metabolites with zero production"}->[0] =~ m/cpd\d\d\d\d\d/) {
2727                                            $Result .= ":".$Row->{"Individual metabolites with zero production"}->[0];
2728                                    }
2729                            } else {
2730                                    if (-e $self->figmodel()->config("MFAToolkit output directory")->[0].$UniqueFilename."/MFAOutput/SolutionReactionData0.txt") {
2731                                            system("cp ".$self->figmodel()->config("MFAToolkit output directory")->[0].$UniqueFilename."/MFAOutput/SolutionReactionData0.txt ".$fluxFilename);
2732                                            system("cp ".$self->figmodel()->config("MFAToolkit output directory")->[0].$UniqueFilename."/MFAOutput/SolutionCompoundData0.txt ".$cpdFluxFilename);
2733                                    }
2734                                    $Result = $Row->{"Objective"}->[0];
2735                            }
2736                    }
2737            }
2738            #Deleting files if necessary
2739            if ($self->figmodel()->config("preserve all log files")->[0] ne "yes") {
2740                    $self->figmodel()->cleardirectory($UniqueFilename);
2741                    unlink($self->figmodel()->config("database message file directory")->[0].$self->id()."-".$Media."-GrowthTest.txt");
2742            }
2743            #Returning result
2744            return $Result;
2745    }
2746    
2747    =head3 classify_model_reactions
2748    Definition:
2749            (FIGMODELTable:Reaction classes,FIGMODELTable:Compound classes) = FIGMODELmodel->classify_model_reactions(string:media);
2750    Description:
2751            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.
2752            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".
2753            Possible values for "Class" include:
2754            1.) Positive: these reactions are essential in the forward direction.
2755            2.) Negative: these reactions are essential in the reverse direction.
2756            3.) Positive variable: these reactions are nonessential, but they only ever proceed in the forward direction.
2757            4.) Negative variable: these reactions are nonessential, but they only ever proceed in the reverse direction.
2758            5.) Variable: these reactions are nonessential and proceed in the forward or reverse direction.
2759            6.) Blocked: these reactions never carry any flux at all in the media condition tested.
2760            7.) Dead: these reactions are disconnected from the network.
2761    =cut
2762    sub classify_model_reactions {
2763            my ($self,$Media,$SaveChanges) = @_;
2764    
2765            #Getting unique file for printing model output
2766            my $UniqueFilename = $self->figmodel()->filename();
2767            #Running the MFAToolkit
2768            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()));
2769            #Reading in the output bounds file
2770            my ($ReactionTB,$CompoundTB,$DeadCompounds,$DeadEndCompounds,$DeadReactions);
2771            if (-e $self->config("MFAToolkit output directory")->[0].$UniqueFilename."/MFAOutput/TightBoundsReactionData0.txt") {
2772                    $ReactionTB = $self->figmodel()->database()->load_table($self->config("MFAToolkit output directory")->[0].$UniqueFilename."/MFAOutput/TightBoundsReactionData0.txt",";","|",1,["DATABASE ID"]);
2773            }
2774            if (-e $self->config("MFAToolkit output directory")->[0].$UniqueFilename."/MFAOutput/TightBoundsCompoundData0.txt") {
2775                    $CompoundTB = $self->figmodel()->database()->load_table($self->config("MFAToolkit output directory")->[0].$UniqueFilename."/MFAOutput/TightBoundsCompoundData0.txt",";","|",1,["DATABASE ID"]);
2776            }
2777            if (-e $self->config("MFAToolkit output directory")->[0].$UniqueFilename."/DeadReactions.txt") {
2778                    $DeadReactions = $self->figmodel()->put_array_in_hash($self->figmodel()->database()->load_single_column_file($self->config("MFAToolkit output directory")->[0].$UniqueFilename."/DeadReactions.txt",""));
2779            }
2780            if (-e $self->config("MFAToolkit output directory")->[0].$UniqueFilename."/DeadMetabolites.txt") {
2781                    $DeadCompounds = $self->figmodel()->put_array_in_hash($self->figmodel()->database()->load_single_column_file($self->config("MFAToolkit output directory")->[0].$UniqueFilename."/DeadMetabolites.txt",""));
2782            }
2783            if (-e $self->config("MFAToolkit output directory")->[0].$UniqueFilename."/DeadEndMetabolites.txt") {
2784                    $DeadEndCompounds = $self->figmodel()->put_array_in_hash($self->figmodel()->database()->load_single_column_file($self->config("MFAToolkit output directory")->[0].$UniqueFilename."/DeadEndMetabolites.txt",""));
2785            }
2786            if (!defined($ReactionTB) && !defined($CompoundTB)) {
2787                    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";
2788                    return (undef,undef);
2789          }          }
2790    
2791          #Clearing output          #Clearing output
# Line 2123  Line 2847 
2847                                  $CpdRow->{MEDIA}->[$index] = $Media;                                  $CpdRow->{MEDIA}->[$index] = $Media;
2848                          }                          }
2849                  }                  }
2850                    if (!defined($SaveChanges) || $SaveChanges == 1) {
2851                  $cpdclasstable->save();                  $cpdclasstable->save();
2852          }          }
2853            }
2854          if (defined($ReactionTB)) {          if (defined($ReactionTB)) {
2855                  for (my $i=0; $i < $ReactionTB->size(); $i++) {                  for (my $i=0; $i < $ReactionTB->size(); $i++) {
2856                          my $Row = $ReactionTB->get_row($i);                          my $Row = $ReactionTB->get_row($i);
# Line 2179  Line 2905 
2905                                  $RxnRow->{MEDIA}->[$index] = $Media;                                  $RxnRow->{MEDIA}->[$index] = $Media;
2906                          }                          }
2907                  }                  }
2908                    if (!defined($SaveChanges) || $SaveChanges == 1) {
2909                  $rxnclasstable->save();                  $rxnclasstable->save();
2910          }          }
2911            }
2912          return ($rxnclasstable,$cpdclasstable);          return ($rxnclasstable,$cpdclasstable);
2913  }  }
2914    
# Line 2212  Line 2940 
2940    
2941          #Running simulations          #Running simulations
2942          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";  
2943          #Parsing the results          #Parsing the results
2944          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);
2945          if (!defined($Results)) {          if (!defined($Results)) {
# Line 2619  Line 3346 
3346                                          if (length($GapFillingRunSpecs) > 0) {                                          if (length($GapFillingRunSpecs) > 0) {
3347                                                  $GapFillingRunSpecs .= ";";                                                  $GapFillingRunSpecs .= ";";
3348                                          }                                          }
3349                                          $GapFillingRunSpecs .= $HeadingDataArray[2].":".$HeadingDataArray[1].".txt:".$HeadingDataArray[3];                                          $GapFillingRunSpecs .= $HeadingDataArray[2].":".$HeadingDataArray[1].":".$HeadingDataArray[3];
3350                                  } else {                                  } else {
3351                                          $SolutionExistedCount++;                                          $SolutionExistedCount++;
3352                                  }                                  }
# Line 2644  Line 3371 
3371          my $SolutionsFound = 0;          my $SolutionsFound = 0;
3372          my $GapFillingArray;          my $GapFillingArray;
3373          push(@{$GapFillingArray},split(/;/,$GapFillingRunSpecs));          push(@{$GapFillingArray},split(/;/,$GapFillingRunSpecs));
3374          $self->datagapfill($GapFillingArray);          my $GapFillingResults = $self->datagapfill($GapFillingArray,"GFS");
3375            if (defined($GapFillingResults)) {
3376                    $SolutionsFound = 1;
3377            }
3378    
3379          if (defined($RescuedPreviousResults) && @{$RescuedPreviousResults} > 0) {          if (defined($RescuedPreviousResults) && @{$RescuedPreviousResults} > 0) {
3380                  #Printing previous solutions to GFS file                  #Printing previous solutions to GFS file
# Line 2667  Line 3397 
3397          return $self->success();          return $self->success();
3398  }  }
3399    
3400    =head3 SolutionReconciliation
3401    Definition:
3402            FIGMODELmodel->SolutionReconciliation();
3403    Description:
3404            This is a wrapper for running the solution reconciliation algorithm on any model in the database.
3405            The algorithm performs a reconciliation of any gap filling solutions to identify the combination of solutions that results in the optimal model.
3406            This function prints out one output file in the Model directory: ReconciliationOutput.txt: this is a summary of the results of the reconciliation analysis
3407    =cut
3408    
3409    sub SolutionReconciliation {
3410            my ($self,$GapFill,$Stage) = @_;
3411    
3412            #Setting the output filenames
3413            my $OutputFilename;
3414            my $OutputFilenameTwo;
3415            if ($GapFill == 1) {
3416                    $OutputFilename = $self->directory().$self->id().$self->selected_version()."-GFReconciliation.txt";
3417                    $OutputFilenameTwo = $self->directory().$self->id().$self->selected_version()."-GFSRS.txt";
3418            } else {
3419                    $OutputFilename = $self->directory().$self->id().$self->selected_version()."-GGReconciliation.txt";
3420                    $OutputFilenameTwo = $self->directory().$self->id().$self->selected_version()."-GGSRS.txt";
3421            }
3422    
3423            #In stage one, we run the reconciliation and create a test file to check combined solution performance
3424            if (!defined($Stage) || $Stage == 1) {
3425                    my $GrowMatchTable = $self->figmodel()->database()->LockDBTable("GROWMATCH TABLE");
3426                    my $Row = $GrowMatchTable->get_row_by_key($self->genome(),"ORGANISM",1);
3427                    $Row->{"GF RECONCILATION TIMING"}->[0] = time()."-";
3428                    $GrowMatchTable->save();
3429                    $self->figmodel()->database()->UnlockDBTable("GROWMATCH TABLE");
3430    
3431                    #Getting a unique filename
3432                    my $UniqueFilename = $self->figmodel()->filename();
3433    
3434                    #Copying over the necessary files
3435                    if ($GapFill == 1) {
3436                            if (!-e $self->directory().$self->id().$self->selected_version()."-GFEM.txt") {
3437                                    print STDERR "FIGMODEL:SolutionReconciliation:".$self->directory().$self->id().$self->selected_version()."-GFEM.txt file not found. Could not reconcile!";
3438                                    return 0;
3439                            }
3440                            if (!-e $self->directory().$self->id().$self->selected_version()."-OPEM.txt") {
3441                                    print STDERR "FIGMODEL:SolutionReconciliation:".$self->directory().$self->id().$self->selected_version()."-OPEM.txt file not found. Could not reconcile!";
3442                                    return 0;
3443                            }
3444                            system("cp ".$self->directory().$self->id().$self->selected_version()."-GFEM.txt ".$self->figmodel()->config("MFAToolkit input files")->[0].$UniqueFilename."-GFEM.txt");
3445                            system("cp ".$self->directory().$self->id().$self->selected_version()."-OPEM.txt ".$self->figmodel()->config("MFAToolkit input files")->[0].$UniqueFilename."-OPEM.txt");
3446                            #Backing up and deleting the existing reconciliation file
3447                            if (-e $OutputFilename) {
3448                                    system("cp ".$OutputFilename." ".$self->directory().$self->id().$self->selected_version()."-OldGFReconciliation.txt");
3449                                    unlink($OutputFilename);
3450                            }
3451                    } else {
3452                            if (!-e $self->directory().$self->id().$self->selected_version()."-GGEM.txt") {
3453                                    print STDERR "FIGMODEL:SolutionReconciliation:".$self->directory().$self->id().$self->selected_version()."-GGEM.txt file not found. Could not reconcile!";
3454                                    return 0;
3455                            }
3456                            if (!-e $self->directory().$self->id().$self->selected_version()."-GGOPEM.txt") {
3457                                    print STDERR "FIGMODEL:SolutionReconciliation:".$self->directory().$self->id().$self->selected_version()."-GGOPEM.txt file not found. Could not reconcile!";
3458                                    return 0;
3459                            }
3460                            system("cp ".$self->directory().$self->id().$self->selected_version()."-GGEM.txt ".$self->figmodel()->config("MFAToolkit input files")->[0].$UniqueFilename."-GGEM.txt");
3461                            system("cp ".$self->directory().$self->id().$self->selected_version()."-GGOPEM.txt ".$self->figmodel()->config("MFAToolkit input files")->[0].$UniqueFilename."-OPEM.txt");
3462                            #Backing up and deleting the existing reconciliation file
3463                            if (-e $OutputFilename) {
3464                                    system("cp ".$OutputFilename." ".$self->directory().$self->id().$self->selected_version()."-OldGGReconciliation.txt");
3465                                    unlink($OutputFilename);
3466                            }
3467                    }
3468    
3469                    #Running the reconciliation
3470                    system($self->figmodel()->GenerateMFAToolkitCommandLineCall($UniqueFilename,$self->id(),"NONE",["SolutionReconciliation"],{"Solution data for model optimization" => $UniqueFilename},"Reconciliation".$UniqueFilename.".log",undef,$self->selected_version()));
3471                    $GrowMatchTable = $self->figmodel()->database()->LockDBTable("GROWMATCH TABLE");
3472                    $Row = $GrowMatchTable->get_row_by_key($self->genome(),"ORGANISM",1);
3473                    $Row->{"GF RECONCILATION TIMING"}->[0] .= time();
3474                    $GrowMatchTable->save();
3475                    $self->figmodel()->database()->UnlockDBTable("GROWMATCH TABLE");
3476    
3477                    #Loading the problem report from the reconciliation run
3478                    my $ReconciliatonOutput = $self->figmodel()->LoadProblemReport($UniqueFilename);
3479                    print $UniqueFilename."\n";
3480                    #Clearing output files
3481                    $self->figmodel()->clearing_output($UniqueFilename,"Reconciliation".$UniqueFilename.".log");
3482                    $ReconciliatonOutput->save("/home/chenry/Test.txt");
3483    
3484                    #Checking the a problem report was found and was loaded
3485                    if (!defined($ReconciliatonOutput) || $ReconciliatonOutput->size() < 1 || !defined($ReconciliatonOutput->get_row(0)->{"Notes"}->[0])) {
3486                            print STDERR "FIGMODEL:SolutionReconciliation: MFAToolkit output from SolutionReconciliation of ".$self->id()." not found!\n\n";
3487                            return 0;
3488                    }
3489    
3490                    #Processing the solutions
3491                    my $SolutionCount = 0;
3492                    my $ReactionSetHash;
3493                    my $SingleReactionHash;
3494                    my $ReactionDataHash;
3495                    for (my $n=0; $n < $ReconciliatonOutput->size(); $n++) {
3496                            if (defined($ReconciliatonOutput->get_row($n)->{"Notes"}->[0]) && $ReconciliatonOutput->get_row($n)->{"Notes"}->[0] =~ m/^Recursive\sMILP\s([^;]+)/) {
3497                                    #Breaking up the solution into reaction sets
3498                                    my @ReactionSets = split(/\|/,$1);
3499                                    #Creating reaction lists for each set
3500                                    my $SolutionHash;
3501                                    for (my $i=0; $i < @ReactionSets; $i++) {
3502                                            if (length($ReactionSets[$i]) > 0) {
3503                                                    my @Alternatives = split(/:/,$ReactionSets[$i]);
3504                                                    for (my $j=1; $j < @Alternatives; $j++) {
3505                                                            if (length($Alternatives[$j]) > 0) {
3506                                                                    push(@{$SolutionHash->{$Alternatives[$j]}},$Alternatives[0]);
3507                                                            }
3508                                                    }
3509                                                    if (@Alternatives == 1) {
3510                                                            $SingleReactionHash->{$Alternatives[0]}->{$SolutionCount} = 1;
3511                                                            if (!defined($SingleReactionHash->{$Alternatives[0]}->{"COUNT"})) {
3512                                                                    $SingleReactionHash->{$Alternatives[0]}->{"COUNT"} = 0;
3513                                                            }
3514                                                            $SingleReactionHash->{$Alternatives[0]}->{"COUNT"}++;
3515                                                    }
3516                                            }
3517                                    }
3518                                    #Identifying reactions sets and storing the sets in the reactions set hash
3519                                    foreach my $Solution (keys(%{$SolutionHash})) {
3520                                            my $SetKey = join(",",sort(@{$SolutionHash->{$Solution}}));
3521                                            if (!defined($ReactionSetHash->{$SetKey}->{$SetKey}->{$SolutionCount})) {
3522                                                    $ReactionSetHash->{$SetKey}->{$SetKey}->{$SolutionCount} = 1;
3523                                                    if (!defined($ReactionSetHash->{$SetKey}->{$SetKey}->{"COUNT"})) {
3524                                                            $ReactionSetHash->{$SetKey}->{$SetKey}->{"COUNT"} = 0;
3525                                                    }
3526                                                    $ReactionSetHash->{$SetKey}->{$SetKey}->{"COUNT"}++;
3527                                            }
3528                                            $ReactionSetHash->{$SetKey}->{$Solution}->{$SolutionCount} = 1;
3529                                            if (!defined($ReactionSetHash->{$SetKey}->{$Solution}->{"COUNT"})) {
3530                                                    $ReactionSetHash->{$SetKey}->{$Solution}->{"COUNT"} = 0;
3531                                            }
3532                                            $ReactionSetHash->{$SetKey}->{$Solution}->{"COUNT"}++;
3533                                    }
3534                                    $SolutionCount++;
3535                            }
3536                    }
3537    
3538                    #Handling the scenario where no solutions were found
3539                    if ($SolutionCount == 0) {
3540                            print STDERR "FIGMODEL:SolutionReconciliation: Reconciliation unsuccessful. No solution found.\n\n";
3541                            return 0;
3542                    }
3543    
3544                    #Printing results without solution performance figures. Also printing solution test file
3545                    open (RECONCILIATION, ">$OutputFilename");
3546                    #Printing the file heading
3547                    print RECONCILIATION "DATABASE;DEFINITION;REVERSIBLITY;DELTAG;DIRECTION;NUMBER OF SOLUTIONS";
3548                    for (my $i=0; $i < $SolutionCount; $i++) {
3549                            print RECONCILIATION ";Solution ".$i;
3550                    }
3551                    print RECONCILIATION "\n";
3552                    #Printing the singlet reactions first
3553                    my $Solutions;
3554                    print RECONCILIATION "SINGLET REACTIONS\n";
3555                    my @SingletReactions = keys(%{$SingleReactionHash});
3556                    for (my $j=0; $j < $SolutionCount; $j++) {
3557                            $Solutions->[$j]->{"BASE"} = $j;
3558                    }
3559                    for (my $i=0; $i < @SingletReactions; $i++) {
3560                            my $ReactionData;
3561                            if (defined($ReactionDataHash->{$SingletReactions[$i]})) {
3562                                    $ReactionData = $ReactionDataHash->{$SingletReactions[$i]};
3563                            } else {
3564                                    my $Direction = substr($SingletReactions[$i],0,1);
3565                                    if ($Direction eq "+") {
3566                                            $Direction = "=>";
3567                                    } else {
3568                                            $Direction = "<=";
3569                                    }
3570                                    my $Reaction = substr($SingletReactions[$i],1);
3571                                    $ReactionData = FIGMODELObject->load($self->figmodel()->config("reaction directory")->[0].$Reaction,"\t");
3572                                    $ReactionData->{"DIRECTIONS"}->[0] = $Direction;
3573                                    $ReactionData->{"REACTIONS"}->[0] = $Reaction;
3574                                    if (!defined($ReactionData->{"DEFINITION"}->[0])) {
3575                                            $ReactionData->{"DEFINITION"}->[0] = "UNKNOWN";
3576                                    }
3577                                    if (!defined($ReactionData->{"THERMODYNAMIC REVERSIBILITY"}->[0])) {
3578                                            $ReactionData->{"THERMODYNAMIC REVERSIBILITY"}->[0] = "UNKNOWN";
3579                                    }
3580                                    if (!defined($ReactionData->{"DELTAG"}->[0])) {
3581                                            $ReactionData->{"DELTAG"}->[0] = "UNKNOWN";
3582                                    }
3583                                    $ReactionDataHash->{$SingletReactions[$i]} = $ReactionData;
3584                            }
3585                            print RECONCILIATION $ReactionData->{"REACTIONS"}->[0].";".$ReactionData->{"DEFINITION"}->[0].";".$ReactionData->{"THERMODYNAMIC REVERSIBILITY"}->[0].";".$ReactionData->{"DELTAG"}->[0].";".$ReactionData->{"DIRECTIONS"}->[0].";".$SingleReactionHash->{$SingletReactions[$i]}->{"COUNT"};
3586                            for (my $j=0; $j < $SolutionCount; $j++) {
3587                                    print RECONCILIATION ";";
3588                                    if (defined($SingleReactionHash->{$SingletReactions[$i]}->{$j})) {
3589                                            $Solutions->[$j]->{$SingletReactions[$i]} = 1;
3590                                            $Solutions->[$j]->{"BASE"} = $j;
3591                                            print RECONCILIATION "|".$j."|";
3592                                    }
3593                            }
3594                            print RECONCILIATION "\n";
3595                    }
3596                    #Printing the reaction sets with alternatives
3597                    print RECONCILIATION "Reaction sets with alternatives\n";
3598                    my @ReactionSets = keys(%{$ReactionSetHash});
3599                    foreach my $ReactionSet (@ReactionSets) {
3600                            my $NewSolutions;
3601                            my $BaseReactions;
3602                            my $AltList = [$ReactionSet];
3603                            push(@{$AltList},keys(%{$ReactionSetHash->{$ReactionSet}}));
3604                            for (my $j=0; $j < @{$AltList}; $j++) {
3605                                    my $CurrentNewSolutions;
3606                                    my $Index;
3607                                    if ($j == 0) {
3608                                            print RECONCILIATION "NEW SET\n";
3609                                    } elsif ($AltList->[$j] ne $ReactionSet) {
3610                                            print RECONCILIATION "ALTERNATIVE SET\n";
3611                                            #For each base solution in which this set is represented, we copy the base solution to the new solution
3612                                            my $NewSolutionCount = 0;
3613                                            for (my $k=0; $k < $SolutionCount; $k++) {
3614                                                    if (defined($ReactionSetHash->{$ReactionSet}->{$AltList->[$j]}->{$k})) {
3615                                                            if (defined($Solutions)) {
3616                                                                    $Index->{$k} = @{$Solutions} + $NewSolutionCount;
3617                                                            } else {
3618                                                                    $Index->{$k} = $NewSolutionCount;
3619                                                            }
3620                                                            if (defined($NewSolutions) && @{$NewSolutions} > 0) {
3621                                                                    $Index->{$k} += @{$NewSolutions};
3622                                                            }
3623                                                            $CurrentNewSolutions->[$NewSolutionCount] = {};
3624                                                            foreach my $Reaction (keys(%{$Solutions->[$k]})) {
3625                                                                    $CurrentNewSolutions->[$NewSolutionCount]->{$Reaction} = $Solutions->[$k]->{$Reaction};
3626                                                            }
3627                                                            $NewSolutionCount++;
3628                                                    }
3629                                            }
3630                                    }
3631                                    if ($j == 0 || $AltList->[$j] ne $ReactionSet) {
3632                                            my @SingletReactions = split(/,/,$AltList->[$j]);
3633                                            for (my $i=0; $i < @SingletReactions; $i++) {
3634                                                    #Adding base reactions to base solutions and set reactions the new solutions
3635                                                    if ($j == 0) {
3636                                                            push(@{$BaseReactions},$SingletReactions[$i]);
3637                                                    } else {
3638                                                            for (my $k=0; $k < @{$CurrentNewSolutions}; $k++) {
3639                                                                    $CurrentNewSolutions->[$k]->{$SingletReactions[$i]} = 1;
3640                                                            }
3641                                                    }
3642                                                    #Getting reaction data and printing reaction in output file
3643                                                    my $ReactionData;
3644                                                    if (defined($ReactionDataHash->{$SingletReactions[$i]})) {
3645                                                            $ReactionData = $ReactionDataHash->{$SingletReactions[$i]};
3646                                                    } else {
3647                                                            my $Direction = substr($SingletReactions[$i],0,1);
3648                                                            if ($Direction eq "+") {
3649                                                                    $Direction = "=>";
3650                                                            } else {
3651                                                                    $Direction = "<=";
3652                                                            }
3653                                                            my $Reaction = substr($SingletReactions[$i],1);
3654                                                            $ReactionData = FIGMODELObject->load($self->figmodel()->config("reaction directory")->[0].$Reaction,"\t");
3655                                                            $ReactionData->{"DIRECTIONS"}->[0] = $Direction;
3656                                                            $ReactionData->{"REACTIONS"}->[0] = $Reaction;
3657                                                            if (!defined($ReactionData->{"DEFINITION"}->[0])) {
3658                                                                    $ReactionData->{"DEFINITION"}->[0] = "UNKNOWN";
3659                                                            }
3660                                                            if (!defined($ReactionData->{"THERMODYNAMIC REVERSIBILITY"}->[0])) {
3661                                                                    $ReactionData->{"THERMODYNAMIC REVERSIBILITY"}->[0] = "UNKNOWN";
3662                                                            }
3663                                                            if (!defined($ReactionData->{"DELTAG"}->[0])) {
3664                                                                    $ReactionData->{"DELTAG"}->[0] = "UNKNOWN";
3665                                                            }
3666                                                            $ReactionDataHash->{$SingletReactions[$i]} = $ReactionData;
3667                                                    }
3668                                                    print RECONCILIATION $ReactionData->{"REACTIONS"}->[0].";".$ReactionData->{"DEFINITION"}->[0].";".$ReactionData->{"THERMODYNAMIC REVERSIBILITY"}->[0].";".$ReactionData->{"DELTAG"}->[0].";".$ReactionData->{"DIRECTIONS"}->[0].";".$ReactionSetHash->{$ReactionSet}->{$AltList->[$j]}->{"COUNT"};
3669                                                    for (my $k=0; $k < $SolutionCount; $k++) {
3670                                                            print RECONCILIATION ";";
3671                                                            if (defined($ReactionSetHash->{$ReactionSet}->{$AltList->[$j]}->{$k})) {
3672                                                                    if ($j == 0) {
3673                                                                            print RECONCILIATION "|".$k."|";
3674                                                                    } else {
3675                                                                            print RECONCILIATION "|".$Index->{$k}."|";
3676                                                                    }
3677                                                            }
3678                                                    }
3679                                                    print RECONCILIATION "\n";
3680                                            }
3681                                            #Adding the current new solutions to the new solutions array
3682                                            if (defined($CurrentNewSolutions) && @{$CurrentNewSolutions} > 0) {
3683                                                    push(@{$NewSolutions},@{$CurrentNewSolutions});
3684                                            }
3685                                    }
3686                            }
3687                            #Adding the base reactions to all existing solutions
3688                            for (my $j=0; $j < @{$Solutions}; $j++) {
3689                                    if (defined($ReactionSetHash->{$ReactionSet}->{$ReactionSet}->{$Solutions->[$j]->{"BASE"}})) {
3690                                            foreach my $SingleReaction (@{$BaseReactions}) {
3691                                                    $Solutions->[$j]->{$SingleReaction} = 1;
3692                                            }
3693                                    }
3694                            }
3695                            #Adding the new solutions to the set of existing solutions
3696                            push(@{$Solutions},@{$NewSolutions});
3697                    }
3698                    close(RECONCILIATION);
3699                    #Now printing a file that defines all of the solutions in a format the testsolutions function understands
3700                    open (RECONCILIATION, ">$OutputFilenameTwo");
3701                    print RECONCILIATION "Experiment;Solution index;Solution cost;Solution reactions\n";
3702                    for (my $i=0; $i < @{$Solutions}; $i++) {
3703                            delete($Solutions->[$i]->{"BASE"});
3704                            print RECONCILIATION "SR".$i.";".$i.";10;".join(",",keys(%{$Solutions->[$i]}))."\n";
3705                    }
3706                    close(RECONCILIATION);
3707    
3708                    $GrowMatchTable = $self->figmodel()->database()->LockDBTable("GROWMATCH TABLE");
3709                    $Row = $GrowMatchTable->get_row_by_key($self->genome(),"ORGANISM",1);
3710                    $Row->{"GF RECON TESTING TIMING"}->[0] = time()."-";
3711                    $Row->{"GF RECON SOLUTIONS"}->[0] = @{$Solutions};
3712                    $GrowMatchTable->save();
3713                    $self->figmodel()->database()->UnlockDBTable("GROWMATCH TABLE");
3714    
3715                    #Scheduling the solution testing
3716                    if ($GapFill == 1) {
3717                            system($self->figmodel()->config("scheduler executable")->[0]." \"add:testsolutions?".$self->id().$self->selected_version()."?-1?GFSR:BACK:fast:QSUB\"");
3718                    } else {
3719                            system($self->figmodel()->config("scheduler executable")->[0]." \"add:testsolutions?".$self->id().$self->selected_version()."?-1?GGSR:BACK:fast:QSUB\"");
3720                    }
3721            } else {
3722                    #Reading in the solution testing results
3723                    my $Data;
3724                    if ($GapFill == 1) {
3725                            $Data = $self->figmodel()->database()->load_single_column_file($self->directory().$self->id().$self->selected_version()."-GFSREM.txt","");
3726                    } else {
3727                            $Data = $self->figmodel()->database()->load_single_column_file($self->directory().$self->id().$self->selected_version()."-GGSREM.txt","");
3728                    }
3729    
3730                    #Reading in the preliminate reconciliation report
3731                    my $OutputData = $self->figmodel()->database()->load_single_column_file($OutputFilename,"");
3732                    #Replacing the file tags with actual performance data
3733                    my $Count = 0;
3734                    for (my $i=0; $i < @{$Data}; $i++) {
3735                            if ($Data->[$i] =~ m/^SR(\d+);.+;(\d+\/\d+);/) {
3736                                    my $Index = $1;
3737                                    my $Performance = $Index."/".$2;
3738                                    for (my $j=0; $j < @{$OutputData}; $j++) {
3739                                            $OutputData->[$j] =~ s/\|$Index\|/$Performance/g;
3740                                    }
3741                            }
3742                    }
3743                    $self->figmodel()->database()->print_array_to_file($OutputFilename,$OutputData);
3744    
3745                    my $GrowMatchTable = $self->figmodel()->database()->LockDBTable("GROWMATCH TABLE");
3746                    my $Row = $GrowMatchTable->get_row_by_key($self->genome(),"ORGANISM",1);
3747                    $Row->{"GF RECON TESTING TIMING"}->[0] .= time();
3748                    $GrowMatchTable->save();
3749                    $self->figmodel()->database()->UnlockDBTable("GROWMATCH TABLE");
3750            }
3751    
3752            return 1;
3753    }
3754    
3755  =head3 BuildSpecificBiomassReaction  =head3 BuildSpecificBiomassReaction
3756  Definition:  Definition:
3757          FIGMODELmodel->BuildSpecificBiomassReaction();          FIGMODELmodel->BuildSpecificBiomassReaction();
# Line 2679  Line 3764 
3764          my $OrganismID = $self->genome();          my $OrganismID = $self->genome();
3765          #Checking for a biomass override          #Checking for a biomass override
3766          if (defined($self->config("biomass reaction override")->{$OrganismID})) {          if (defined($self->config("biomass reaction override")->{$OrganismID})) {
3767                  $biomassrxn = $self->config("biomass reaction override")->{$OrganismID};                  my $biomassID = $self->config("biomass reaction override")->{$OrganismID};
3768                  print "Overriding biomass template and selecting ".$biomassrxn." for ".$OrganismID.".\n";                  my $tbl = $self->database()->get_table("BIOMASS",1);
3769                    $biomassrxn = $tbl->get_row_by_key($biomassID,"DATABASE");
3770                    print "Overriding biomass template and selecting ".$biomassID." for ".$OrganismID.".\n";
3771          } else {#Creating biomass reaction from the template          } else {#Creating biomass reaction from the template
3772                  #Getting the genome stats                  #Getting the genome stats
3773                  my $genomestats = $self->figmodel()->get_genome_stats($self->genome());                  my $genomestats = $self->figmodel()->get_genome_stats($self->genome());
# Line 2971  Line 4058 
4058    
4059                  #Adding the biomass equation to the biomass table                  #Adding the biomass equation to the biomass table
4060                  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());
4061                  $biomassrxn = $NewRow->{DATABASE}->[0];                  $biomassrxn = $NewRow;
                 print $biomassrxn."\n";  
4062          }          }
4063          print $biomassrxn."\n";          return $biomassrxn;
         my $BiomassRow = $self->figmodel()->add_model_to_biomass_reaction($biomassrxn,$self->id());  
         return $BiomassRow;  
4064  }  }
4065    
4066  =head3 PrintSBMLFile  =head3 PrintSBMLFile
# Line 2989  Line 4073 
4073          my($self) = @_;          my($self) = @_;
4074    
4075          #Opening the SBML file for printing          #Opening the SBML file for printing
4076          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";  
         }  
4077          if (!open (SBMLOUTPUT, ">$Filename")) {          if (!open (SBMLOUTPUT, ">$Filename")) {
4078                  return;                  return;
4079          }          }
4080    
4081          #Loading and parsing the model data          #Loading and parsing the model data
4082          my $ModelTable = $self->reaction_table();          my $mdlTbl = $self->reaction_table();
4083          if (!defined($ModelTable) || !defined($ModelTable->{"array"})) {          if (!defined($mdlTbl) || !defined($mdlTbl->{"array"})) {
4084                  print "Failed to load ".$self->id()."\n";                  return $self->fail();
                 return;  
4085          }          }
4086            my $rxnTbl = $self->figmodel()->database()->get_table("REACTIONS");
4087            my $bioTbl = $self->figmodel()->database()->get_table("BIOMASS");
4088            my $cpdTbl = $self->figmodel()->database()->get_table("COMPOUNDS");
4089            my $cmpTbl = $self->figmodel()->database()->get_table("COMPARTMENTS");
4090    
4091          #Adding intracellular metabolites that also need exchange fluxes to the exchange hash          #Adding intracellular metabolites that also need exchange fluxes to the exchange hash
4092          my $ExchangeHash = {"cpd11416" => "c"};          my $ExchangeHash = {"cpd11416" => "c"};
   
4093          my %CompartmentsPresent;          my %CompartmentsPresent;
4094          $CompartmentsPresent{"c"} = 1;          $CompartmentsPresent{"c"} = 1;
4095          my %CompoundList;          my %CompoundList;
4096          my @ReactionList;          my @ReactionList;
4097          my $ReactionTable = $self->figmodel()->database()->GetDBTable("REACTIONS");          for (my $i=0; $i < $mdlTbl->size(); $i++) {
4098          for (my $i=0; $i < $ModelTable->size(); $i++) {                  my $Reaction = $mdlTbl->get_row($i)->{"LOAD"}->[0];
4099                  my $Reaction = $ModelTable->get_row($i)->{"LOAD"}->[0];                  my $row = $rxnTbl->get_row_by_key($Reaction,"DATABASE");
4100                  if (defined($ReactionTable->get_row_by_key($Reaction,"DATABASE")) && defined($ReactionTable->get_row_by_key($Reaction,"DATABASE")->{"EQUATION"}->[0])) {                  if (!defined($row)) {
4101                            $row = $bioTbl->get_row_by_key($Reaction,"DATABASE");
4102                            if (!defined($row)) {
4103                                    next;
4104                            }
4105                    }
4106                    if (!defined($row->{"EQUATION"}->[0])) {
4107                            next;
4108                    }
4109                          push(@ReactionList,$Reaction);                          push(@ReactionList,$Reaction);
4110                          $_ = $ReactionTable->get_row_by_key($Reaction,"DATABASE")->{"EQUATION"}->[0];                  $_ = $row->{"EQUATION"}->[0];
4111                          my @MatchArray = /(cpd\d\d\d\d\d)/g;                          my @MatchArray = /(cpd\d\d\d\d\d)/g;
4112                          for (my $j=0; $j < @MatchArray; $j++) {                          for (my $j=0; $j < @MatchArray; $j++) {
4113                                  $CompoundList{$MatchArray[$j]}->{"c"} = 1;                                  $CompoundList{$MatchArray[$j]}->{"c"} = 1;
4114                          }                          }
4115                          $_ = $ReactionTable->get_row_by_key($Reaction,"DATABASE")->{"EQUATION"}->[0];                  $_ = $row->{"EQUATION"}->[0];
4116                          @MatchArray = /(cpd\d\d\d\d\d\[\D\])/g;                          @MatchArray = /(cpd\d\d\d\d\d\[\D\])/g;
4117                          for (my $j=0; $j < @MatchArray; $j++) {                          for (my $j=0; $j < @MatchArray; $j++) {
4118                                  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 4121 
4121                                  }                                  }
4122                          }                          }
4123                  }                  }
         }  
4124    
4125          #Printing header to SBML file          #Printing header to SBML file
4126          my $ModelName = $self->id();          my $ModelName = $self->id().$self->selected_version();
4127          $ModelName =~ s/\./_/;          $ModelName =~ s/\./_/;
4128          print SBMLOUTPUT '<?xml version="1.0" encoding="UTF-8"?>'."\n";          print SBMLOUTPUT '<?xml version="1.0" encoding="UTF-8"?>'."\n";
4129      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";
4130      if (defined($self->figmodel()->database()->GetDBTable("MODEL STATS")->{$self->id()}->[0]->{"Organism name"}->[0])) {          if (defined($self->name())) {
4131          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";
4132      } else {      } else {
4133          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";
4134      }      }
4135    
4136          #Printing the unit data          #Printing the unit data
# Line 3060  Line 4147 
4147      #Printing compartments for SBML file      #Printing compartments for SBML file
4148      print SBMLOUTPUT '<listOfCompartments>'."\n";      print SBMLOUTPUT '<listOfCompartments>'."\n";
4149      foreach my $Compartment (keys(%CompartmentsPresent)) {      foreach my $Compartment (keys(%CompartmentsPresent)) {
4150          if (defined($self->figmodel()->database()->GetDBTable("COMPARTMENTS")->{$Compartment}->[0]->{"Name"}->[0])) {                  my $row = $cmpTbl->get_row_by_key($Compartment,"Abbreviation");
4151                  my @OutsideList = split(/\//,$self->figmodel()->database()->GetDBTable("COMPARTMENTS")->{$Compartment}->[0]->{"Outside"}->[0]);                  if (!defined($row) && !defined($row->{"Name"}->[0])) {
4152                            next;
4153                    }
4154                    my @OutsideList = split(/\//,$row->{"Outside"}->[0]);
4155                  my $Printed = 0;                  my $Printed = 0;
4156                  foreach my $Outside (@OutsideList) {                  foreach my $Outside (@OutsideList) {
4157                                  if (defined($CompartmentsPresent{$Outside}) && defined($self->figmodel()->database()->GetDBTable("COMPARTMENTS")->{$Outside}->[0]->{"Name"}->[0])) {                          if (defined($CompartmentsPresent{$Outside}) && defined($row->{"Name"}->[0])) {
4158                                  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";
4159                                  $Printed = 1;                                  $Printed = 1;
4160                                  last;                                  last;
4161                          }                          }
4162                  }                  }
4163                  if ($Printed eq 0) {                  if ($Printed eq 0) {
4164                          print SBMLOUTPUT '<compartment id="'.$self->figmodel()->database()->GetDBTable("COMPARTMENTS")->{$Compartment}->[0]->{"Name"}->[0].'"/>'."\n";                          print SBMLOUTPUT '<compartment id="'.$row->{"Name"}->[0].'"/>'."\n";
                         }  
4165          }          }
4166      }      }
4167      print SBMLOUTPUT '</listOfCompartments>'."\n";      print SBMLOUTPUT '</listOfCompartments>'."\n";
# Line 3080  Line 4169 
4169      #Printing the list of metabolites involved in the model      #Printing the list of metabolites involved in the model
4170          print SBMLOUTPUT '<listOfSpecies>'."\n";          print SBMLOUTPUT '<listOfSpecies>'."\n";
4171      foreach my $Compound (keys(%CompoundList)) {      foreach my $Compound (keys(%CompoundList)) {
4172                    my $row = $cpdTbl->get_row_by_key($Compound,"DATABASE");
4173                    if (!defined($row)) {
4174                            next;
4175                    }
4176          my $Name = $Compound;          my $Name = $Compound;
4177                  my $Formula = "";                  my $Formula = "";
4178                  if (defined($self->figmodel()->database()->GetDBTable("COMPOUNDS")->{$Compound}->[0]->{"FORMULA"}->[0])) {                  if (defined($row->{"FORMULA"}->[0])) {
4179                          $Formula = $self->figmodel()->database()->GetDBTable("COMPOUNDS")->{$Compound}->[0]->{"FORMULA"}->[0];                          $Formula = $row->{"FORMULA"}->[0];
4180                  }                  }
4181                  if (defined($self->figmodel()->database()->GetDBTable("COMPOUNDS")->{$Compound}->[0]->{"NAME"}->[0])) {                  if (defined($row->{"NAME"}->[0])) {
4182                          $Name = $self->figmodel()->database()->GetDBTable("COMPOUNDS")->{$Compound}->[0]->{"NAME"}->[0];                          $Name = $row->{"NAME"}->[0];
4183                          $Name =~ s/\s/_/;                          $Name =~ s/\s/_/;
4184                          $Name .= "_".$Formula;                          $Name .= "_".$Formula;
4185                  }                  }
4186                  $Name =~ s/[<>;&\*]//;                  $Name =~ s/[<>;&\*]//;
4187                  my $Charge = 0;                  my $Charge = 0;
4188                  if (defined($self->figmodel()->database()->GetDBTable("COMPOUNDS")->{$Compound}->[0]->{"CHARGE"}->[0])) {                  if (defined($row->{"CHARGE"}->[0])) {
4189                          $Charge = $self->figmodel()->database()->GetDBTable("COMPOUNDS")->{$Compound}->[0]->{"CHARGE"}->[0];                          $Charge = $row->{"CHARGE"}->[0];
4190                  }                  }
4191                  foreach my $Compartment (keys(%{$CompoundList{$Compound}})) {                  foreach my $Compartment (keys(%{$CompoundList{$Compound}})) {
4192                  if ($Compartment eq "e") {                  if ($Compartment eq "e") {
4193                          $ExchangeHash->{$Compound} = "e";                          $ExchangeHash->{$Compound} = "e";
4194                  }                  }
4195                  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");
4196                            print SBMLOUTPUT '<species id="'.$Compound.'_'.$Compartment.'" name="'.$Name.'" compartment="'.$cmprow->{"Name"}->[0].'" charge="'.$Charge.'" boundaryCondition="false"/>'."\n";
4197          }          }
4198      }      }
4199    
4200          #Printing the boundary species          #Printing the boundary species
4201          foreach my $Compound (keys(%{$ExchangeHash})) {          foreach my $Compound (keys(%{$ExchangeHash})) {
4202                  my $Name = $Compound;                  my $Name = $Compound;
4203                  my $Formula = "";                  my $Formula = "";
4204                  if (defined($self->figmodel()->database()->GetDBTable("COMPOUNDS")->{$Compound}->[0]->{"FORMULA"}->[0])) {                  my $row = $cpdTbl->get_row_by_key($Compound,"DATABASE");
4205                          $Formula = $self->figmodel()->database()->GetDBTable("COMPOUNDS")->{$Compound}->[0]->{"FORMULA"}->[0];                  if (!defined($row)) {
4206                            next;
4207                  }                  }
4208                  if (defined($self->figmodel()->database()->GetDBTable("COMPOUNDS")->{$Compound}->[0]->{"NAME"}->[0])) {                  if (defined($row->{"FORMULA"}->[0])) {
4209                          $Name = $self->figmodel()->database()->GetDBTable("COMPOUNDS")->{$Compound}->[0]->{"NAME"}->[0];                          $Formula = $row->{"FORMULA"}->[0];
4210                    }
4211                    if (defined($row->{"NAME"}->[0])) {
4212                            $Name = $row->{"NAME"}->[0];
4213                          $Name =~ s/\s/_/;                          $Name =~ s/\s/_/;
4214                          $Name .= "_".$Formula;                          $Name .= "_".$Formula;
4215                  }                  }
4216                  $Name =~ s/[<>;&\*]//;                  $Name =~ s/[<>;&\*]//;
4217                  my $Charge = 0;                  my $Charge = 0;
4218                  if (defined($self->figmodel()->database()->GetDBTable("COMPOUNDS")->{$Compound}->[0]->{"CHARGE"}->[0])) {                  if (defined($row->{"CHARGE"}->[0])) {
4219                          $Charge = $self->figmodel()->database()->GetDBTable("COMPOUNDS")->{$Compound}->[0]->{"CHARGE"}->[0];                          $Charge = $row->{"CHARGE"}->[0];
4220                  }                  }
4221                  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";
4222          }          }
# Line 3126  Line 4225 
4225      #Printing the list of reactions involved in the model      #Printing the list of reactions involved in the model
4226          my $ObjectiveCoef;          my $ObjectiveCoef;
4227      print SBMLOUTPUT '<listOfReactions>'."\n";      print SBMLOUTPUT '<listOfReactions>'."\n";
4228    
4229          foreach my $Reaction (@ReactionList) {          foreach my $Reaction (@ReactionList) {
4230          $ObjectiveCoef = "0.0";          $ObjectiveCoef = "0.0";
4231                  if (defined($self->figmodel()->database()->GetDBTable("REACTIONS")->{$Reaction}->[0]->{"EQUATION"}->[0])) {                  my $mdlrow = $mdlTbl->get_row_by_key($Reaction,"LOAD");
4232                    my $Reaction = $mdlrow->{"LOAD"}->[0];
4233                    my $row = $rxnTbl->get_row_by_key($Reaction,"DATABASE");
4234                    if (!defined($row)) {
4235                            $row = $bioTbl->get_row_by_key($Reaction,"DATABASE");
4236                            if (!defined($row)) {
4237                                    next;
4238                            }
4239                    }
4240                    if (!defined($row->{"EQUATION"}->[0])) {
4241                            next;
4242                    }
4243                  if ($Reaction =~ m/^bio/) {                  if ($Reaction =~ m/^bio/) {
4244                                  $ObjectiveCoef = "1.0";                                  $ObjectiveCoef = "1.0";
4245                          }                          }
4246                          my $LowerBound = -10000;                          my $LowerBound = -10000;
4247                  my $UpperBound = 10000;                  my $UpperBound = 10000;
4248                          my ($Reactants,$Products) = $self->figmodel()->GetReactionSubstrateData($Reaction);                  my ($Reactants,$Products) = $self->figmodel()->GetReactionSubstrateDataFromEquation($row->{"EQUATION"}->[0]);
4249                  my $Name = $Reaction;                  my $Name = $Reaction;
4250                  if (defined($self->figmodel()->database()->GetDBTable("REACTIONS")->{$Reaction}->[0]->{"NAME"}->[0])) {                  if (defined($row->{"NAME"}->[0])) {
4251                          $Name = $self->figmodel()->database()->GetDBTable("REACTIONS")->{$Reaction}->[0]->{"NAME"}->[0];                          $Name = $row->{"NAME"}->[0];
4252                                  $Name =~ s/[<>;&]//g;                                  $Name =~ s/[<>;&]//g;
4253                  }                  }
4254                  my $Reversibility = "true";                  my $Reversibility = "true";
4255                  if (defined($ModelTable->{$Reaction}->[0]->{"DIRECTIONALITY"}->[0])) {                  if (defined($mdlrow->{"DIRECTIONALITY"}->[0])) {
4256                          if ($ModelTable->{$Reaction}->[0]->{"DIRECTIONALITY"}->[0] ne "<=>") {                          if ($mdlrow->{"DIRECTIONALITY"}->[0] ne "<=>") {
4257                                  $LowerBound = 0;                                  $LowerBound = 0;
4258                                          $Reversibility = "false";                                          $Reversibility = "false";
4259                          }                          }
4260                          if ($ModelTable->{$Reaction}->[0]->{"DIRECTIONALITY"}->[0] eq "<=") {                          if ($mdlrow->{"DIRECTIONALITY"}->[0] eq "<=") {
4261                                  my $Temp = $Products;                                  my $Temp = $Products;
4262                                  $Products = $Reactants;                                  $Products = $Reactants;
4263                                  $Reactants = $Temp;                                  $Reactants = $Temp;
# Line 3155  Line 4266 
4266                          print SBMLOUTPUT '<reaction id="'.$Reaction.'" name="'.$Name.'" reversible="'.$Reversibility.'">'."\n";                          print SBMLOUTPUT '<reaction id="'.$Reaction.'" name="'.$Name.'" reversible="'.$Reversibility.'">'."\n";
4267                          print SBMLOUTPUT "<notes>\n";                          print SBMLOUTPUT "<notes>\n";
4268                          my $ECData = "";                          my $ECData = "";
4269                          if (defined($self->figmodel()->database()->GetDBTable("REACTIONS")->{$Reaction}->[0]->{"ENZYME"}->[0])) {                  if (defined($row->{"ENZYME"}->[0])) {
4270                                  $ECData = $self->figmodel()->database()->GetDBTable("REACTIONS")->{$Reaction}->[0]->{"ENZYME"}->[0];                          $ECData = $row->{"ENZYME"}->[0];
4271                          }                          }
4272                          my $SubsystemData = "";                          my $SubsystemData = "";
4273                          if (defined($ModelTable->{$Reaction}->[0]->{"SUBSYSTEM"}->[0])) {                  if (defined($mdlrow->{"SUBSYSTEM"}->[0])) {
4274                                  $SubsystemData = $ModelTable->{$Reaction}->[0]->{"SUBSYSTEM"}->[0];                          $SubsystemData = $mdlrow->{"SUBSYSTEM"}->[0];
4275                          }                          }
4276                          my $GeneAssociation = "";                          my $GeneAssociation = "";
4277                          my $ProteinAssociation = "";                          my $ProteinAssociation = "";
4278                          if (defined($ModelTable->{$Reaction}->[0]->{"ASSOCIATED PEG"}->[0])) {                  if (defined($mdlrow->{"ASSOCIATED PEG"}->[0])) {
4279                                  if (@{$ModelTable->{$Reaction}->[0]->{"ASSOCIATED PEG"}} == 1 && $ModelTable->{$Reaction}->[0]->{"ASSOCIATED PEG"}->[0] !~ m/\+/) {                          if (@{$mdlrow->{"ASSOCIATED PEG"}} == 1 && $mdlrow->{"ASSOCIATED PEG"}->[0] !~ m/\+/) {
4280                                          $GeneAssociation = $ModelTable->{$Reaction}->[0]->{"ASSOCIATED PEG"}->[0];                                  $GeneAssociation = $mdlrow->{"ASSOCIATED PEG"}->[0];
4281                                  } else {                                  } else {
4282                                          if (@{$ModelTable->{$Reaction}->[0]->{"ASSOCIATED PEG"}} > 1) {                                  if (@{$mdlrow->{"ASSOCIATED PEG"}} > 1) {
4283                                                  $GeneAssociation = "( ";                                                  $GeneAssociation = "( ";
4284                                          }                                          }
4285                                          for (my $i=0; $i < @{$ModelTable->{$Reaction}->[0]->{"ASSOCIATED PEG"}}; $i++) {                                  for (my $i=0; $i < @{$mdlrow->{"ASSOCIATED PEG"}}; $i++) {
4286                                                  if ($i > 0) {                                                  if ($i > 0) {
4287                                                          $GeneAssociation .= " )  or  ( ";                                                          $GeneAssociation .= " )  or  ( ";
4288                                                  }                                                  }
4289                                                  $GeneAssociation .= $ModelTable->{$Reaction}->[0]->{"ASSOCIATED PEG"}->[$i];                                          $GeneAssociation .= $mdlrow->{"ASSOCIATED PEG"}->[$i];
4290                                          }                                          }
4291                                          if (@{$ModelTable->{$Reaction}->[0]->{"ASSOCIATED PEG"}} > 1) {                                  if (@{$mdlrow->{"ASSOCIATED PEG"}} > 1) {
4292                                                  $GeneAssociation .= " )";                                                  $GeneAssociation .= " )";
4293                                          }                                          }
4294                                  }                                  }
# Line 3186  Line 4297 
4297                                          $GeneAssociation = "( ".$GeneAssociation." )";                                          $GeneAssociation = "( ".$GeneAssociation." )";
4298                                  }                                  }
4299                                  $ProteinAssociation = $GeneAssociation;                                  $ProteinAssociation = $GeneAssociation;
4300                                  if (defined($self->figmodel()->database()->GetDBTable("MODEL STATS")->{$self->id()}->[0]->{"Genome ID"}->[0])) {                          if (defined($self->genome())) {
4301                                          $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());
4302                                  }                                  }
4303                          }                          }
4304                          print SBMLOUTPUT "<html:p>GENE_ASSOCIATION:".$GeneAssociation."</html:p>\n";                          print SBMLOUTPUT "<html:p>GENE_ASSOCIATION:".$GeneAssociation."</html:p>\n";
# Line 3218  Line 4329 
4329              print SBMLOUTPUT "</kineticLaw>\n";              print SBMLOUTPUT "</kineticLaw>\n";
4330                          print SBMLOUTPUT '</reaction>'."\n";                          print SBMLOUTPUT '</reaction>'."\n";
4331                  }                  }
         }  
4332    
4333          my @ExchangeList = keys(%{$ExchangeHash});          my @ExchangeList = keys(%{$ExchangeHash});
4334          foreach my $ExCompound (@ExchangeList) {          foreach my $ExCompound (@ExchangeList) {
4335                  my $ExCompoundName = $ExCompound;                  my $ExCompoundName = $ExCompound;
4336                  my $Row = $self->figmodel()->database()->GetDBTable("COMPOUNDS")->get_row_by_key($ExCompound,"DATABASE");                  my $Row = $cpdTbl->get_row_by_key($ExCompound,"DATABASE");
4337                  if (defined($Row) && defined($Row->{"NAME"}->[0])) {                  if (defined($Row) && defined($Row->{"NAME"}->[0])) {
4338                          $ExCompoundName = $Row->{"NAME"}->[0];                          $ExCompoundName = $Row->{"NAME"}->[0];
4339                          $ExCompoundName =~ s/[<>;&]//g;                          $ExCompoundName =~ s/[<>;&]//g;
# Line 3263  Line 4373 
4373          close(SBMLOUTPUT);          close(SBMLOUTPUT);
4374  }  }
4375    
4376    =head3 PrintModelSimpleReactionTable
4377    Definition:
4378            success()/fail() FIGMODELmodel->PrintModelSimpleReactionTable();
4379    Description:
4380            Prints the table of model data
4381    =cut
4382    sub PrintModelSimpleReactionTable {
4383            my ($self) = @_;
4384    
4385            my $rxntbl = $self->reaction_table();
4386            my $tbl = $self->create_table_prototype("ModelSimpleReactionTable");
4387            for (my $i=0; $i < $rxntbl->size(); $i++) {
4388                    my $row = $rxntbl->get_row($i);
4389                    $row->{DATABASE} = $row->{LOAD};
4390                    $tbl->add_row($row);
4391            }
4392            $tbl->save();
4393    }
4394    
4395  =head3 PrintModelLPFile  =head3 PrintModelLPFile
4396  Definition:  Definition:
4397          success()/fail() FIGMODELmodel->PrintModelLPFile();          success()/fail() FIGMODELmodel->PrintModelLPFile();
# Line 3287  Line 4416 
4416          $self->figmodel()->clearing_output($UniqueFilename,"FBA-".$self->id().$self->selected_version().".lp");          $self->figmodel()->clearing_output($UniqueFilename,"FBA-".$self->id().$self->selected_version().".lp");
4417  }  }
4418    
4419    =head3 patch_model
4420    Definition:
4421            FIGMODELTable:patch results = FIGMODELmodel->patch_model(FIGMODELTable:patch table);
4422