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