[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.21, Sat Jul 10 22:43:52 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}) && $self->source() =~ /^MGRAST/) {          if (!defined($self->{_mgdata}) && $self->source() =~ /^MGRAST/) {
195                  require MGRAST;                  require MGRAST;
196                  $self->{_mgdata} = $self->figmodel()->mgrast()->Job->get_objects( { 'genome_id' => $self->genome() } )                  $self->{_mgdata} = $self->figmodel()->mgrast()->Job->get_objects( { 'genome_id' => $self->genome() } )
197          }          }
   
198          return $self->{_mgdata};          return $self->{_mgdata};
199  }  }
200    
# Line 144  Line 206 
206  =cut  =cut
207  sub id {  sub id {
208          my ($self) = @_;          my ($self) = @_;
209          return $self->{_data}->{id}->[0];          return $self->{_data}->id();
210  }  }
211    
212  =head3 owner  =head3 get_model_type
213  Definition:  Definition:
214          string = FIGMODELmodel->owner();          string = FIGMODELmodel->get_model_type();
215  Description:  Description:
216          Returns the username for the model owner          Returns the type of the model
217  =cut  =cut
218  sub owner {  sub get_model_type {
219          my ($self) = @_;          my ($self) = @_;
220          return $self->{_data}->{owner}->[0];          return $self->{_modeltype};
221  }  }
222    
223  =head3 index  =head3 owner
224  Definition:  Definition:
225          string = FIGMODELmodel->index();          string = FIGMODELmodel->owner();
226  Description:  Description:
227          Returns model index          Returns the username for the model owner
228  =cut  =cut
229  sub index {  sub owner {
230          my ($self) = @_;          my ($self) = @_;
231          return $self->{_index};          return $self->{_data}->owner();
232  }  }
233    
234  =head3 name  =head3 name
# Line 185  Line 247 
247                          if (defined($self->mgdata())) {                          if (defined($self->mgdata())) {
248                                  $self->{_name} = $self->mgdata()->genome_name;                                  $self->{_name} = $self->mgdata()->genome_name;
249                          }                          }
                 } elsif (defined($self->stats())) {  
                         $self->{_name} = $self->stats()->{'Organism name'}->[0];  
250                  } elsif ($source !~ /^RAST/) {                  } elsif ($source !~ /^RAST/) {
251                          $self->{_name} = $self->fig()->orgname_of_orgid($self->genome());                          $self->{_name} = $self->fig()->orgname_of_orgid($self->genome());
252                    } else {
253                            $self->{_name} = $self->figmodel()->get_genome_stats($self->genome())->{NAME}->[0];
254                  }                  }
255          }          }
256    
257          return $self->{_name};          return $self->{_name};
258  }  }
259    
 =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};  
 }  
   
260  =head3 get_reaction_class  =head3 get_reaction_class
261  Definition:  Definition:
262          string = FIGMODELmodel->get_reaction_class(string::reaction ID);          string = FIGMODELmodel->get_reaction_class(string::reaction ID);
# Line 217  Line 264 
264          Returns reaction class          Returns reaction class
265  =cut  =cut
266  sub get_reaction_class {  sub get_reaction_class {
267          my ($self,$reaction,$nohtml) = @_;          my ($self,$reaction,$nohtml,$brief_flux) = @_;
268    
269          if (!-e $self->directory()."ReactionClassification-".$self->id().".tbl") {          if (!-e $self->directory()."ReactionClassification-".$self->id().".tbl") {
270                  if (!defined($self->{_reaction_classes})) {                  if (!defined($self->{_reaction_classes})) {
# Line 230  Line 277 
277                  my $ClassRow = $self->{_reaction_classes}->get_row_by_key($reaction,"REACTION");                  my $ClassRow = $self->{_reaction_classes}->get_row_by_key($reaction,"REACTION");
278                  if (defined($ClassRow) && defined($ClassRow->{CLASS})) {                  if (defined($ClassRow) && defined($ClassRow->{CLASS})) {
279                          my $class;                          my $class;
280                            my $min = $ClassRow->{MIN}->[0];
281                            my $max = $ClassRow->{MAX}->[0];
282                          if ($ClassRow->{CLASS}->[0] eq "Positive") {                          if ($ClassRow->{CLASS}->[0] eq "Positive") {
283                                  $class = "Essential =>";                                  $class = "Essential =>";
284                                    $brief_flux ? $class.="<br>[Flux: ".sprintf("%.3g",$min)." to ".sprintf("%.3g",$max)."]<br>" : $class.="<br>[Flux: ".$min." to ".$max."]<br>";
285                          } elsif ($ClassRow->{CLASS}->[0] eq "Negative") {                          } elsif ($ClassRow->{CLASS}->[0] eq "Negative") {
286                                  $class = "Essential <=";                                  $class = "Essential <=";
287                                    $brief_flux ? $class.="<br>[Flux: ".sprintf("%.3g",$min)." to ".sprintf("%.3g",$max)."]<br>" : $class.="<br>[Flux: ".$min." to ".$max."]<br>";
288                          } elsif ($ClassRow->{CLASS}->[0] eq "Positive variable") {                          } elsif ($ClassRow->{CLASS}->[0] eq "Positive variable") {
289                                  $class = "Active =>";                                  $class = "Active =>";
290                                    $brief_flux ? $class.="<br>[Flux: ".sprintf("%.3g",$min)." to ".sprintf("%.3g",$max)."]<br>" : $class.="<br>[Flux: ".$min." to ".$max."]<br>";
291                          } elsif ($ClassRow->{CLASS}->[0] eq "Negative variable") {                          } elsif ($ClassRow->{CLASS}->[0] eq "Negative variable") {
292                                  $class = "Active <=";                                  $class = "Active <=";
293                                    $brief_flux ? $class.="<br>[Flux: ".sprintf("%.3g",$min)." to ".sprintf("%.3g",$max)."]<br>" : $class.="<br>[Flux: ".$min." to ".$max."]<br>";
294                          } elsif ($ClassRow->{CLASS}->[0] eq "Variable") {                          } elsif ($ClassRow->{CLASS}->[0] eq "Variable") {
295                                  $class = "Active <=>";                                  $class = "Active <=>";
296                                    $brief_flux ? $class.="<br>[Flux: ".sprintf("%.3g",$min)." to ".sprintf("%.3g",$max)."]<br>" : $class.="<br>[Flux: ".$min." to ".$max."]<br>";
297                          } elsif ($ClassRow->{CLASS}->[0] eq "Blocked") {                          } elsif ($ClassRow->{CLASS}->[0] eq "Blocked") {
298                                  $class = "Inactive";                                  $class = "Inactive";
299                          } elsif ($ClassRow->{CLASS}->[0] eq "Dead") {                          } elsif ($ClassRow->{CLASS}->[0] eq "Dead") {
300                                  $class = "Disconnected";                                  $class = "Disconnected";
301                          }                          }
302    
303                          if (!defined($nohtml) || $nohtml ne "1") {                          if (!defined($nohtml) || $nohtml ne "1") {
304                                  $class = "<span title=\"Flux:".$ClassRow->{MIN}->[0]." to ".$ClassRow->{MAX}->[0]."\">".$class."</span>";                                  $class = "<span title=\"Flux:".$min." to ".$max."\">".$class."</span>";
305                          }                          }
306    
307                          return $class;                          return $class;
308                  }                  }
309                  return undef;                  return undef;
# Line 268  Line 324 
324                                  $classstring .= "<br>";                                  $classstring .= "<br>";
325                          }                          }
326                          my $NewClass;                          my $NewClass;
327                            my $min = $ClassRow->{MIN}->[$i];
328                            my $max = $ClassRow->{MAX}->[$i];
329                          if ($ClassRow->{CLASS}->[$i] eq "Positive") {                          if ($ClassRow->{CLASS}->[$i] eq "Positive") {
330                                  $NewClass = $ClassRow->{MEDIA}->[$i].":Essential =>";                                  $NewClass = $ClassRow->{MEDIA}->[$i].":Essential =>";
331                                  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>";  
                                 }  
332                          } elsif ($ClassRow->{CLASS}->[$i] eq "Negative") {                          } elsif ($ClassRow->{CLASS}->[$i] eq "Negative") {
333                                  $NewClass = $ClassRow->{MEDIA}->[$i].":Essential <=";                                  $NewClass = $ClassRow->{MEDIA}->[$i].":Essential <=";
334                                  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>";  
                                 }  
335                          } elsif ($ClassRow->{CLASS}->[$i] eq "Positive variable") {                          } elsif ($ClassRow->{CLASS}->[$i] eq "Positive variable") {
336                                  $NewClass = $ClassRow->{MEDIA}->[$i].":Active =>";                                  $NewClass = $ClassRow->{MEDIA}->[$i].":Active =>";
337                                  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>";  
                                 }  
338                          } elsif ($ClassRow->{CLASS}->[$i] eq "Negative variable") {                          } elsif ($ClassRow->{CLASS}->[$i] eq "Negative variable") {
339                                  $NewClass = $ClassRow->{MEDIA}->[$i].":Active <=";                                  $NewClass = $ClassRow->{MEDIA}->[$i].":Active <=";
340                                  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>";  
                                 }  
341                          } elsif ($ClassRow->{CLASS}->[$i] eq "Variable") {                          } elsif ($ClassRow->{CLASS}->[$i] eq "Variable") {
342                                  $NewClass = $ClassRow->{MEDIA}->[$i].":Active <=>";                                  $NewClass = $ClassRow->{MEDIA}->[$i].":Active <=>";
343                                  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>";  
                                 }  
344                          } elsif ($ClassRow->{CLASS}->[$i] eq "Blocked") {                          } elsif ($ClassRow->{CLASS}->[$i] eq "Blocked") {
345                                  $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>";  
                                 }  
346                          } elsif ($ClassRow->{CLASS}->[$i] eq "Dead") {                          } elsif ($ClassRow->{CLASS}->[$i] eq "Dead") {
347                                  $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>";  
348                                  }                                  }
349    
350                            if (!defined($nohtml) || $nohtml ne "1") {
351                                    $NewClass = "<span title=\"Flux:".$min." to ".$max."\">".$NewClass."</span>";
352                          }                          }
353                          $classstring .= $NewClass;                          $classstring .= $NewClass;
354                  }                  }
# Line 321  Line 367 
367    
368          if (!defined($self->{_biomass})) {          if (!defined($self->{_biomass})) {
369                  my $rxntbl = $self->reaction_table();                  my $rxntbl = $self->reaction_table();
370                    if (defined($rxntbl)) {
371                  for (my $i=0; $i < $rxntbl->size(); $i++) {                  for (my $i=0; $i < $rxntbl->size(); $i++) {
372                          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/) {
373                                  $self->{_biomass} = $rxntbl->get_row($i)->{"LOAD"}->[0];                                  $self->{_biomass} = $rxntbl->get_row($i)->{"LOAD"}->[0];
# Line 328  Line 375 
375                          }                          }
376                  }                  }
377          }          }
378            }
379    
380          return $self->get_reaction_data($self->{_biomass});          return $self->get_reaction_data($self->{_biomass});
381  }  }
# Line 340  Line 388 
388  =cut  =cut
389  sub get_reaction_data {  sub get_reaction_data {
390          my ($self,$reaction) = @_;          my ($self,$reaction) = @_;
   
391          if (!defined($self->reaction_table())) {          if (!defined($self->reaction_table())) {
392                  return undef;                  return undef;
393          }          }
394          if ($reaction =~ m/^\d+$/) {          if ($reaction =~ m/^\d+$/) {
395                  $self->reaction_table()->get_row($reaction);                  return $self->reaction_table()->get_row($reaction);
396          }          }
397          return $self->reaction_table()->get_row_by_key($reaction,"LOAD");          return $self->reaction_table()->get_row_by_key($reaction,"LOAD");
398  }  }
# Line 366  Line 413 
413          return $Data->{LOAD}->[0];          return $Data->{LOAD}->[0];
414  }  }
415    
416    =head3 load_model_table
417    
418    Definition: FIGMODELTable = FIGMODELmodel->load_model_table(string:table name,0/1:refresh the table));
419    
420    Description: Returns the table specified by the input filename. Table will be stored in a file in the model directory.
421    
422    =cut
423    sub load_model_table {
424            my ($self,$name,$refresh) = @_;
425            if (defined($refresh) && $refresh == 1) {
426                    delete $self->{"_".$name};
427            }
428            if (!defined($self->{"_".$name})) {
429                    my $tbldef = $self->figmodel()->config($name);
430                    if (!defined($tbldef)) {
431                            return undef;
432                    }
433                    my $itemDelim = "|";
434                    if (defined($tbldef->{itemdelimiter}->[0])) {
435                            $itemDelim = $tbldef->{itemdelimiter}->[0];
436                            if ($itemDelim eq "SC") {
437                                    $itemDelim = ";";
438                            }
439                    }
440                    my $columnDelim = "\t";
441                    if (defined($tbldef->{columndelimiter}->[0])) {
442                            $columnDelim = $tbldef->{columndelimiter}->[0];
443                            if ($columnDelim eq "SC") {
444                                    $columnDelim = ";";
445                            }
446                    }
447                    my $suffix = ".tbl";
448                    if (defined($tbldef->{filename_suffix}->[0])) {
449                            $suffix = $tbldef->{filename_suffix}->[0];
450                    }
451                    my $filename = $self->directory().$name."-".$self->id().$self->selected_version().$suffix;
452                    if (defined($tbldef->{filename_prefix}->[0])) {
453                            if ($tbldef->{filename_prefix}->[0] eq "NONE") {
454                                    $filename = $self->directory().$self->id().$self->selected_version().$suffix;
455                            } else {
456                                    $filename = $self->directory().$tbldef->{filename_prefix}->[0]."-".$self->id().$self->selected_version().$suffix;
457                            }
458                    }
459                    if (-e $filename) {
460                            $self->{"_".$name} = $self->figmodel()->database()->load_table($filename,$columnDelim,$itemDelim,$tbldef->{headingline}->[0],$tbldef->{hashcolumns});
461                    } else {
462                            if (defined($tbldef->{prefix})) {
463                                    $self->{"_".$name} = FIGMODELTable->new($tbldef->{columns},$filename,$tbldef->{hashcolumns},$columnDelim,$itemDelim,join(@{$tbldef->{prefix}},"\n"));
464                            } else {
465                                    $self->{"_".$name} = FIGMODELTable->new($tbldef->{columns},$filename,$tbldef->{hashcolumns},$columnDelim,$itemDelim);
466                            }
467                    }
468            }
469            return $self->{"_".$name};
470    }
471    
472    =head3 create_table_prototype
473    
474    Definition:
475            FIGMODELTable::table = FIGMODELmodel->create_table_prototype(string::table);
476    Description:
477            Returns a empty FIGMODELTable with all the metadata associated with the input table name
478    
479    =cut
480    sub create_table_prototype {
481            my ($self,$TableName) = @_;
482            #Checking if the table definition exists in the FIGMODELconfig file
483            my $tbldef = $self->figmodel()->config($TableName);
484            if (!defined($tbldef)) {
485                    $self->figmodel()->error_message("FIGMODELdatabase:create_table_prototype:Definition not found for ".$TableName);
486                    return undef;
487            }
488            #Checking that this is a database table
489            if (!defined($tbldef->{tabletype}) || $tbldef->{tabletype}->[0] ne "ModelTable") {
490                    $self->figmodel()->error_message("FIGMODELdatabase:create_table_prototype:".$TableName." is not a model table!");
491                    return undef;
492            }
493            #Setting default values for table parameters
494            my $prefix;
495            if (defined($tbldef->{prefix})) {
496                    $prefix = join("\n",@{$self->config($TableName)->{prefix}})."\n";
497            }
498            my $itemDelim = "|";
499            if (defined($tbldef->{itemdelimiter}->[0])) {
500                    $itemDelim = $tbldef->{itemdelimiter}->[0];
501                    if ($itemDelim eq "SC") {
502                            $itemDelim = ";";
503                    }
504            }
505            my $columnDelim = "\t";
506            if (defined($tbldef->{columndelimiter}->[0])) {
507                    $columnDelim = $tbldef->{columndelimiter}->[0];
508                    if ($columnDelim eq "SC") {
509                            $columnDelim = ";";
510                    }
511            }
512            my $suffix = ".tbl";
513            if (defined($tbldef->{filename_suffix}->[0])) {
514                    $suffix = $tbldef->{filename_suffix}->[0];
515            }
516            my $filename = $self->directory().$TableName."-".$self->id().$self->selected_version().$suffix;
517            if (defined($tbldef->{filename_prefix}->[0])) {
518                    if ($tbldef->{filename_prefix}->[0] eq "NONE") {
519                            $filename = $self->directory().$self->id().$self->selected_version().$suffix;
520                    } else {
521                            $filename = $self->directory().$tbldef->{filename_prefix}->[0]."-".$self->id().$self->selected_version().$suffix;
522                    }
523            }
524            #Creating the table prototype
525            my $tbl = FIGMODELTable->new($tbldef->{columns},$filename,$tbldef->{hashcolumns},$columnDelim,$itemDelim,$prefix);
526            return $tbl;
527    }
528    
529  =head3 get_reaction_number  =head3 get_reaction_number
530  Definition:  Definition:
531          int = FIGMODELmodel->get_reaction_number();          int = FIGMODELmodel->get_reaction_number();
# Line 374  Line 534 
534  =cut  =cut
535  sub get_reaction_number {  sub get_reaction_number {
536          my ($self) = @_;          my ($self) = @_;
   
537          if (!defined($self->reaction_table())) {          if (!defined($self->reaction_table())) {
538                  return 0;                  return 0;
539          }          }
   
540          return $self->reaction_table()->size();          return $self->reaction_table()->size();
541  }  }
542    
# Line 389  Line 547 
547          Returns FIGMODELTable with the reaction list for the model          Returns FIGMODELTable with the reaction list for the model
548  =cut  =cut
549  sub reaction_table {  sub reaction_table {
550          my ($self) = @_;          my ($self,$clear) = @_;
551            if (defined($self->{_reaction_table})) {
552                    return $self->{_reaction_table};
553            }
554            $self->{_reaction_table} = $self->load_model_table("ModelReactions",$clear);
555            my $classTbl = $self->reaction_class_table();
556            if (defined($classTbl)) {
557                    for (my $i=0; $i < $classTbl->size(); $i++) {
558                            my $row = $classTbl->get_row($i);
559                            if (defined($row->{REACTION})) {
560                                    my $rxnRow = $self->{_reaction_table}->get_row_by_key($row->{"REACTION"}->[0],"LOAD");
561                                    if (defined($row->{MEDIA})) {
562                                            for (my $j=0; $j < @{$row->{MEDIA}};$j++) {
563                                                    my $class = "Active <=>";
564                                                    if ($row->{CLASS}->[$j] eq "Positive") {
565                                                            $class = "Essential =>";
566                                                    } elsif ($row->{CLASS}->[$j] eq "Negative") {
567                                                            $class = "Essential <=";
568                                                    } elsif ($row->{CLASS}->[$j] eq "Blocked") {
569                                                            $class = "Inactive";
570                                                    } elsif ($row->{CLASS}->[$j] eq "Positive variable") {
571                                                            $class = "Active =>";
572                                                    } elsif ($row->{CLASS}->[$j] eq "Negative variable") {
573                                                            $class = "Active <=";
574                                                    } elsif ($row->{CLASS}->[$j] eq "Variable") {
575                                                            $class = "Active <=>";
576                                                    } elsif ($row->{CLASS}->[$j] eq "Dead") {
577                                                            $class = "Dead";
578                                                    }
579                                                    push(@{$rxnRow->{PREDICTIONS}},$row->{MEDIA}->[$j].":".$class);
580                                            }
581                                    }
582                            }
583                    }
584            }
585            return $self->{_reaction_table};
586    }
587    
588          if (!defined($self->{_reaction_data})) {  =head3 essentials_table
589                  $self->{_reaction_data} = $self->figmodel()->database()->GetDBModel($self->id());  Definition:
590            FIGMODELTable = FIGMODELmodel->essentials_table();
591    Description:
592            Returns FIGMODELTable with the essential genes for the model
593    =cut
594    sub essentials_table {
595            my ($self,$clear) = @_;
596            my $tbl = $self->load_model_table("ModelEssentialGenes",$clear);
597            return $tbl;
598          }          }
599    
600          return $self->{_reaction_data};  =head3 model_history
601    Definition:
602            FIGMODELTable = FIGMODELmodel->model_history();
603    Description:
604            Returns FIGMODELTable with the history of model changes
605    =cut
606    sub model_history {
607            my ($self,$clear) = @_;
608            return $self->load_model_table("ModelHistory",$clear);
609  }  }
610    
611  =head3 reaction_class_table  =head3 feature_table
612  Definition:  Definition:
613          FIGMODELTable = FIGMODELmodel->reaction_class_table();          FIGMODELTable = FIGMODELmodel->feature_table();
614  Description:  Description:
615          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
616  =cut  =cut
617  sub reaction_class_table {  sub feature_table {
618          my ($self) = @_;          my ($self) = @_;
619    
620          if (!defined($self->{_reaction_class_table})) {          if (!defined($self->{_feature_data})) {
621                  if (-e $self->directory()."ReactionClassification-".$self->id().$self->selected_version().".tbl") {                  #Getting the genome feature list
622                          $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());
623                    if (!defined($FeatureTable)) {
624                            print STDERR "FIGMODELmodel:feature_table:Could not get features for genome ".$self->genome()." in database!";
625                            return undef;
626                    }
627                    #Getting the reaction table for the model
628                    my $rxnTable = $self->reaction_table();
629                    if (!defined($rxnTable)) {
630                            print STDERR "FIGMODELmodel:feature_table:Could not get reaction table for model ".$self->id()." in database!";
631                            return undef;
632                    }
633                    #Cloning the feature table
634                    $self->{_feature_data} = $FeatureTable->clone_table_def();
635                    $self->{_feature_data}->add_headings(($self->id()."REACTIONS",$self->id()."PREDICTIONS"));
636                    for (my $i=0; $i < $rxnTable->size(); $i++) {
637                            my $Row = $rxnTable->get_row($i);
638                            if (defined($Row) && defined($Row->{"ASSOCIATED PEG"})) {
639                                    foreach my $GeneSet (@{$Row->{"ASSOCIATED PEG"}}) {
640                                            my $temp = $GeneSet;
641                                            $temp =~ s/\+/|/g;
642                                            $temp =~ s/\sAND\s/|/gi;
643                                            $temp =~ s/\sOR\s/|/gi;
644                                            $temp =~ s/[\(\)\s]//g;
645                                            my @GeneList = split(/\|/,$temp);
646                                            foreach my $Gene (@GeneList) {
647                                                    my $FeatureRow = $self->{_feature_data}->get_row_by_key("fig|".$self->genome().".".$Gene,"ID");
648                                                    if (!defined($FeatureRow)) {
649                                                            $FeatureRow = $FeatureTable->get_row_by_key("fig|".$self->genome().".".$Gene,"ID");
650                                                            if (defined($FeatureRow)) {
651                                                                    $self->{_feature_data}->add_row($FeatureRow);
652                                                            }
653                                                    }
654                                                    if (defined($FeatureRow)) {
655                                                            $self->{_feature_data}->add_data($FeatureRow,$self->id()."REACTIONS",$Row->{"LOAD"}->[0],1);
656                                                    }
657                                            }
658                                    }
659                            }
660                    }
661                    #Loading predictions
662                    my $esstbl = $self->essentials_table();
663                    for (my $i=0; $i < $self->{_feature_data}->size(); $i++) {
664                            my $Row = $self->{_feature_data}->get_row($i);
665                            if ($Row->{ID}->[0] =~ m/(peg\.\d+)/) {
666                                    my $gene = $1;
667                                    my @rows = $esstbl->get_rows_by_key($gene,"ESSENTIAL GENES");
668                                    my $mediahash;
669                                    for (my $j=0; $j < $esstbl->size(); $j++) {
670                                            $mediahash->{$esstbl->get_row($j)->{MEDIA}->[0]} = 0;
671                                    }
672                                    for (my $j=0; $j < @rows; $j++) {
673                                            $mediahash->{$rows[$j]->{MEDIA}->[0]} = 1;
674                                    }
675                                    my @mediaList = keys(%{$mediahash});
676                                    for (my $j=0; $j < @mediaList; $j++) {
677                                            if ($mediahash->{$mediaList[$j]} == 1) {
678                                                    push(@{$Row->{$self->id()."PREDICTIONS"}},$mediaList[$j].":essential");
679                  } else {                  } else {
680                          $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");
681                                            }
682                  }                  }
683          }          }
684                    }
685            }
686            return $self->{_feature_data};
687    }
688    
689          return $self->{_reaction_class_table};  =head3 reaction_class_table
690    Definition:
691            FIGMODELTable = FIGMODELmodel->reaction_class_table();
692    Description:
693            Returns FIGMODELTable with the reaction class data, and creates the table file  if it does not exist
694    =cut
695    sub reaction_class_table {
696            my ($self,$clear) = @_;
697            return $self->load_model_table("ModelReactionClasses",$clear);
698  }  }
699    
700  =head3 compound_class_table  =head3 compound_class_table
# Line 425  Line 704 
704          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
705  =cut  =cut
706  sub compound_class_table {  sub compound_class_table {
707          my ($self) = @_;          my ($self,$clear) = @_;
708            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};  
709  }  }
710    
711  =head3 get_essential_genes  =head3 get_essential_genes
# Line 446  Line 716 
716  =cut  =cut
717  sub get_essential_genes {  sub get_essential_genes {
718          my ($self,$media) = @_;          my ($self,$media) = @_;
719            my $tbl = $self->essentials_table();
720          if (!defined($media)) {          my $row = $tbl->get_row_by_key($media,"MEDIA");
721                  $media = "Complete";          if (defined($row)) {
722          }                  return $row->{"ESSENTIAL GENES"};
         if (!defined($self->{_essential_genes}->{$media})) {  
                 $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","");  
723                  }                  }
724          }          return undef;
   
         return $self->{_essential_genes}->{$media};  
725  }  }
726    
727  =head3 compound_table  =head3 compound_table
# Line 470  Line 734 
734          my ($self) = @_;          my ($self) = @_;
735    
736          if (!defined($self->{_compound_table})) {          if (!defined($self->{_compound_table})) {
737                  $self->{_compound_table} = $self->figmodel()->database()->GetDBModelCompounds($self->id());                  $self->{_compound_table} = $self->create_table_prototype("ModelCompounds");
738                    #Loading the reactions
739                    my $ReactionTable = $self->figmodel()->database()->get_table("REACTIONS");
740                    my $BiomassTable = $self->figmodel()->database()->get_table("BIOMASS");
741                    #Loading the model
742                    my $ModelTable = $self->reaction_table();
743                    #Checking that the tables were loaded
744                    if (!defined($ModelTable) || !defined($ReactionTable)) {
745                            return undef;
746                    }
747                    #Finding the biomass reaction
748                    for (my $i=0; $i < $ModelTable->size(); $i++) {
749                            my $ID = $ModelTable->get_row($i)->{"LOAD"}->[0];
750                            my $Row = $ReactionTable->get_row_by_key($ID,"DATABASE");
751                            my $IsBiomass = 0;
752                            if (!defined($Row)) {
753                                    $Row = $BiomassTable->get_row_by_key($ID,"DATABASE");
754                                    $IsBiomass = 1;
755                            }
756                            if (defined($Row->{"EQUATION"}->[0])) {
757                                    $_ = $Row->{"EQUATION"}->[0];
758                                    my @OriginalArray = /(cpd\d\d\d\d\d[\[\w]*)/g;
759                                    foreach my $Compound (@OriginalArray) {
760                                            my $ID = substr($Compound,0,8);
761                                            my $NewRow = $self->{_compound_table}->get_row_by_key($ID,"DATABASE",1);
762                                            if ($IsBiomass == 1) {
763                                                    $self->{_compound_table}->add_data($NewRow,"BIOMASS",$Row->{"DATABASE"}->[0],1);
764                                            }
765                                            if (length($Compound) > 8) {
766                                                    #print $Compound."\t".$Row->{"EQUATION"}->[0]."\t".$Row->{"DATABASE"}->[0]."\n";
767                                                    my $Compartment = substr($Compound,8,1);
768                                                    $self->{_compound_table}->add_data($NewRow,"COMPARTMENTS",$Compartment,1);
769                                                    $self->{_compound_table}->add_data($NewRow,"TRANSPORTERS",$Row->{"DATABASE"}->[0],1);
770                                            }
771                                    }
772                            }
773                    }
774          }          }
775    
776          return $self->{_compound_table};          return $self->{_compound_table};
# Line 478  Line 778 
778    
779  =head3 get_compound_data  =head3 get_compound_data
780  Definition:  Definition:
781          string = FIGMODELmodel->get_compound_data(string::compound ID);          {string:key=>[string]:values} = FIGMODELmodel->get_compound_data(string::compound ID);
782  Description:  Description:
783          Returns model compound data          Returns model compound data
784  =cut  =cut
# Line 489  Line 789 
789                  return undef;                  return undef;
790          }          }
791          if ($compound =~ m/^\d+$/) {          if ($compound =~ m/^\d+$/) {
792                  $self->compound_table()->get_row($compound);                  return $self->compound_table()->get_row($compound);
793          }          }
794          return $self->compound_table()->get_row_by_key($compound,"DATABASE");          return $self->compound_table()->get_row_by_key($compound,"DATABASE");
795  }  }
796    
797    =head3 get_feature_data
798    Definition:
799            {string:key=>[string]:values} = FIGMODELmodel->get_feature_data(string::feature ID);
800    Description:
801            Returns model feature data
802    =cut
803    sub get_feature_data {
804            my ($self,$feature) = @_;
805            if (!defined($self->feature_table())) {
806                    return undef;
807            }
808            if ($feature =~ m/^\d+$/) {
809                    return $self->feature_table()->get_row($feature);
810            }
811            if ($feature =~ m/(peg\.\d+)/) {
812                    $feature = $1;
813            }
814            return $self->feature_table()->get_row_by_key("fig|".$self->genome().".".$feature,"ID");
815    }
816    
817  =head3 genome  =head3 genome
818  Definition:  Definition:
819          string = FIGMODELmodel->genome();          string = FIGMODELmodel->genome();
# Line 502  Line 822 
822  =cut  =cut
823  sub genome {  sub genome {
824          my ($self) = @_;          my ($self) = @_;
825          return $self->{_data}->{genome}->[0];          return $self->{_data}->genome();
826  }  }
827    
828  =head3 source  =head3 source
# Line 513  Line 833 
833  =cut  =cut
834  sub source {  sub source {
835          my ($self) = @_;          my ($self) = @_;
836          return $self->{_data}->{source}->[0];          return $self->{_data}->source();
837  }  }
838    
839  =head3 rights  =head3 rights
# Line 524  Line 844 
844  =cut  =cut
845  sub rights {  sub rights {
846          my ($self,$username) = @_;          my ($self,$username) = @_;
   
847          if ($self->public()) {          if ($self->public()) {
848                  return 1;                  return 1;
849          }          }
# Line 532  Line 851 
851                  return 0;                  return 0;
852          }          }
853          if (!defined($self->{_userrights}->{$username})) {          if (!defined($self->{_userrights}->{$username})) {
854                  if (defined($self->{_data}->{master})) {                  $self->{_userrights}->{$self->{_data}->owner()} = 1;
855                          for (my $i=0; $i < @{$self->{_data}->{master}};$i++) {                  my @users = split(/\|/,$self->{_data}->users());
856                                  $self->{_userrights}->{$self->{_data}->{master}->[$i]} = 1;                  for (my $i=0; $i < @users;$i++) {
857                          }                          $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;  
                         }  
858                  }                  }
859          }          }
860          return $self->{_userrights}->{$username};          return $self->{_userrights}->{$username};
# Line 554  Line 868 
868  =cut  =cut
869  sub public {  sub public {
870          my ($self) = @_;          my ($self) = @_;
871            if ($self->{_data}->users() eq "all") {
872          if (!defined($self->{_public})) {                  return 1;
                 $self->{_public} = 0;  
                 if (defined($self->{_data}->{users}->[0]) && $self->{_data}->{users}->[0] eq "all") {  
                         $self->{_public} = 1;  
                 }  
873          }          }
874          return $self->{_public};          return 0;
875  }  }
876    
877  =head3 directory  =head3 directory
# Line 580  Line 890 
890                  }                  }
891                  my $source = $self->source();                  my $source = $self->source();
892                  if ($source =~ /^MGRAST/) {                  if ($source =~ /^MGRAST/) {
893                          $self->{_directory} = $self->figmodel()->config("organism directory")->[0].$userdirectory.$self->genome()."/";                          $self->{_directory} = $self->figmodel()->config("mgrast model directory")->[0].$userdirectory.$self->genome()."/";
894                  } elsif ($source =~ /^RAST/) {                  } elsif ($source =~ /^RAST/) {
895                          $self->{_directory} = $self->figmodel()->config("organism directory")->[0].$userdirectory.$self->genome()."/";                          $self->{_directory} = $self->figmodel()->config("organism directory")->[0].$userdirectory.$self->genome()."/";
896                  } elsif ($source =~ /^SEED/) {                  } elsif ($source =~ /^SEED/) {
# Line 609  Line 919 
919          return $self->directory().$self->id().$self->selected_version().".txt";          return $self->directory().$self->id().$self->selected_version().".txt";
920  }  }
921    
 =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};  
         }  
 }  
   
922  =head3 version  =head3 version
923  Definition:  Definition:
924          string = FIGMODELmodel->version();          string = FIGMODELmodel->version();
# Line 660  Line 930 
930    
931          if (!defined($self->{_version})) {          if (!defined($self->{_version})) {
932                  if (!defined($self->{_selectedversion})) {                  if (!defined($self->{_selectedversion})) {
933                          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];  
                         }  
934                  } else {                  } else {
935                          $self->{_version} = $self->{_selectedversion};                          $self->{_version} = $self->{_selectedversion};
936                  }                  }
# Line 693  Line 961 
961  =cut  =cut
962  sub modification_time {  sub modification_time {
963          my ($self) = @_;          my ($self) = @_;
964          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};  
965  }  }
966    
967  =head3 gene_reactions  =head3 gene_reactions
# Line 717  Line 972 
972  =cut  =cut
973  sub gene_reactions {  sub gene_reactions {
974          my ($self) = @_;          my ($self) = @_;
975            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};  
976  }  }
977    
978  =head3 total_compounds  =head3 total_compounds
# Line 736  Line 983 
983  =cut  =cut
984  sub total_compounds {  sub total_compounds {
985          my ($self) = @_;          my ($self) = @_;
986            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};  
987  }  }
988    
989  =head3 gapfilling_reactions  =head3 gapfilling_reactions
# Line 755  Line 994 
994  =cut  =cut
995  sub gapfilling_reactions {  sub gapfilling_reactions {
996          my ($self) = @_;          my ($self) = @_;
997            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};  
998  }  }
999    
1000  =head3 total_reactions  =head3 total_reactions
# Line 774  Line 1005 
1005  =cut  =cut
1006  sub total_reactions {  sub total_reactions {
1007          my ($self) = @_;          my ($self) = @_;
1008            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};  
1009  }  }
1010    
1011  =head3 model_genes  =head3 model_genes
# Line 793  Line 1016 
1016  =cut  =cut
1017  sub model_genes {  sub model_genes {
1018          my ($self) = @_;          my ($self) = @_;
1019            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};  
1020  }  }
1021    
1022  =head3 class  =head3 class
# Line 812  Line 1027 
1027  =cut  =cut
1028  sub class {  sub class {
1029          my ($self) = @_;          my ($self) = @_;
1030            return $self->{_data}->cellwalltype();
         if (!defined($self->{_class})) {  
                 if ($self->source() =~ /^MGRAST/) {  
                         $self->{_class} = "Other";  
                 } elsif (defined($self->stats())) {  
                         $self->{_class} = $self->stats()->{Class}->[0];  
                 }  
1031          }          }
1032          return $self->{_class};  
1033    sub autocompleteMedia {
1034            my ($self) = @_;
1035            return $self->{_data}->autoCompleteMedia();
1036  }  }
1037    
1038  =head3 taxonomy  =head3 taxonomy
# Line 888  Line 1100 
1100                          if (defined($self->mgdata())) {                          if (defined($self->mgdata())) {
1101                                  $self->{_genome_genes} = $self->mgdata()->genome_contig_count;                                  $self->{_genome_genes} = $self->mgdata()->genome_contig_count;
1102                          }                          }
1103                  } elsif (defined($self->stats())) {                  } else {
1104                          $self->{_genome_genes} = $self->stats()->{'Total genes'}->[0];                          $self->{_genome_genes} = $self->figmodel()->get_genome_stats($self->genome())->{"TOTAL GENES"}->[0];
1105                  }                  }
1106          }          }
1107    
# Line 906  Line 1118 
1118    
1119          #Assuming complete media if none is provided          #Assuming complete media if none is provided
1120          if (!defined($Media)) {          if (!defined($Media)) {
1121                  $Media = "Complete";                  $Media = $self->autocompleteMedia();
1122          }          }
1123    
1124          #Predicting essentiality          #Predicting essentiality
1125          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]);
1126          #Checking that the table is defined and the output file exists          #Checking that the table is defined and the output file exists
1127          if (defined($result) && defined($result->get_row(0)->{"ESSENTIALGENES"})) {          if (defined($result) && defined($result->get_row(0)->{"ESSENTIALGENES"})) {
1128                  $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();
1129                    my $row = $tbl->get_row_by_key($Media,"MEDIA",1);
1130                    $row->{"ESSENTIAL GENES"} = $result->get_row(0)->{"ESSENTIALGENES"};
1131                    $tbl->save();
1132          } else {          } else {
1133                  $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().".");
1134                  return $self->figmodel()->fail();                  return $self->figmodel()->fail();
# Line 930  Line 1145 
1145          return $self->figmodel()->success();          return $self->figmodel()->success();
1146  }  }
1147    
 =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();  
         }  
 }  
   
1148  =head3 update_stats_for_gap_filling  =head3 update_stats_for_gap_filling
1149  Definition:  Definition:
1150          {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 1152 
1152  =cut  =cut
1153  sub update_stats_for_gap_filling {  sub update_stats_for_gap_filling {
1154          my ($self,$gapfilltime) = @_;          my ($self,$gapfilltime) = @_;
1155            $self->{_data}->autoCompleteTime($gapfilltime);
1156          #preserving the stats for the now obselete model          $self->{_data}->autocompleteDate(time());
1157          $self->save_obsolete_stats();          $self->{_data}->modificationDate(time());
1158          my $stats = $self->update_model_stats(0);          my $version = $self->{_data}->autocompleteVersion();
1159          $stats->{"Gap filling time"}->[0] = $gapfilltime;          $self->{_data}->autocompleteVersion($version+1);
         $stats->{"Gap fill date"}->[0] = time();  
         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;  
1160  }  }
1161    
1162  =head3 update_stats_for_build  =head3 update_stats_for_build
# Line 977  Line 1166 
1166  =cut  =cut
1167  sub update_stats_for_build {  sub update_stats_for_build {
1168          my ($self) = @_;          my ($self) = @_;
1169            $self->{_data}->builtDate(time());
1170          #preserving the stats for the now obselete model          $self->{_data}->modificationDate(time());
1171          $self->save_obsolete_stats();          my $version = $self->{_data}->version();
1172          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;  
1173  }  }
1174    
1175  =head3 update_model_stats  =head3 update_model_stats
# Line 1008  Line 1188 
1188          }          }
1189          my $cpdtbl = $self->compound_table();          my $cpdtbl = $self->compound_table();
1190    
1191          #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];  
         }  
   
1192          my %GeneHash;          my %GeneHash;
1193          my %NonpegHash;          my %NonpegHash;
1194          my %CompoundHash;          my %CompoundHash;
1195            my $spontaneousReactions = 0;
1196            my $gapFillReactions = 0;
1197            my $biologReactions = 0;
1198            my $transporters = 0;
1199            my $autoCompleteReactions = 0;
1200            my $associatedSubsystemGenes = 0;
1201          for (my $i=0; $i < $rxntbl->size(); $i++) {          for (my $i=0; $i < $rxntbl->size(); $i++) {
1202                  my $Row = $rxntbl->get_row($i);                  my $Row = $rxntbl->get_row($i);
1203                  if (defined($Row) && defined($Row->{"ASSOCIATED PEG"})) {                  if (defined($Row) && defined($Row->{"ASSOCIATED PEG"})) {
# Line 1066  Line 1205 
1205                          if (defined($ReactionRow->{"EQUATION"}->[0])) {                          if (defined($ReactionRow->{"EQUATION"}->[0])) {
1206                                  #Checking for extracellular metabolites which indicate that this is a transporter                                  #Checking for extracellular metabolites which indicate that this is a transporter
1207                                  if ($ReactionRow->{"EQUATION"}->[0] =~ m/\[e\]/) {                                  if ($ReactionRow->{"EQUATION"}->[0] =~ m/\[e\]/) {
1208                                          $CurrentStats->{"Transport reaction"}->[0]++;                                          $transporters++;
1209                                  }                                  }
1210                          }                          }
1211                          #Identifying spontaneous/biolog/gapfilling/gene associated reactions                          #Identifying spontaneous/biolog/gapfilling/gene associated reactions
1212                          if ($Row->{"ASSOCIATED PEG"}->[0] =~ m/BIOLOG/i) {                          if ($Row->{"ASSOCIATED PEG"}->[0] =~ m/BIOLOG/i) {
1213                                  $CurrentStats->{"Biolog gap filling reactions"}->[0]++;                                  $biologReactions++;
1214                            } elsif ($Row->{"ASSOCIATED PEG"}->[0] =~ m/GROW/i) {
1215                                    $gapFillReactions++;
1216                          } elsif ($Row->{"ASSOCIATED PEG"}->[0] =~ m/SPONTANEOUS/i) {                          } elsif ($Row->{"ASSOCIATED PEG"}->[0] =~ m/SPONTANEOUS/i) {
1217                                  $CurrentStats->{"Spontaneous"}->[0]++;                                  $spontaneousReactions++;
1218                          } 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) {
1219                                  $CurrentStats->{"Gap filling reactions"}->[0]++;                                  $autoCompleteReactions++;
1220                          } else {                          } else {
1221                                  foreach my $GeneSet (@{$Row->{"ASSOCIATED PEG"}}) {                                  foreach my $GeneSet (@{$Row->{"ASSOCIATED PEG"}}) {
1222                                          my @GeneList = split(/\+/,$GeneSet);                                          $_ = $GeneSet;
1223                                            my @GeneList = /(peg\.\d+)/g;
1224                                          foreach my $Gene (@GeneList) {                                          foreach my $Gene (@GeneList) {
1225                                                  if ($Gene =~ m/(peg\.\d+)/) {                                                  if ($Gene =~ m/(peg\.\d+)/) {
1226                                                          $GeneHash{$1} = 1;                                                          $GeneHash{$1} = 1;
# Line 1092  Line 1234 
1234          }          }
1235          my @genes = keys(%GeneHash);          my @genes = keys(%GeneHash);
1236          my @othergenes = keys(%NonpegHash);          my @othergenes = keys(%NonpegHash);
         $CurrentStats->{"Genes with reactions"}->[0] = @genes + @othergenes;  
1237    
1238          #Updating the stats stored in the table          #Setting the reaction count
1239          $self->figmodel()->database()->update_row("MODEL STATS",$CurrentStats,"Model ID");          $self->{_data}->reactions($rxntbl->size());
1240          $self->{_stats} = $CurrentStats;          #Setting the metabolite count
1241          return $CurrentStats;          $self->{_data}->compounds($cpdtbl->size());
1242            #Setting the gene count
1243            my $geneCount = @genes + @othergenes;
1244            $self->{_data}->associatedGenes($geneCount);
1245            #Setting remaining stats
1246            $self->{_data}->spontaneousReactions($spontaneousReactions);
1247            $self->{_data}->gapFillReactions($gapFillReactions);
1248            $self->{_data}->biologReactions($biologReactions);
1249            $self->{_data}->transporters($transporters);
1250            $self->{_data}->autoCompleteReactions($autoCompleteReactions);
1251            $self->{_data}->associatedSubsystemGenes($associatedSubsystemGenes);
1252            #Setting the model class
1253            my $class = "";
1254            for (my $i=0; $i < @{$self->figmodel()->config("class list")}; $i++) {
1255                    if (defined($self->figmodel()->config($self->figmodel()->config("class list")->[$i]))) {
1256                            if (defined($self->figmodel()->config($self->figmodel()->config("class list")->[$i])->{$self->id()})) {
1257                                    $class = $self->figmodel()->config("class list")->[$i];
1258                                    last;
1259                            }
1260                            if ($class eq "" && defined($self->figmodel()->config($self->figmodel()->config("class list")->[$i])->{$self->genome()})) {
1261                                    $class = $self->figmodel()->config("class list")->[$i];
1262                            }
1263                    }
1264            }
1265            if ($class eq "") {
1266                    $class = $self->figmodel()->get_genome_stats($self->genome())->{CLASS}->[0];
1267            }
1268            if ($class eq "") {
1269                    $class = "unknown";
1270            }
1271            $self->{_data}->cellwalltype($class);
1272  }  }
1273    
1274  =head3 GapFillModel  =head3 GapFillModel
# Line 1117  Line 1288 
1288          my $UniqueFilename = $self->figmodel()->filename();          my $UniqueFilename = $self->figmodel()->filename();
1289          my $StartTime = time();          my $StartTime = time();
1290    
1291          #Archiving the existing model          #Reading original reaction table
1292          $self->ArchiveModel();          my $OriginalRxn = $self->reaction_table();
1293            #Clearing the table
1294            $self->reaction_table(1);
1295    
1296          #Removing any gapfilling reactions that may be currently present in the model          #Removing any gapfilling reactions that may be currently present in the model
1297          if (!defined($donotclear) || $donotclear != 1) {          if (!defined($donotclear) || $donotclear != 1) {
1298                  my $ModelTable = $self->reaction_table();                  my $ModelTable = $self->reaction_table();
1299                  for (my $i=0; $i < $ModelTable->size(); $i++) {                  for (my $i=0; $i < $ModelTable->size(); $i++) {
1300                          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/) {
1301                                  $ModelTable->delete_row($i);                                  $ModelTable->delete_row($i);
1302                                  $i--;                                  $i--;
1303                          }                          }
# Line 1148  Line 1321 
1321                          }                          }
1322                  }                  }
1323                  $MediaTable->save($self->config("Media directory")->[0].$UniqueFilename."TestMedia.txt");                  $MediaTable->save($self->config("Media directory")->[0].$UniqueFilename."TestMedia.txt");
1324                  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";
1325                    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));
1326                  unlink($self->config("Media directory")->[0].$UniqueFilename."TestMedia.txt");                  unlink($self->config("Media directory")->[0].$UniqueFilename."TestMedia.txt");
1327          } else {          } else {
1328                  system($self->figmodel()->GenerateMFAToolkitCommandLineCall($UniqueFilename,$self->id(),undef,["GapFilling"],undef,"GapFill".$self->id().".log",undef));                  #print $self->figmodel()->GenerateMFAToolkitCommandLineCall($UniqueFilename,$self->id(),undef,["GapFilling"],{"Reactions to knockout" => $self->config("permanently knocked out reactions")->[0]},"GapFill".$self->id().".log",undef)."\n";
1329                    system($self->figmodel()->GenerateMFAToolkitCommandLineCall($UniqueFilename,$self->id(),undef,["GapFilling"],{"Reactions to knockout" => $self->config("permanently knocked out reactions")->[0]},"GapFill".$self->id().".log",undef));
1330          }          }
1331    
1332          #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
1333          my $SolutionData = $self->figmodel()->LoadProblemReport($UniqueFilename);          my $SolutionData = $self->figmodel()->LoadProblemReport($UniqueFilename);
1334    
1335          #Clearing the mfatoolkit output and log file          #Clearing the mfatoolkit output and log file
1336          $self->figmodel()->clearing_output($UniqueFilename,"GapFill".$self->id().".log");          $self->figmodel()->clearing_output($UniqueFilename,"GapFill".$self->id().".log");
1337          if (!defined($SolutionData) || $SolutionData->size() == 0) {          if (!defined($SolutionData) || $SolutionData->size() == 0) {
# Line 1191  Line 1367 
1367                                                  push(@{$ReactionList},$ID);                                                  push(@{$ReactionList},$ID);
1368                                          }                                          }
1369                                  }                                  }
1370                                  $self->figmodel()->IntegrateGrowMatchSolution($self->id(),undef,$ReactionList,$DirectionList,"GAP FILLING",0,1);                                  $self->figmodel()->IntegrateGrowMatchSolution($self->id(),undef,$ReactionList,$DirectionList,"AUTOCOMPLETION",0,1);
1371                          }                          }
1372                          last;                          last;
1373                  }                  }
1374          }          }
1375    
1376          #Updating model stats with gap filling results          #Updating model stats with gap filling results
1377          my $ElapsedTime = time() - $StartTime;          my $ElapsedTime = time() - $StartTime;
1378          $self->figmodel()->ClearDBModel($self->id(),1);          $self->reaction_table(1);
1379            $self->calculate_model_changes($OriginalRxn,"AUTOCOMPLETION");
1380    
1381          #Determining why each gap filling reaction was added          #Determining why each gap filling reaction was added
1382          $self->figmodel()->IdentifyDependancyOfGapFillingReactions($self->id(),$Media);          $self->figmodel()->IdentifyDependancyOfGapFillingReactions($self->id(),$Media);
1383          if (!defined($donotclear) || $donotclear != 1) {          if (!defined($donotclear) || $donotclear != 1) {
                 $self->figmodel()->AddBiologTransporters($self->id());  
1384                  if ($self->id() !~ m/MGRast/) {                  if ($self->id() !~ m/MGRast/) {
1385                          $self->update_stats_for_gap_filling($ElapsedTime);                          $self->update_stats_for_gap_filling($ElapsedTime);
1386                  }                  }
# Line 1218  Line 1396 
1396          return $self->success();          return $self->success();
1397  }  }
1398    
1399  =head3 datagapfill  =head3 calculate_model_changes
1400  Definition:  Definition:
1401          success()/fail() = FIGMODELmodel->datagapfill();          FIGMODELmodel->calculate_model_changes(FIGMODELTable:original reaction table,string:modification cause);
1402  Description:  Description:
1403          Run gapfilling on the input run specifications  
1404  =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));  
1405    
1406                  #Checking that the solution exists  sub calculate_model_changes {
1407                  if (!-e $self->config("MFAToolkit output directory")->[0].$UniqueFilename."/GapFillingSolutionTable.txt") {          my ($self,$originalReactions,$cause,$tbl,$version) = @_;
1408                          $self->figmodel()->error_message("FIGMODEL:GapFillingAlgorithm: Could not find MFA output file!");          my $modTime = time();
1409                          $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)) {
1410                          return undef;                  $version = $self->selected_version();
1411                  }                  }
1412                  my $GapFillResultTable = $self->figmodel()->database()->load_table($self->config("MFAToolkit output directory")->[0].$UniqueFilename."/GapFillingSolutionTable.txt",";","",0,undef);          my $user = $self->figmodel()->user();
1413                  if (defined($TansferFileSuffix)) {          #Getting the history table
1414                          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();
1415                          system("cp ".$self->config("MFAToolkit output directory")->[0].$UniqueFilename."/GapFillingReport.txt ".$self->directory().$self->id().$self->selected_version()."-".$TansferFileSuffix.".txt");          #Checking for differences
1416            if (!defined($tbl)) {
1417                    $tbl = $self->reaction_table();
1418                  }                  }
1419            for (my $i=0; $i < $tbl->size(); $i++) {
1420                  #If the system is not configured to preserve all logfiles, then the mfatoolkit output folder is deleted                  my $row = $tbl->get_row($i);
1421                  $self->figmodel()->clearing_output($UniqueFilename,"GapFilling-".$self->id().$self->selected_version()."-".$UniqueFilename.".log");                  my $orgRow = $originalReactions->get_row_by_key($row->{LOAD}->[0],"LOAD");
1422                  return $GapFillingRunSpecs;                  if (!defined($orgRow)) {
1423                            $histTbl->add_row({Reaction => [$row->{LOAD}->[0]], DirectionChange => $row->{DIRECTIONALITY}, GeneChange => $row->{"ASSOCIATED PEG"}, Action => ["ADDED"], ModificationTime => [$modTime], ModifcationCause => [$cause], User => [$user], Version => [$version]});
1424                    } else {
1425                            my $geneChanges;
1426                            my $directionChange;
1427                            if ($orgRow->{"DIRECTIONALITY"}->[0] ne $row->{"DIRECTIONALITY"}->[0]) {
1428                                    $directionChange = $orgRow->{"DIRECTIONALITY"}->[0]." to ".$row->{"DIRECTIONALITY"}->[0];
1429          }          }
1430          if (defined($TansferFileSuffix)) {                          for (my $j=0; $j < @{$row->{"ASSOCIATED PEG"}}; $j++) {
1431                  $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;
1432                                    if (defined($orgRow->{"ASSOCIATED PEG"})) {
1433                                            for (my $k=0; $k < @{$orgRow->{"ASSOCIATED PEG"}}; $k++) {
1434                                                    if ($row->{"ASSOCIATED PEG"}->[$j] eq $orgRow->{"ASSOCIATED PEG"}->[$k]) {
1435                                                            $match = 1;
1436                                                    }
1437                                            }
1438                                    }
1439                                    if ($match == 0) {
1440                                            push(@{$geneChanges},"Added ".$row->{"ASSOCIATED PEG"}->[$j]);
1441          }          }
1442          return undef;                          }
1443                            if (defined($orgRow->{"ASSOCIATED PEG"})) {
1444                                    for (my $k=0; $k < @{$orgRow->{"ASSOCIATED PEG"}}; $k++) {
1445                                            my $match = 0;
1446                                            if (defined($row->{"ASSOCIATED PEG"})) {
1447                                                    for (my $j=0; $j < @{$row->{"ASSOCIATED PEG"}}; $j++) {
1448                                                            if ($row->{"ASSOCIATED PEG"}->[$j] eq $orgRow->{"ASSOCIATED PEG"}->[$k]) {
1449                                                                    $match = 1;
1450                                                            }
1451                                                    }
1452                                            }
1453                                            if ($match == 0) {
1454                                                    push(@{$geneChanges},"Removed ".$orgRow->{"ASSOCIATED PEG"}->[$k]);
1455                                            }
1456                                    }
1457                            }
1458                            if ((defined($directionChange) && length($directionChange) > 0) || defined($geneChanges) && @{$geneChanges} > 0) {
1459                                    $histTbl->add_row({Reaction => [$row->{LOAD}->[0]], DirectionChange => [$directionChange], GeneChange => $geneChanges, Action => ["CHANGE"], ModificationTime => [$modTime], ModifcationCause => [$cause], User => [$user], Version => [$version]});
1460                            }
1461                    }
1462            }
1463            #Looking for removed reactions
1464            for (my $i=0; $i < $originalReactions->size(); $i++) {
1465                    my $row = $originalReactions->get_row($i);
1466                    my $orgRow = $tbl->get_row_by_key($row->{LOAD}->[0],"LOAD");
1467                    if (!defined($orgRow)) {
1468                            $histTbl->add_row({Reaction => [$row->{LOAD}->[0]], DirectionChange => $row->{DIRECTIONALITY}, GeneChange => $row->{"ASSOCIATED PEG"}, Action => ["REMOVED"], ModificationTime => [$modTime], ModifcationCause => [$cause], User => [$user], Version => [$version]});
1469                    }
1470            }
1471            $histTbl->save();
1472  }  }
1473    
1474  =head3 datagapgen  =head3 GapGenModel
1475  Definition:  Definition:
1476          $model->datagapgen($NumberOfProcessors,$ProcessorIndex,$Filename);          FIGMODELmodel->GapGenModel();
1477    Description:
1478            Runs the gap generation algorithm to correct a single false positive prediction. Results are loaded into a table.
1479  =cut  =cut
1480    
1481  sub datagapgen {  sub GapGenModel {
1482          my ($self,$Media,$KOList,$NoKOList,$suffix) = @_;          my ($self,$Media,$KOList,$NoKOList,$Experiment,$SolutionLimit) = @_;
1483          #Setting default values for inputs  
1484          if (!defined($NoKOList)) {          #Enforcing nonoptional arguments
1485                  $NoKOList = "none";          if (!defined($Media)) {
1486                    return undef;
1487          }          }
1488          if (!defined($KOList)) {          if (!defined($KOList)) {
1489                  $KOList = "none";                  $KOList->[0] = "none";
1490            }
1491            if (!defined($NoKOList)) {
1492                    $NoKOList->[0] = "none";
1493            }
1494            if (!defined($Experiment)) {
1495                    $Experiment= "ReactionKO";
1496            }
1497            if (!defined($SolutionLimit)) {
1498                    $SolutionLimit = "10";
1499            }
1500    
1501            #Translating the KO lists into arrays
1502            if (ref($KOList) ne "ARRAY") {
1503                    my $temp = $KOList;
1504                    $KOList = ();
1505                    push(@{$KOList},split(/[,;]/,$temp));
1506            }
1507            my $noKOHash;
1508            if (defined($NoKOList) && ref($NoKOList) ne "ARRAY") {
1509                    my $temp = $NoKOList;
1510                    $NoKOList = ();
1511                    push(@{$NoKOList},split(/[,;]/,$temp));
1512                    foreach my $rxn (@{$NoKOList}) {
1513                            $noKOHash->{$rxn} = 1;
1514                    }
1515            }
1516    
1517            #Checking if solutions exist for the input parameters
1518            $self->aquireModelLock();
1519            my $tbl = $self->load_model_table("GapGenSolutions");
1520            my $solutionRow = $tbl->get_table_by_key($Experiment,"Experiment")->get_table_by_key($Media,"Media")->get_row_by_key(join(",",@{$KOList}),"KOlist");
1521            my $solutions;
1522            if (defined($solutionRow)) {
1523                    #Checking if any solutions conform to the no KO list
1524                    foreach my $solution (@{$solutionRow->{Solutions}}) {
1525                            my @reactions = split(/,/,$solution);
1526                            my $include = 1;
1527                            foreach my $rxn (@reactions) {
1528                                    if ($rxn =~ m/(rxn\d\d\d\d\d)/) {
1529                                            if (defined($noKOHash->{$1})) {
1530                                                    $include = 0;
1531                                            }
1532                                    }
1533                            }
1534                            if ($include == 1) {
1535                                    push(@{$solutions},$solution);
1536                            }
1537                    }
1538            } else {
1539                    $solutionRow = {Media => [$Media],Experiment => [$Experiment],KOlist => [join(",",@{$KOList})]};
1540                    $tbl->add_row($solutionRow);
1541                    $self->figmodel()->database()->save_table($tbl);
1542            }
1543            $self->releaseModelLock();
1544    
1545            #Returning solution list of solutions were found
1546            if (defined($solutions) && @{$solutions} > 0) {
1547                    return $solutions;
1548          }          }
1549    
1550          #Getting unique filename          #Getting unique filename
1551          my $Filename = $self->figmodel()->filename();          my $Filename = $self->figmodel()->filename();
1552          if (!defined($suffix)) {  
                 $suffix = "-".$Media."-".$KOList."-S";  
         }  
         $KOList =~ s/,/;/g;  
         $NoKOList =~ s/,/;/g;  
1553          #Running the gap generation          #Running the gap generation
1554          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));
1555          my $ProblemReport = $self->figmodel()->LoadProblemReport($Filename);          my $ProblemReport = $self->figmodel()->LoadProblemReport($Filename);
1556          if (!defined($ProblemReport)) {          if (!defined($ProblemReport)) {
1557                  $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);
1558                  return undef;                  return undef;
1559          }          }
1560    
1561          #Clearing the output folder and log file          #Clearing the output folder and log file
1562          $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");
1563          #Scheduling the testing of this gap filling solution  
1564          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
1565            $self->aquireModelLock();
1566            $tbl = $self->load_model_table("GapGenSolutions");
1567            $solutionRow = $tbl->get_table_by_key($Experiment,"Experiment")->get_table_by_key($Media,"Media")->get_row_by_key(join(",",@{$KOList}),"KOlist");
1568          for (my $j=0; $j < $ProblemReport->size(); $j++) {          for (my $j=0; $j < $ProblemReport->size(); $j++) {
1569                  if ($ProblemReport->get_row($j)->{"Notes"}->[0] =~ m/^Recursive\sMILP\s([^)]+)/) {                  if ($ProblemReport->get_row($j)->{"Notes"}->[0] =~ m/^Recursive\sMILP\s([^)]+)/) {
1570                          my @SolutionList = split(/\|/,$1);                          my @SolutionList = split(/\|/,$1);
1571                          for (my $k=0; $k < @SolutionList; $k++) {                          for (my $k=0; $k < @SolutionList; $k++) {
1572                                  if ($SolutionList[$k] =~ m/(\d+):(.+)/) {                                  if ($SolutionList[$k] =~ m/(\d+):(.+)/) {
1573                                          $Tbl->add_row({"Experiment"=>[$Media],"Solution index"=>[$k],"Solution cost"=>[$1],"Solution reactions"=>[$2]});                                          push(@{$solutionRow->{Solutions}},$2);
1574                                            push(@{$solutions},$2);
1575                                    }
1576                            }
1577                    }
1578            }
1579            $self->figmodel()->database()->save_table($tbl);
1580            $self->releaseModelLock();
1581    
1582            return $solutions;
1583    }
1584    
1585    =head3 datagapfill
1586    Definition:
1587            success()/fail() = FIGMODELmodel->datagapfill();
1588    Description:
1589            Run gapfilling on the input run specifications
1590    =cut
1591    sub datagapfill {
1592            my ($self,$GapFillingRunSpecs,$TansferFileSuffix) = @_;
1593            my $UniqueFilename = $self->figmodel()->filename();
1594            if (defined($GapFillingRunSpecs) && @{$GapFillingRunSpecs} > 0) {
1595                    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));
1596                    #Checking that the solution exists
1597                    if (!-e $self->config("MFAToolkit output directory")->[0].$UniqueFilename."/GapFillingSolutionTable.txt") {
1598                            $self->figmodel()->error_message("FIGMODEL:GapFillingAlgorithm: Could not find MFA output file!");
1599                            $self->figmodel()->database()->print_array_to_file($self->directory().$self->id().$self->selected_version()."-GFS.txt",["Experiment;Solution index;Solution cost;Solution reactions"]);
1600                            return undef;
1601                                  }                                  }
1602                    my $GapFillResultTable = $self->figmodel()->database()->load_table($self->config("MFAToolkit output directory")->[0].$UniqueFilename."/GapFillingSolutionTable.txt",";","",0,undef);
1603                    if (defined($TansferFileSuffix)) {
1604                            system("cp ".$self->config("MFAToolkit output directory")->[0].$UniqueFilename."/GapFillingSolutionTable.txt ".$self->directory().$self->id().$self->selected_version()."-".$TansferFileSuffix.".txt");
1605                          }                          }
1606                    #If the system is not configured to preserve all logfiles, then the mfatoolkit output folder is deleted
1607                    $self->figmodel()->clearing_output($UniqueFilename,"GapFilling-".$self->id().$self->selected_version()."-".$UniqueFilename.".log");
1608                    return $GapFillResultTable;
1609                  }                  }
1610            if (defined($TansferFileSuffix)) {
1611                    $self->figmodel()->database()->print_array_to_file($self->directory().$self->id().$self->selected_version()."-".$TansferFileSuffix.".txt",["Experiment;Solution index;Solution cost;Solution reactions"]);
1612          }          }
1613          return $Tbl;          return undef;
1614  }  }
1615    
1616  =head3 TestSolutions  =head3 TestSolutions
# Line 1356  Line 1671 
1671                          push(@{$DirectionArray},$SolutionHash{$ReactionList[$k]});                          push(@{$DirectionArray},$SolutionHash{$ReactionList[$k]});
1672                  }                  }
1673                  print "Integrating solution!\n";                  print "Integrating solution!\n";
1674                  $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);
1675                  my $model = $self->get_model($self->id().$TempVersion);                  $self->PrintModelLPFile();
                 $model->PrintModelLPFile();  
1676                  #Running the model against all available experimental data                  #Running the model against all available experimental data
1677                  print "Running test model!\n";                  print "Running test model!\n";
1678                  my ($FalsePostives,$FalseNegatives,$CorrectNegatives,$CorrectPositives,$Errorvector,$HeadingVector) = $self->RunAllStudiesWithDataFast("All");                  my ($FalsePostives,$FalseNegatives,$CorrectNegatives,$CorrectPositives,$Errorvector,$HeadingVector) = $self->RunAllStudiesWithDataFast("All");
# Line 1394  Line 1708 
1708  =cut  =cut
1709  sub status {  sub status {
1710          my ($self) = @_;          my ($self) = @_;
1711          return $self->{_data}->{status}->[0];          return $self->{_data}->status();
1712  }  }
1713    
1714  =head3 message  =head3 message
# Line 1405  Line 1719 
1719  =cut  =cut
1720  sub message {  sub message {
1721          my ($self) = @_;          my ($self) = @_;
1722          return $self->{_data}->{message}->[0];          return $self->{_data}->message();
1723  }  }
1724    
1725  =head3 set_status  =head3 set_status
# Line 1420  Line 1734 
1734  =cut  =cut
1735  sub set_status {  sub set_status {
1736          my ($self,$NewStatus,$Message) = @_;          my ($self,$NewStatus,$Message) = @_;
1737            $self->{_data}->status($NewStatus);
1738          #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");  
1739          return $self->config("SUCCESS")->[0];          return $self->config("SUCCESS")->[0];
1740  }  }
1741    
# Line 1439  Line 1750 
1750  sub CreateSingleGenomeReactionList {  sub CreateSingleGenomeReactionList {
1751          my ($self,$RunGapFilling) = @_;          my ($self,$RunGapFilling) = @_;
1752    
1753            #Creating directory
1754            if ($self->owner() ne "master" && !-d $self->figmodel()->config("organism directory")->[0].$self->owner()."/") {
1755                    system("mkdir ".$self->figmodel()->config("organism directory")->[0].$self->owner()."/");
1756            } elsif ($self->owner() eq "master" && !-d $self->figmodel()->config("organism directory")->[0].$self->genome()."/") {
1757                    system("mkdir ".$self->figmodel()->config("organism directory")->[0].$self->genome()."/");
1758            }
1759            if ($self->owner() ne "master" && !-d $self->figmodel()->config("organism directory")->[0].$self->owner()."/".$self->genome()."/") {
1760                    system("mkdir ".$self->figmodel()->config("organism directory")->[0].$self->owner()."/".$self->genome()."/");
1761            }
1762    
1763          #Getting genome stats          #Getting genome stats
1764          my $genomestats = $self->figmodel()->get_genome_stats($self->genome());          my $genomestats = $self->figmodel()->get_genome_stats($self->genome());
1765          my $FeatureTable = $self->figmodel()->GetGenomeFeatureTable($self->genome());          my $FeatureTable = $self->figmodel()->GetGenomeFeatureTable($self->genome());
# Line 1453  Line 1774 
1774          }          }
1775          #Setting up needed variables          #Setting up needed variables
1776          my $OriginalModelTable = undef;          my $OriginalModelTable = undef;
1777          #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) {  
1778                  $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");  
1779                  return $self->fail();                  return $self->fail();
1780          }elsif ($Row->{status}->[0] == 1) {          }elsif ($self->status() == 1) {
1781                  $OriginalModelTable = $self->reaction_table();                  $OriginalModelTable = $self->reaction_table();
1782                  $self->ArchiveModel();                  $self->set_status(0,"Rebuilding preliminary reconstruction");
                 $Row->{status}->[0] = 0;  
                 $Row->{message}->[0] = "Rebuilding preliminary reconstruction";  
1783          } else {          } else {
1784                  $Row->{status}->[0] = 0;                  $self->set_status(0,"Preliminary reconstruction");
                 $Row->{message}->[0] = "Preliminary reconstruction";  
1785          }          }
         #Updating the status table  
         $self->figmodel()->database()->save_table($ModelTable);  
         $self->figmodel()->database()->UnlockDBTable("MODELS");  
1786          #Sorting GenomeData by gene location on the chromosome          #Sorting GenomeData by gene location on the chromosome
1787            my $ftrTbl = $self->figmodel()->database()->get_table("ROLERXNMAPPING");
1788          $FeatureTable->sort_rows("MIN LOCATION");          $FeatureTable->sort_rows("MIN LOCATION");
1789          my ($ComplexHash,$SuggestedMappings,$UnrecognizedReactions,$ReactionHash);          my ($ComplexHash,$SuggestedMappings,$UnrecognizedReactions,$ReactionHash);
1790          my %LastGenePosition;          my %LastGenePosition;
# Line 1548  Line 1856 
1856                          }                          }
1857                  }                  }
1858          }          }
   
1859          #Creating nonadjacent complexes          #Creating nonadjacent complexes
1860          my @ReactionList = keys(%{$ReactionHash});          my @ReactionList = keys(%{$ReactionHash});
1861          foreach my $Reaction (@ReactionList) {          foreach my $Reaction (@ReactionList) {
# Line 1654  Line 1961 
1961                  $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"]});
1962          }          }
1963    
1964            #Getting feature rows for features that are lumped
1965            my @rows = $ftrTbl->get_rows_by_key("2","MASTER");
1966            for (my $i=0; $i < @rows; $i++) {
1967                    my $rxn = $rows[$i]->{REACTION}->[0];
1968                    my $role = $rows[$i]->{ROLE}->[0];
1969                    my @orgrows = $FeatureTable->get_rows_by_key($role,"ROLES");
1970                    my $genes;
1971                    for (my $j=0; $j < @orgrows; $j++) {
1972                            if ($orgrows[$j]->{ID}->[0] =~ m/(peg\.\d+)/) {
1973                                    push(@{$genes},$1);
1974                            }
1975                    }
1976                    if (defined($genes) && @{$genes} > 0) {
1977                            my $row = $NewModelTable->get_row_by_key($rxn,"LOAD");
1978                            my $newGeneAssociations;
1979                            for (my $k=0; $k < @{$genes}; $k++) {
1980                                    for (my $j=0; $j < @{$row->{"ASSOCIATED PEG"}}; $j++) {
1981                                            my $peg = $genes->[$k];
1982                                            if ($row->{"ASSOCIATED PEG"}->[$j] !~ m/$peg/) {
1983                                                    push(@{$newGeneAssociations},$row->{"ASSOCIATED PEG"}->[$j]."+".$peg);
1984                                            }
1985                                    }
1986                            }
1987                            $row->{"ASSOCIATED PEG"} = $newGeneAssociations;
1988                    }
1989            }
1990    
1991          #Adding the spontaneous and universal reactions          #Adding the spontaneous and universal reactions
1992          foreach my $ReactionID (@{$self->config("spontaneous reactions")}) {          foreach my $ReactionID (@{$self->config("spontaneous reactions")}) {
1993                  #Getting the thermodynamic reversibility from the database                  #Getting the thermodynamic reversibility from the database
# Line 1673  Line 2007 
2007          }          }
2008    
2009          #Checking if a biomass reaction already exists          #Checking if a biomass reaction already exists
2010          my $BiomassReactionRow = $self->figmodel()->database()->get_row_by_key("BIOMASS TABLE",$self->id(),"MODELS");          my $BiomassReactionRow = $self->BuildSpecificBiomassReaction();
         if (!defined($BiomassReactionRow)) {  
                 $BiomassReactionRow = $self->BuildSpecificBiomassReaction();  
2011                  if (!defined($BiomassReactionRow)) {                  if (!defined($BiomassReactionRow)) {
2012                          $self->set_status(-2,"Preliminary reconstruction failed: could not generate biomass reaction");                          $self->set_status(-2,"Preliminary reconstruction failed: could not generate biomass reaction");
2013                          $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()."!");
2014                          return $self->fail();                          return $self->fail();
2015                  }                  }
         }  
2016          my $ReactionList = $BiomassReactionRow->{"ESSENTIAL REACTIONS"};          my $ReactionList = $BiomassReactionRow->{"ESSENTIAL REACTIONS"};
2017          push(@{$ReactionList},$BiomassReactionRow->{DATABASE}->[0]);          push(@{$ReactionList},$BiomassReactionRow->{DATABASE}->[0]);
2018    
# Line 1713  Line 2044 
2044                  }                  }
2045          }          }
2046    
2047            #If an original model exists, we copy the gap filling solution from that model
2048            if (defined($OriginalModelTable)) {
2049                    for (my $i=0; $i < $OriginalModelTable->size(); $i++) {
2050                            if ($OriginalModelTable->get_row($i)->{"ASSOCIATED PEG"}->[0] =~ m/GAP/ && $OriginalModelTable->get_row($i)->{"ASSOCIATED PEG"}->[0] ne "INITIAL GAP FILLING") {
2051                                    my $Row = $NewModelTable->get_row_by_key($OriginalModelTable->get_row($i)->{"LOAD"}->[0],"LOAD");
2052                                    if (!defined($Row)) {
2053                                            $NewModelTable->add_row($OriginalModelTable->get_row($i));
2054                                    }
2055                            }
2056                    }
2057            }
2058    
2059          #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
2060          if (defined($OriginalModelTable)) {          if (defined($OriginalModelTable)) {
2061                  my $PerfectMatch = 1;                  my $PerfectMatch = 1;
# Line 1772  Line 2115 
2115          #Saving the new model to file          #Saving the new model to file
2116          $self->set_status(1,"Preliminary reconstruction complete");          $self->set_status(1,"Preliminary reconstruction complete");
2117          $self->figmodel()->database()->save_table($NewModelTable);          $self->figmodel()->database()->save_table($NewModelTable);
2118          $self->{_reaction_data} = $NewModelTable;          $self->reaction_table(1);
         #Clearing the previous model from the cache  
         $self->figmodel()->ClearDBModel($self->id(),1);  
2119          #Updating the model stats table          #Updating the model stats table
2120          $self->update_stats_for_build();          $self->update_stats_for_build();
2121          $self->PrintSBMLFile();          $self->PrintSBMLFile();
2122            if (defined($OriginalModelTable)) {
2123                    $self->calculate_model_changes($OriginalModelTable,"REBUILD");
2124            }
2125    
2126          #Adding model to gapfilling queue          #Adding model to gapfilling queue
2127          if (defined($RunGapFilling) && $RunGapFilling == 1) {          if (defined($RunGapFilling) && $RunGapFilling == 1) {
# Line 1796  Line 2140 
2140    
2141  sub CreateMetaGenomeReactionList {  sub CreateMetaGenomeReactionList {
2142          my ($self) = @_;          my ($self) = @_;
   
2143          #Checking if the metagenome file exists          #Checking if the metagenome file exists
2144          if (!-e $self->config("raw MGRAST directory")->[0].$self->genome().".summary") {          if (!-e $self->config("raw MGRAST directory")->[0].$self->genome().".summary") {
2145                  $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());
2146                    return $self->fail();
2147          }          }
2148          #Loading metagenome data          #Loading metagenome data
2149          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");
2150          if (!defined($MGRASTData)) {          if (!defined($MGRASTData)) {
2151                  $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());
2152                    return $self->fail();
2153          }          }
   
2154          #Setting up needed variables          #Setting up needed variables
2155          my $OriginalModelTable = undef;          my $OriginalModelTable = undef;
   
2156          #Checking status          #Checking status
2157          if ($self->status() < 0) {          if ($self->status() < 0) {
2158                  $self->set_status(0,"Preliminary reconstruction");                  $self->set_status(0,"Preliminary reconstruction");
# Line 1821  Line 2164 
2164                  $self->ArchiveModel();                  $self->ArchiveModel();
2165                  $self->set_status(0,"Rebuilding preliminary reconstruction");                  $self->set_status(0,"Rebuilding preliminary reconstruction");
2166          }          }
2167            #Creating a hash of escores and pegs associated with each role
2168            my $rolePegHash;
2169            my $roleEscores;
2170            for (my $i=0; $i < @{$MGRASTData};$i++) {
2171                    #MD5,PEG,number of sims,role,sim e-scores,max escore,min escore,ave escore,stdev escore,ave exponent,stddev exponent
2172                    $rolePegHash->{$MGRASTData->[$i]->[3]}->{substr($MGRASTData->[$i]->[1],4)} = 1;
2173                    push(@{$roleEscores->{$MGRASTData->[$i]->[3]}},split(/;/,$MGRASTData->[$i]->[4]));
2174            }
2175          #Getting the reaction table          #Getting the reaction table
2176          my $ReactionTable = $self->figmodel()->database()->GetDBTable("REACTIONS");          my $ReactionTable = $self->figmodel()->database()->get_table("REACTIONS");
2177          #Creating model table          #Creating model table
2178          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");
2179          for (my $i=0; $i < @{$MGRASTData};$i++) {          print $ModelTable->filename();
2180                  #MD5,PEG,number of sims,role,sim e-scores          my @roles = keys(%{$rolePegHash});
2181                  my $Role = $MGRASTData->[$i]->[3];          for (my $i=0; $i < @roles; $i++) {
2182                  my $MD5 = $MGRASTData->[$i]->[0];                  my $min = -1;
2183                  my $peg = $MGRASTData->[$i]->[1];                  my $max = -1;
2184                  my $sims = $MGRASTData->[$i]->[4];                  my $count = @{$roleEscores->{$roles[$i]}};
2185                  $sims =~ s/;/,/g;                  my $ave = 0;
2186                    my $stdev = 0;
2187                    my $aveexp = 0;
2188                    my $stdevexp = 0;
2189                    for (my $j=0; $j < @{$roleEscores->{$roles[$i]}}; $j++) {
2190                            if ($roleEscores->{$roles[$i]} < $min || $min == -1) {
2191                                    $min = $roleEscores->{$roles[$i]};
2192                            }
2193                            if ($roleEscores->{$roles[$i]} > $max || $max == -1) {
2194                                    $max = $roleEscores->{$roles[$i]};
2195                            }
2196                            $ave += $roleEscores->{$roles[$i]}->[$j];
2197                            if ($roleEscores->{$roles[$i]}->[$j] =~ m/e(-\d+$)/) {
2198                                    $aveexp += $1;
2199                            }
2200                    }
2201                    $ave = $ave/$count;
2202                    $aveexp = $aveexp/$count;
2203                    for (my $j=0; $j < @{$roleEscores->{$roles[$i]}}; $j++) {
2204                            $stdev += ($roleEscores->{$roles[$i]}->[$j]-$ave)*($roleEscores->{$roles[$i]}->[$j]-$ave);
2205                            if ($roleEscores->{$roles[$i]}->[$j] =~ m/e(-\d+$)/) {
2206                                    $stdevexp += ($1-$aveexp)*($1-$aveexp);
2207                            }
2208                    }
2209                    $stdev = sqrt($stdev/$count);
2210                    $stdevexp = sqrt($stdevexp/$count);
2211                  #Checking for subsystems                  #Checking for subsystems
2212                  my $GeneSubsystems = $self->figmodel()->subsystems_of_role($Role);                  my $GeneSubsystems = $self->figmodel()->subsystems_of_role($roles[$i]);
2213                  #Checking if there are reactions associated with this role                  #Checking if there are reactions associated with this role
2214                  my $ReactionHashArrayRef = $self->figmodel()->reactions_of_role($Role);                  my $ReactionHashArrayRef = $self->figmodel()->reactions_of_role($roles[$i]);
2215                  if ($ReactionHashArrayRef != 0) {                  if ($ReactionHashArrayRef != 0) {
2216                          foreach my $Mapping (@{$ReactionHashArrayRef}) {                          foreach my $Mapping (@{$ReactionHashArrayRef}) {
2217                                  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 2223 
2223                                                                  $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"]};
2224                                                                  $ModelTable->add_row($ReactionRow);                                                                  $ModelTable->add_row($ReactionRow);
2225                                                          }                                                          }
2226                                                          push(@{$ReactionRow->{"ASSOCIATED PEG"}},substr($peg,4));                                                          my %pegHash = %{$rolePegHash->{$roles[$i]}};
2227                                                          push(@{$ReactionRow->{"REFERENCE"}},$MD5.":".$Role);                                                          if (defined($ReactionRow->{"ASSOCIATED PEG"})) {
2228                                                          push(@{$ReactionRow->{"CONFIDENCE"}},$sims);                                                                  for (my $j=0; $j < @{$ReactionRow->{"ASSOCIATED PEG"}}; $j++) {
2229                                                                            $pegHash{$ReactionRow->{"ASSOCIATED PEG"}->[$j]} = 1;
2230                                                                    }
2231                                                            }
2232                                                            delete $ReactionRow->{"ASSOCIATED PEG"};
2233                                                            push(@{$ReactionRow->{"ASSOCIATED PEG"}},keys(%pegHash));
2234                                                            push(@{$ReactionRow->{"REFERENCE"}},$count.":".$ave.":".$stdev.":".$aveexp.":".$stdevexp.":".$min.":".$max);
2235                                                          if (defined($GeneSubsystems)) {                                                          if (defined($GeneSubsystems)) {
2236                                                                  push(@{$ReactionRow->{"SUBSYSTEM"}},@{$GeneSubsystems});                                                                  push(@{$ReactionRow->{"SUBSYSTEM"}},@{$GeneSubsystems});
2237                                                          }                                                          }
# Line 1895  Line 2275 
2275          }          }
2276    
2277          #Clearing the previous model from the cache          #Clearing the previous model from the cache
2278          $self->figmodel()->ClearDBModel($self->id(),1);          $self->figmodel()->database()->ClearDBModel($self->id(),1);
2279          $ModelTable->save();          $ModelTable->save();
2280    
2281          return $self->success();          return $self->success();
# Line 1911  Line 2291 
2291  sub ArchiveModel {  sub ArchiveModel {
2292          my ($self) = @_;          my ($self) = @_;
2293    
         #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();  
         }  
   
2294          #Checking that the model file exists          #Checking that the model file exists
2295          if (!(-e $self->filename())) {          if (!(-e $self->filename())) {
2296                  $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 2341 
2341          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
2342  =cut  =cut
2343  sub run_microarray_analysis {  sub run_microarray_analysis {
2344          my ($self,$media,$jobid,$index,$genecall) = @_;          my ($self,$media,$label,$index,$genecall) = @_;
2345          $genecall =~ s/_/:/g;          $genecall =~ s/_/:/g;
2346          $genecall =~ s/\//;/g;          $genecall =~ s/\//;/g;
2347          #print "\n\n".$genecall."\n\n";          my $uniqueFilename = $self->figmodel()->filename();
2348          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";  
2349          system($command);          system($command);
2350          #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";
2351            if (-e $filename) {
2352                    my $output = $self->figmodel()->database()->load_single_column_file($filename);
2353                    if (defined($output->[0])) {
2354                            my @array = split(/;/,$output->[0]);
2355                            $self->figmodel()->clearing_output($uniqueFilename,"MicroarrayAnalysis-".$uniqueFilename.".txt");
2356                            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]);
2357                    }
2358                    print STDERR $filename." is empty!";
2359            }
2360            print STDERR $filename." not found!";
2361            $self->figmodel()->clearing_output($uniqueFilename,"MicroarrayAnalysis-".$uniqueFilename.".txt");
2362    
2363            return undef;
2364  }  }
2365    
2366  =head3 find_minimal_pathways  =head3 find_minimal_pathways
# Line 1984  Line 2370 
2370          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
2371  =cut  =cut
2372  sub find_minimal_pathways {  sub find_minimal_pathways {
2373          my ($self,$media,$objective,$solutionnum) = @_;          my ($self,$media,$objective,$solutionnum,$AllReversible,$additionalexchange) = @_;
2374    
2375          #Setting default media          #Setting default media
2376          if (!defined($media)) {          if (!defined($media)) {
# Line 1996  Line 2382 
2382                  $solutionnum = "5";                  $solutionnum = "5";
2383          }          }
2384    
2385            #Setting additional exchange fluxes
2386            if (!defined($additionalexchange) || length($additionalexchange) == 0) {
2387                    if ($self->id() eq "iAF1260") {
2388                            $additionalexchange = "cpd03422[c]:-100:100;cpd01997[c]:-100:100;cpd11416[c]:-100:0;cpd15378[c]:-100:0;cpd15486[c]:-100:0";
2389                    } else {
2390                            $additionalexchange = $self->figmodel()->config("default exchange fluxes")->[0];
2391                    }
2392            }
2393    
2394          #Translating objective          #Translating objective
2395          my $objectivestring;          my $objectivestring;
2396          if ($objective eq "ALL") {          if ($objective eq "ALL") {
# Line 2016  Line 2411 
2411                          }                          }
2412                  }                  }
2413                  for (my $i=0; $i < @objectives; $i++) {                  for (my $i=0; $i < @objectives; $i++) {
2414                          $self->find_minimal_pathways($media,$objectives[$i])                          $self->find_minimal_pathways($media,$objectives[$i]);
2415                  }                  }
2416                    return;
2417          } elsif ($objective eq "ENERGY") {          } elsif ($objective eq "ENERGY") {
2418                  $objectivestring = "MAX;FLUX;rxn00062;c;1";                  $objectivestring = "MAX;FLUX;rxn00062;c;1";
2419          } elsif ($objective =~ m/cpd\d\d\d\d\d/) {          } elsif ($objective =~ m/cpd\d\d\d\d\d/) {
2420                    if ($objective =~ m/\[(\w)\]/) {
2421                            $objectivestring = "MIN;DRAIN_FLUX;".$objective.";".$1.";1";
2422                            $additionalexchange .= ";".$objective."[".$1."]:-100:0";
2423                    } else {
2424                  $objectivestring = "MIN;DRAIN_FLUX;".$objective.";c;1";                  $objectivestring = "MIN;DRAIN_FLUX;".$objective.";c;1";
2425                            $additionalexchange .= ";".$objective."[c]:-100:0";
2426                    }
2427            } elsif ($objective =~ m/(rxn\d\d\d\d\d)/) {
2428                    my ($Reactants,$Products) = $self->figmodel()->GetReactionSubstrateData($objective);
2429                    for (my $i=0; $i < @{$Products};$i++) {
2430                            my $temp = $Products->[$i]->{"DATABASE"}->[0];
2431                            if ($additionalexchange !~ m/$temp/) {
2432                                    #$additionalexchange .= ";".$temp."[c]:-100:0";
2433                            }
2434                    }
2435                    for (my $i=0; $i < @{$Reactants};$i++) {
2436                            print $Reactants->[$i]->{"DATABASE"}->[0]." started\n";
2437                            $self->find_minimal_pathways($media,$Reactants->[$i]->{"DATABASE"}->[0],$additionalexchange);
2438                            print $Reactants->[$i]->{"DATABASE"}->[0]." done\n";
2439                    }
2440                    return;
2441          }          }
2442    
2443          #Setting additional exchange fluxes          #Adding additional drains
2444          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") {  
2445                  $additionalexchange .= ";cpd15666[c]:0:100";                  $additionalexchange .= ";cpd15666[c]:0:100";
2446          } elsif ($objective eq "cpd11493") {          } elsif ($objective eq "cpd11493" && $additionalexchange !~ m/cpd12370/) {
2447                  $additionalexchange .= ";cpd12370[c]:0:100";                  $additionalexchange .= ";cpd12370[c]:0:100";
2448          } elsif ($objective eq "cpd00166") {          } elsif ($objective eq "cpd00166" && $additionalexchange !~ m/cpd01997/) {
2449                  $additionalexchange .= ";cpd01997[c]:0:100;cpd03422[c]:0:100";                  $additionalexchange .= ";cpd01997[c]:0:100;cpd03422[c]:0:100";
2450          }          }
2451    
2452          #Running MFAToolkit          #Running MFAToolkit
2453          my $filename = $self->figmodel()->filename();          my $filename = $self->figmodel()->filename();
2454          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;
2455            if (defined($AllReversible) && $AllReversible == 1) {
2456                    $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());
2457            } else {
2458                    $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());
2459            }
2460          system($command);          system($command);
2461    
2462          #Loading problem report          #Loading problem report
# Line 2044  Line 2464 
2464          #Clearing output          #Clearing output
2465          $self->figmodel()->clearing_output($filename,"MinimalPathways-".$media."-".$self->id()."-".$objective.".txt");          $self->figmodel()->clearing_output($filename,"MinimalPathways-".$media."-".$self->id()."-".$objective.".txt");
2466          if (!defined($results)) {          if (!defined($results)) {
2467                    print STDERR $objective." pathway results not found!\n";
2468                  return;                  return;
2469          }          }
2470    
# Line 2055  Line 2476 
2476                  @Array = /\d+:([^\|]+)\|/g;                  @Array = /\d+:([^\|]+)\|/g;
2477          }          }
2478    
2479          # Storing data in a figmodel table          #Writing output to file
2480          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();  
2481  }  }
2482    
2483  =head3 calculate_growth  =head3 find_minimal_pathways
2484  Definition:  Definition:
2485          string::growth = FIGMODELmodel->calculate_growth(string:media);          int::status = FIGMODEL->find_minimal_pathways(string::media,string::objective);
2486  Description:  Description:
2487          Calculating growth in the input media          Runs microarray analysis attempting to turn off genes that are inactive in the microarray
2488  =cut  =cut
2489  sub calculate_growth {  sub find_minimal_pathways_two {
2490          my ($self,$Media) = @_;          my ($self,$media,$objective,$solutionnum,$AllReversible,$additionalexchange) = @_;
2491          my $UniqueFilename = $self->figmodel()->filename();  
2492          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
2493          my $ProblemReport = $self->figmodel()->LoadProblemReport($UniqueFilename);          if (!defined($media)) {
2494          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];  
2495                          }                          }
2496    
2497            #Setting default solution number
2498            if (!defined($solutionnum)) {
2499                    $solutionnum = "5";
2500                  }                  }
2501    
2502            #Setting additional exchange fluxes
2503            if (!defined($additionalexchange) || length($additionalexchange) == 0) {
2504                    if ($self->id() eq "iAF1260") {
2505                            $additionalexchange = "cpd03422[c]:-100:100;cpd01997[c]:-100:100;cpd11416[c]:-100:0;cpd15378[c]:-100:0;cpd15486[c]:-100:0";
2506                    } else {
2507                            $additionalexchange = $self->figmodel()->config("default exchange fluxes")->[0];
2508          }          }
         return $Result;  
2509  }  }
2510    
2511  =head3 classify_model_reactions          #Translating objective
2512  Definition:          my $objectivestring;
2513          (FIGMODELTable:Reaction classes,FIGMODELTable:Compound classes) = FIGMODELmodel->classify_model_reactions(string:media);          if ($objective eq "ALL") {
2514  Description:                  #Getting the list of universal building blocks
2515          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");
2516          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});
2517          Possible values for "Class" include:                  #Getting the nonuniversal building blocks
2518          1.) Positive: these reactions are essential in the forward direction.                  my $otherbuildingblocks = $self->config("nonuniversal building blocks");
2519          2.) Negative: these reactions are essential in the reverse direction.                  my @array = keys(%{$otherbuildingblocks});
2520          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]))) {
2521          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];
2522          5.) Variable: these reactions are nonessential and proceed in the forward or reverse direction.                          if (defined($equation)) {
2523          6.) Blocked: these reactions never carry any flux at all in the media condition tested.                                  for (my $i=0; $i < @array; $i++) {
2524          7.) Dead: these reactions are disconnected from the network.                                          if (CORE::index($equation,$array[$i]) > 0) {
2525  =cut                                                  push(@objectives,$array[$i]);
2526  sub classify_model_reactions {                                          }
2527          my ($self,$Media,$SaveChanges) = @_;                                  }
2528                            }
2529          #Getting unique file for printing model output                  }
2530          my $UniqueFilename = $self->figmodel()->filename();                  for (my $i=0; $i < @objectives; $i++) {
2531          #Running the MFAToolkit                          $self->find_minimal_pathways($media,$objectives[$i]);
2532          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()));                  }
2533          #Reading in the output bounds file                  return;
2534          my ($ReactionTB,$CompoundTB,$DeadCompounds,$DeadEndCompounds,$DeadReactions);          } elsif ($objective eq "ENERGY") {
2535          if (-e $self->config("MFAToolkit output directory")->[0].$UniqueFilename."/MFAOutput/TightBoundsReactionData0.txt") {                  $objectivestring = "MAX;FLUX;rxn00062;c;1";
2536                  $ReactionTB = $self->figmodel()->database()->load_table($self->config("MFAToolkit output directory")->[0].$UniqueFilename."/MFAOutput/TightBoundsReactionData0.txt",";","|",1,["DATABASE ID"]);          } elsif ($objective =~ m/cpd\d\d\d\d\d/) {
2537                    if ($objective =~ m/\[(\w)\]/) {
2538                            $objectivestring = "MIN;DRAIN_FLUX;".$objective.";".$1.";1";
2539                            $additionalexchange .= ";".$objective."[".$1."]:-100:0";
2540                    } else {
2541                            $objectivestring = "MIN;DRAIN_FLUX;".$objective.";c;1";
2542                            $additionalexchange .= ";".$objective."[c]:-100:0";
2543                    }
2544            } elsif ($objective =~ m/(rxn\d\d\d\d\d)/) {
2545                    my ($Reactants,$Products) = $self->figmodel()->GetReactionSubstrateData($objective);
2546                    for (my $i=0; $i < @{$Products};$i++) {
2547                            my $temp = $Products->[$i]->{"DATABASE"}->[0];
2548                            if ($additionalexchange !~ m/$temp/) {
2549                                    #$additionalexchange .= ";".$temp."[c]:-100:0";
2550                            }
2551                    }
2552                    for (my $i=0; $i < @{$Reactants};$i++) {
2553                            print $Reactants->[$i]->{"DATABASE"}->[0]." started\n";
2554                            $self->find_minimal_pathways($media,$Reactants->[$i]->{"DATABASE"}->[0],$additionalexchange);
2555                            print $Reactants->[$i]->{"DATABASE"}->[0]." done\n";
2556                    }
2557                    return;
2558            }
2559    
2560            #Adding additional drains
2561            if (($objective eq "cpd15665" || $objective eq "cpd15667" || $objective eq "cpd15668" || $objective eq "cpd15669") && $additionalexchange !~ m/cpd15666/) {
2562                    $additionalexchange .= ";cpd15666[c]:0:100";
2563            } elsif ($objective eq "cpd11493" && $additionalexchange !~ m/cpd12370/) {
2564                    $additionalexchange .= ";cpd12370[c]:0:100";
2565            } elsif ($objective eq "cpd00166" && $additionalexchange !~ m/cpd01997/) {
2566                    $additionalexchange .= ";cpd01997[c]:0:100;cpd03422[c]:0:100";
2567            }
2568    
2569            #Running MFAToolkit
2570            my $filename = $self->figmodel()->filename();
2571            my $command;
2572            if (defined($AllReversible) && $AllReversible == 1) {
2573                    $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());
2574            } else {
2575                    $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());
2576            }
2577            print $command."\n";
2578            system($command);
2579    
2580            #Loading problem report
2581            my $results = $self->figmodel()->LoadProblemReport($filename);
2582            #Clearing output
2583            $self->figmodel()->clearing_output($filename,"MinimalPathways-".$media."-".$self->id()."-".$objective.".txt");
2584            if (!defined($results)) {
2585                    print STDERR $objective." pathway results not found!\n";
2586                    return;
2587            }
2588    
2589            #Parsing output
2590            my @Array;
2591            my $row = $results->get_row(1);
2592            if (defined($row->{"Notes"}->[0])) {
2593                    $_ = $row->{"Notes"}->[0];
2594                    @Array = /\d+:([^\|]+)\|/g;
2595            }
2596    
2597            #Writing output to file
2598            $self->figmodel()->database()->print_array_to_file($self->directory()."MinimalPathways-".$media."-".$objective."-".$self->id()."-".$AllReversible."-".$self->selected_version().".txt",[join("|",@Array)]);
2599    }
2600    
2601    sub combine_minimal_pathways {
2602            my ($self) = @_;
2603    
2604            my $tbl;
2605            if (-e $self->directory()."MinimalPathwayTable-".$self->id().$self->selected_version().".tbl") {
2606                    $tbl = FIGMODELTable::load_table($self->directory()."MinimalPathwayTable-".$self->id().$self->selected_version().".tbl",";","|",0,["Objective","Media","Reversible"]);
2607            } else {
2608                    $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"],";","|");
2609            }
2610            my @files = glob($self->directory()."MinimalPathways-*");
2611            for (my $i=0; $i < @files;$i++) {
2612                    if ($files[$i] =~ m/MinimalPathways\-(\S+)\-(cpd\d\d\d\d\d)\-(\w+)\-(\d)\-/ || $files[$i] =~ m/MinimalPathways\-(\S+)\-(ENERGY)\-(\w+)\-(\d)\-/) {
2613                            my $reactions = $self->figmodel()->database()->load_single_column_file($files[$i],"");
2614                            if (defined($reactions) && @{$reactions} > 0 && length($reactions->[0]) > 0) {
2615                                    my $newrow = {"Objective"=>[$2],"Media"=>[$1],"Reversible"=>[$4]};
2616                                    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");
2617                                    if (!defined($row)) {
2618                                            $row = $tbl->add_row($newrow);
2619                                    }
2620                                    $row->{Reactions} = $self->figmodel()->database()->load_single_column_file($files[$i],"");
2621                                    delete($row->{"Shortest path"});
2622                                    delete($row->{"Number of essentials"});
2623                                    delete($row->{"Essentials"});
2624                                    delete($row->{"Length"});
2625                                    for (my $j=0; $j < @{$row->{Reactions}}; $j++) {
2626                                            my @array = split(/,/,$row->{Reactions}->[$j]);
2627                                            $row->{"Length"}->[$j] = @array;
2628                                            if (!defined($row->{"Shortest path"}->[0]) || $row->{"Length"}->[$j] < $row->{"Shortest path"}->[0]) {
2629                                                    $row->{"Shortest path"}->[0] = $row->{"Length"}->[$j];
2630                                            }
2631                                            $row->{"Number of essentials"}->[0] = 0;
2632                                            for (my $k=0; $k < @array;$k++) {
2633                                                    if ($array[$k] =~ m/(rxn\d\d\d\d\d)/) {
2634                                                            my $class = $self->get_reaction_class($1,1);
2635                                                            my $temp = $row->{Media}->[0].":Essential";
2636                                                            if ($class =~ m/$temp/) {
2637                                                                    $row->{"Number of essentials"}->[$j]++;
2638                                                                    if (!defined($row->{"Essentials"}->[$j]) && length($row->{"Essentials"}->[$j]) > 0) {
2639                                                                            $row->{"Essentials"}->[$j] = $array[$k];
2640                                                                    } else {
2641                                                                            $row->{"Essentials"}->[$j] .= ",".$array[$k];
2642                                                                    }
2643                                                            }
2644                                                    }
2645                                            }
2646                                    }
2647                            }
2648                    }
2649            }
2650            $tbl->save();
2651    }
2652    
2653    =head3 calculate_growth
2654    Definition:
2655            string::growth = FIGMODELmodel->calculate_growth(string:media);
2656    Description:
2657            Calculating growth in the input media
2658    =cut
2659    sub calculate_growth {
2660            my ($self,$Media,$outputDirectory,$InParameters,$saveLPFile) = @_;
2661            #Setting the Media
2662            if (!defined($Media) || length($Media) == 0) {
2663                    $Media = $self->autocompleteMedia();
2664            }
2665            #Setting parameters for the run
2666            my $DefaultParameters = $self->figmodel()->defaultParameters();
2667            if (defined($InParameters)) {
2668                    my @parameters = keys(%{$InParameters});
2669                    for (my $i=0; $i < @parameters; $i++) {
2670                            $DefaultParameters->{$parameters[$i]} = $InParameters->{$parameters[$i]};
2671                    }
2672            }
2673            $DefaultParameters->{"optimize metabolite production if objective is zero"} = 1;
2674            #Setting filenames
2675            my $UniqueFilename = $self->figmodel()->filename();
2676            if (!defined($outputDirectory)) {
2677                    $outputDirectory = $self->config("database message file directory")->[0];
2678            }
2679            my $fluxFilename = $outputDirectory."Fluxes-".$self->id()."-".$Media.".txt";
2680            my $cpdFluxFilename = $outputDirectory."CompoundFluxes-".$self->id()."-".$Media.".txt";
2681            #Running FBA
2682            #print $self->figmodel()->GenerateMFAToolkitCommandLineCall($UniqueFilename,$self->id(),$Media,["ProductionMFA"],$DefaultParameters,$self->id()."-".$Media."-GrowthTest.txt",undef,$self->selected_version())."\n";
2683            system($self->figmodel()->GenerateMFAToolkitCommandLineCall($UniqueFilename,$self->id(),$Media,["ProductionMFA"],$DefaultParameters,$self->id()."-".$Media."-GrowthTest.txt",undef,$self->selected_version()));
2684            #Saving LP file if requested
2685            if (defined($saveLPFile) && $saveLPFile == 1 && -e $self->figmodel()->{"MFAToolkit output directory"}->[0].$UniqueFilename."/CurrentProblem.lp") {
2686                    system("cp ".$self->figmodel()->config("MFAToolkit output directory")->[0].$UniqueFilename."/CurrentProblem.lp ".$self->directory().$self->id().".lp");
2687            }
2688            my $ProblemReport = $self->figmodel()->LoadProblemReport($UniqueFilename);
2689            my $Result;
2690            if (defined($ProblemReport)) {
2691                    my $Row = $ProblemReport->get_row(0);
2692                    if (defined($Row) && defined($Row->{"Objective"}->[0])) {
2693                            if ($Row->{"Objective"}->[0] < 0.00000001 || $Row->{"Objective"}->[0] == 1e7) {
2694                                    $Result = "NOGROWTH";
2695                                    if (defined($Row->{"Individual metabolites with zero production"}->[0]) && $Row->{"Individual metabolites with zero production"}->[0] =~ m/cpd\d\d\d\d\d/) {
2696                                            $Result .= ":".$Row->{"Individual metabolites with zero production"}->[0];
2697                                    }
2698                            } else {
2699                                    if (-e $self->figmodel()->config("MFAToolkit output directory")->[0].$UniqueFilename."/MFAOutput/SolutionReactionData0.txt") {
2700                                            system("cp ".$self->figmodel()->config("MFAToolkit output directory")->[0].$UniqueFilename."/MFAOutput/SolutionReactionData0.txt ".$fluxFilename);
2701                                            system("cp ".$self->figmodel()->config("MFAToolkit output directory")->[0].$UniqueFilename."/MFAOutput/SolutionCompoundData0.txt ".$cpdFluxFilename);
2702                                    }
2703                                    $Result = $Row->{"Objective"}->[0];
2704                            }
2705                    }
2706            }
2707            #Deleting files if necessary
2708            if ($self->figmodel()->config("preserve all log files")->[0] ne "yes") {
2709                    $self->figmodel()->cleardirectory($UniqueFilename);
2710                    unlink($self->figmodel()->config("database message file directory")->[0].$self->id()."-".$Media."-GrowthTest.txt");
2711            }
2712            #Returning result
2713            return $Result;
2714    }
2715    
2716    =head3 classify_model_reactions
2717    Definition:
2718            (FIGMODELTable:Reaction classes,FIGMODELTable:Compound classes) = FIGMODELmodel->classify_model_reactions(string:media);
2719    Description:
2720            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.
2721            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".
2722            Possible values for "Class" include:
2723            1.) Positive: these reactions are essential in the forward direction.
2724            2.) Negative: these reactions are essential in the reverse direction.
2725            3.) Positive variable: these reactions are nonessential, but they only ever proceed in the forward direction.
2726            4.) Negative variable: these reactions are nonessential, but they only ever proceed in the reverse direction.
2727            5.) Variable: these reactions are nonessential and proceed in the forward or reverse direction.
2728            6.) Blocked: these reactions never carry any flux at all in the media condition tested.
2729            7.) Dead: these reactions are disconnected from the network.
2730    =cut
2731    sub classify_model_reactions {
2732            my ($self,$Media,$SaveChanges) = @_;
2733    
2734            #Getting unique file for printing model output
2735            my $UniqueFilename = $self->figmodel()->filename();
2736            #Running the MFAToolkit
2737            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()));
2738            #Reading in the output bounds file
2739            my ($ReactionTB,$CompoundTB,$DeadCompounds,$DeadEndCompounds,$DeadReactions);
2740            if (-e $self->config("MFAToolkit output directory")->[0].$UniqueFilename."/MFAOutput/TightBoundsReactionData0.txt") {
2741                    $ReactionTB = $self->figmodel()->database()->load_table($self->config("MFAToolkit output directory")->[0].$UniqueFilename."/MFAOutput/TightBoundsReactionData0.txt",";","|",1,["DATABASE ID"]);
2742          }          }
2743          if (-e $self->config("MFAToolkit output directory")->[0].$UniqueFilename."/MFAOutput/TightBoundsCompoundData0.txt") {          if (-e $self->config("MFAToolkit output directory")->[0].$UniqueFilename."/MFAOutput/TightBoundsCompoundData0.txt") {
2744                  $CompoundTB = $self->figmodel()->database()->load_table($self->config("MFAToolkit output directory")->[0].$UniqueFilename."/MFAOutput/TightBoundsCompoundData0.txt",";","|",1,["DATABASE ID"]);                  $CompoundTB = $self->figmodel()->database()->load_table($self->config("MFAToolkit output directory")->[0].$UniqueFilename."/MFAOutput/TightBoundsCompoundData0.txt",";","|",1,["DATABASE ID"]);
# Line 2288  Line 2909 
2909    
2910          #Running simulations          #Running simulations
2911          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";  
2912          #Parsing the results          #Parsing the results
2913          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);
2914          if (!defined($Results)) {          if (!defined($Results)) {
# Line 2695  Line 3315 
3315                                          if (length($GapFillingRunSpecs) > 0) {                                          if (length($GapFillingRunSpecs) > 0) {
3316                                                  $GapFillingRunSpecs .= ";";                                                  $GapFillingRunSpecs .= ";";
3317                                          }                                          }
3318                                          $GapFillingRunSpecs .= $HeadingDataArray[2].":".$HeadingDataArray[1].".txt:".$HeadingDataArray[3];                                          $GapFillingRunSpecs .= $HeadingDataArray[2].":".$HeadingDataArray[1].":".$HeadingDataArray[3];
3319                                  } else {                                  } else {
3320                                          $SolutionExistedCount++;                                          $SolutionExistedCount++;
3321                                  }                                  }
# Line 2720  Line 3340 
3340          my $SolutionsFound = 0;          my $SolutionsFound = 0;
3341          my $GapFillingArray;          my $GapFillingArray;
3342          push(@{$GapFillingArray},split(/;/,$GapFillingRunSpecs));          push(@{$GapFillingArray},split(/;/,$GapFillingRunSpecs));
3343          $self->datagapfill($GapFillingArray);          my $GapFillingResults = $self->datagapfill($GapFillingArray,"GFS");
3344            if (defined($GapFillingResults)) {
3345                    $SolutionsFound = 1;
3346            }
3347    
3348          if (defined($RescuedPreviousResults) && @{$RescuedPreviousResults} > 0) {          if (defined($RescuedPreviousResults) && @{$RescuedPreviousResults} > 0) {
3349                  #Printing previous solutions to GFS file                  #Printing previous solutions to GFS file
# Line 2743  Line 3366 
3366          return $self->success();          return $self->success();
3367  }  }
3368    
3369    =head3 SolutionReconciliation
3370    Definition:
3371            FIGMODELmodel->SolutionReconciliation();
3372    Description:
3373            This is a wrapper for running the solution reconciliation algorithm on any model in the database.
3374            The algorithm performs a reconciliation of any gap filling solutions to identify the combination of solutions that results in the optimal model.
3375            This function prints out one output file in the Model directory: ReconciliationOutput.txt: this is a summary of the results of the reconciliation analysis
3376    =cut
3377    
3378    sub SolutionReconciliation {
3379            my ($self,$GapFill,$Stage) = @_;
3380    
3381            #Setting the output filenames
3382            my $OutputFilename;
3383            my $OutputFilenameTwo;
3384            if ($GapFill == 1) {
3385                    $OutputFilename = $self->directory().$self->id().$self->selected_version()."-GFReconciliation.txt";
3386                    $OutputFilenameTwo = $self->directory().$self->id().$self->selected_version()."-GFSRS.txt";
3387            } else {
3388                    $OutputFilename = $self->directory().$self->id().$self->selected_version()."-GGReconciliation.txt";
3389                    $OutputFilenameTwo = $self->directory().$self->id().$self->selected_version()."-GGSRS.txt";
3390            }
3391    
3392            #In stage one, we run the reconciliation and create a test file to check combined solution performance
3393            if (!defined($Stage) || $Stage == 1) {
3394                    my $GrowMatchTable = $self->figmodel()->database()->LockDBTable("GROWMATCH TABLE");
3395                    my $Row = $GrowMatchTable->get_row_by_key($self->genome(),"ORGANISM",1);
3396                    $Row->{"GF RECONCILATION TIMING"}->[0] = time()."-";
3397                    $GrowMatchTable->save();
3398                    $self->figmodel()->database()->UnlockDBTable("GROWMATCH TABLE");
3399    
3400                    #Getting a unique filename
3401                    my $UniqueFilename = $self->figmodel()->filename();
3402    
3403                    #Copying over the necessary files
3404                    if ($GapFill == 1) {
3405                            if (!-e $self->directory().$self->id().$self->selected_version()."-GFEM.txt") {
3406                                    print STDERR "FIGMODEL:SolutionReconciliation:".$self->directory().$self->id().$self->selected_version()."-GFEM.txt file not found. Could not reconcile!";
3407                                    return 0;
3408                            }
3409                            if (!-e $self->directory().$self->id().$self->selected_version()."-OPEM.txt") {
3410                                    print STDERR "FIGMODEL:SolutionReconciliation:".$self->directory().$self->id().$self->selected_version()."-OPEM.txt file not found. Could not reconcile!";
3411                                    return 0;
3412                            }
3413                            system("cp ".$self->directory().$self->id().$self->selected_version()."-GFEM.txt ".$self->figmodel()->config("MFAToolkit input files")->[0].$UniqueFilename."-GFEM.txt");
3414                            system("cp ".$self->directory().$self->id().$self->selected_version()."-OPEM.txt ".$self->figmodel()->config("MFAToolkit input files")->[0].$UniqueFilename."-OPEM.txt");
3415                            #Backing up and deleting the existing reconciliation file
3416                            if (-e $OutputFilename) {
3417                                    system("cp ".$OutputFilename." ".$self->directory().$self->id().$self->selected_version()."-OldGFReconciliation.txt");
3418                                    unlink($OutputFilename);
3419                            }
3420                    } else {
3421                            if (!-e $self->directory().$self->id().$self->selected_version()."-GGEM.txt") {
3422                                    print STDERR "FIGMODEL:SolutionReconciliation:".$self->directory().$self->id().$self->selected_version()."-GGEM.txt file not found. Could not reconcile!";
3423                                    return 0;
3424                            }
3425                            if (!-e $self->directory().$self->id().$self->selected_version()."-GGOPEM.txt") {
3426                                    print STDERR "FIGMODEL:SolutionReconciliation:".$self->directory().$self->id().$self->selected_version()."-GGOPEM.txt file not found. Could not reconcile!";
3427                                    return 0;
3428                            }
3429                            system("cp ".$self->directory().$self->id().$self->selected_version()."-GGEM.txt ".$self->figmodel()->config("MFAToolkit input files")->[0].$UniqueFilename."-GGEM.txt");
3430                            system("cp ".$self->directory().$self->id().$self->selected_version()."-GGOPEM.txt ".$self->figmodel()->config("MFAToolkit input files")->[0].$UniqueFilename."-OPEM.txt");
3431                            #Backing up and deleting the existing reconciliation file
3432                            if (-e $OutputFilename) {
3433                                    system("cp ".$OutputFilename." ".$self->directory().$self->id().$self->selected_version()."-OldGGReconciliation.txt");
3434                                    unlink($OutputFilename);
3435                            }
3436                    }
3437    
3438                    #Running the reconciliation
3439                    system($self->figmodel()->GenerateMFAToolkitCommandLineCall($UniqueFilename,$self->id(),"NONE",["SolutionReconciliation"],{"Solution data for model optimization" => $UniqueFilename},"Reconciliation".$UniqueFilename.".log",undef,$self->selected_version()));
3440                    $GrowMatchTable = $self->figmodel()->database()->LockDBTable("GROWMATCH TABLE");
3441                    $Row = $GrowMatchTable->get_row_by_key($self->genome(),"ORGANISM",1);
3442                    $Row->{"GF RECONCILATION TIMING"}->[0] .= time();
3443                    $GrowMatchTable->save();
3444                    $self->figmodel()->database()->UnlockDBTable("GROWMATCH TABLE");
3445    
3446                    #Loading the problem report from the reconciliation run
3447                    my $ReconciliatonOutput = $self->figmodel()->LoadProblemReport($UniqueFilename);
3448                    print $UniqueFilename."\n";
3449                    #Clearing output files
3450                    $self->figmodel()->clearing_output($UniqueFilename,"Reconciliation".$UniqueFilename.".log");
3451                    $ReconciliatonOutput->save("/home/chenry/Test.txt");
3452    
3453                    #Checking the a problem report was found and was loaded
3454                    if (!defined($ReconciliatonOutput) || $ReconciliatonOutput->size() < 1 || !defined($ReconciliatonOutput->get_row(0)->{"Notes"}->[0])) {
3455                            print STDERR "FIGMODEL:SolutionReconciliation: MFAToolkit output from SolutionReconciliation of ".$self->id()." not found!\n\n";
3456                            return 0;
3457                    }
3458    
3459                    #Processing the solutions
3460                    my $SolutionCount = 0;
3461                    my $ReactionSetHash;
3462                    my $SingleReactionHash;
3463                    my $ReactionDataHash;
3464                    for (my $n=0; $n < $ReconciliatonOutput->size(); $n++) {
3465                            if (defined($ReconciliatonOutput->get_row($n)->{"Notes"}->[0]) && $ReconciliatonOutput->get_row($n)->{"Notes"}->[0] =~ m/^Recursive\sMILP\s([^;]+)/) {
3466                                    #Breaking up the solution into reaction sets
3467                                    my @ReactionSets = split(/\|/,$1);
3468                                    #Creating reaction lists for each set
3469                                    my $SolutionHash;
3470                                    for (my $i=0; $i < @ReactionSets; $i++) {
3471                                            if (length($ReactionSets[$i]) > 0) {
3472                                                    my @Alternatives = split(/:/,$ReactionSets[$i]);
3473                                                    for (my $j=1; $j < @Alternatives; $j++) {
3474                                                            if (length($Alternatives[$j]) > 0) {
3475                                                                    push(@{$SolutionHash->{$Alternatives[$j]}},$Alternatives[0]);
3476                                                            }
3477                                                    }
3478                                                    if (@Alternatives == 1) {
3479                                                            $SingleReactionHash->{$Alternatives[0]}->{$SolutionCount} = 1;
3480                                                            if (!defined($SingleReactionHash->{$Alternatives[0]}->{"COUNT"})) {
3481                                                                    $SingleReactionHash->{$Alternatives[0]}->{"COUNT"} = 0;
3482                                                            }
3483                                                            $SingleReactionHash->{$Alternatives[0]}->{"COUNT"}++;
3484                                                    }
3485                                            }
3486                                    }
3487                                    #Identifying reactions sets and storing the sets in the reactions set hash
3488                                    foreach my $Solution (keys(%{$SolutionHash})) {
3489                                            my $SetKey = join(",",sort(@{$SolutionHash->{$Solution}}));
3490                                            if (!defined($ReactionSetHash->{$SetKey}->{$SetKey}->{$SolutionCount})) {
3491                                                    $ReactionSetHash->{$SetKey}->{$SetKey}->{$SolutionCount} = 1;
3492                                                    if (!defined($ReactionSetHash->{$SetKey}->{$SetKey}->{"COUNT"})) {
3493                                                            $ReactionSetHash->{$SetKey}->{$SetKey}->{"COUNT"} = 0;
3494                                                    }
3495                                                    $ReactionSetHash->{$SetKey}->{$SetKey}->{"COUNT"}++;
3496                                            }
3497                                            $ReactionSetHash->{$SetKey}->{$Solution}->{$SolutionCount} = 1;
3498                                            if (!defined($ReactionSetHash->{$SetKey}->{$Solution}->{"COUNT"})) {
3499                                                    $ReactionSetHash->{$SetKey}->{$Solution}->{"COUNT"} = 0;
3500                                            }
3501                                            $ReactionSetHash->{$SetKey}->{$Solution}->{"COUNT"}++;
3502                                    }
3503                                    $SolutionCount++;
3504                            }
3505                    }
3506    
3507                    #Handling the scenario where no solutions were found
3508                    if ($SolutionCount == 0) {
3509                            print STDERR "FIGMODEL:SolutionReconciliation: Reconciliation unsuccessful. No solution found.\n\n";
3510                            return 0;
3511                    }
3512    
3513                    #Printing results without solution performance figures. Also printing solution test file
3514                    open (RECONCILIATION, ">$OutputFilename");
3515                    #Printing the file heading
3516                    print RECONCILIATION "DATABASE;DEFINITION;REVERSIBLITY;DELTAG;DIRECTION;NUMBER OF SOLUTIONS";
3517                    for (my $i=0; $i < $SolutionCount; $i++) {
3518                            print RECONCILIATION ";Solution ".$i;
3519                    }
3520                    print RECONCILIATION "\n";
3521                    #Printing the singlet reactions first
3522                    my $Solutions;
3523                    print RECONCILIATION "SINGLET REACTIONS\n";
3524                    my @SingletReactions = keys(%{$SingleReactionHash});
3525                    for (my $j=0; $j < $SolutionCount; $j++) {
3526                            $Solutions->[$j]->{"BASE"} = $j;
3527                    }
3528                    for (my $i=0; $i < @SingletReactions; $i++) {
3529                            my $ReactionData;
3530                            if (defined($ReactionDataHash->{$SingletReactions[$i]})) {
3531                                    $ReactionData = $ReactionDataHash->{$SingletReactions[$i]};
3532                            } else {
3533                                    my $Direction = substr($SingletReactions[$i],0,1);
3534                                    if ($Direction eq "+") {
3535                                            $Direction = "=>";
3536                                    } else {
3537                                            $Direction = "<=";
3538                                    }
3539                                    my $Reaction = substr($SingletReactions[$i],1);
3540                                    $ReactionData = FIGMODELObject->load($self->figmodel()->config("reaction directory")->[0].$Reaction,"\t");
3541                                    $ReactionData->{"DIRECTIONS"}->[0] = $Direction;
3542                                    $ReactionData->{"REACTIONS"}->[0] = $Reaction;
3543                                    if (!defined($ReactionData->{"DEFINITION"}->[0])) {
3544                                            $ReactionData->{"DEFINITION"}->[0] = "UNKNOWN";
3545                                    }
3546                                    if (!defined($ReactionData->{"THERMODYNAMIC REVERSIBILITY"}->[0])) {
3547                                            $ReactionData->{"THERMODYNAMIC REVERSIBILITY"}->[0] = "UNKNOWN";
3548                                    }
3549                                    if (!defined($ReactionData->{"DELTAG"}->[0])) {
3550                                            $ReactionData->{"DELTAG"}->[0] = "UNKNOWN";
3551                                    }
3552                                    $ReactionDataHash->{$SingletReactions[$i]} = $ReactionData;
3553                            }
3554                            print RECONCILIATION $ReactionData->{"REACTIONS"}->[0].";".$ReactionData->{"DEFINITION"}->[0].";".$ReactionData->{"THERMODYNAMIC REVERSIBILITY"}->[0].";".$ReactionData->{"DELTAG"}->[0].";".$ReactionData->{"DIRECTIONS"}->[0].";".$SingleReactionHash->{$SingletReactions[$i]}->{"COUNT"};
3555                            for (my $j=0; $j < $SolutionCount; $j++) {
3556                                    print RECONCILIATION ";";
3557                                    if (defined($SingleReactionHash->{$SingletReactions[$i]}->{$j})) {
3558                                            $Solutions->[$j]->{$SingletReactions[$i]} = 1;
3559                                            $Solutions->[$j]->{"BASE"} = $j;
3560                                            print RECONCILIATION "|".$j."|";
3561                                    }
3562                            }
3563                            print RECONCILIATION "\n";
3564                    }
3565                    #Printing the reaction sets with alternatives
3566                    print RECONCILIATION "Reaction sets with alternatives\n";
3567                    my @ReactionSets = keys(%{$ReactionSetHash});
3568                    foreach my $ReactionSet (@ReactionSets) {
3569                            my $NewSolutions;
3570                            my $BaseReactions;
3571                            my $AltList = [$ReactionSet];
3572                            push(@{$AltList},keys(%{$ReactionSetHash->{$ReactionSet}}));
3573                            for (my $j=0; $j < @{$AltList}; $j++) {
3574                                    my $CurrentNewSolutions;
3575                                    my $Index;
3576                                    if ($j == 0) {
3577                                            print RECONCILIATION "NEW SET\n";
3578                                    } elsif ($AltList->[$j] ne $ReactionSet) {
3579                                            print RECONCILIATION "ALTERNATIVE SET\n";
3580                                            #For each base solution in which this set is represented, we copy the base solution to the new solution
3581                                            my $NewSolutionCount = 0;
3582                                            for (my $k=0; $k < $SolutionCount; $k++) {
3583                                                    if (defined($ReactionSetHash->{$ReactionSet}->{$AltList->[$j]}->{$k})) {
3584                                                            if (defined($Solutions)) {
3585                                                                    $Index->{$k} = @{$Solutions} + $NewSolutionCount;
3586                                                            } else {
3587                                                                    $Index->{$k} = $NewSolutionCount;
3588                                                            }
3589                                                            if (defined($NewSolutions) && @{$NewSolutions} > 0) {
3590                                                                    $Index->{$k} += @{$NewSolutions};
3591                                                            }
3592                                                            $CurrentNewSolutions->[$NewSolutionCount] = {};
3593                                                            foreach my $Reaction (keys(%{$Solutions->[$k]})) {
3594                                                                    $CurrentNewSolutions->[$NewSolutionCount]->{$Reaction} = $Solutions->[$k]->{$Reaction};
3595                                                            }
3596                                                            $NewSolutionCount++;
3597                                                    }
3598                                            }
3599                                    }
3600                                    if ($j == 0 || $AltList->[$j] ne $ReactionSet) {
3601                                            my @SingletReactions = split(/,/,$AltList->[$j]);
3602                                            for (my $i=0; $i < @SingletReactions; $i++) {
3603                                                    #Adding base reactions to base solutions and set reactions the new solutions
3604                                                    if ($j == 0) {
3605                                                            push(@{$BaseReactions},$SingletReactions[$i]);
3606                                                    } else {
3607                                                            for (my $k=0; $k < @{$CurrentNewSolutions}; $k++) {
3608                                                                    $CurrentNewSolutions->[$k]->{$SingletReactions[$i]} = 1;
3609                                                            }
3610                                                    }
3611                                                    #Getting reaction data and printing reaction in output file
3612                                                    my $ReactionData;
3613                                                    if (defined($ReactionDataHash->{$SingletReactions[$i]})) {
3614                                                            $ReactionData = $ReactionDataHash->{$SingletReactions[$i]};
3615                                                    } else {
3616                                                            my $Direction = substr($SingletReactions[$i],0,1);
3617                                                            if ($Direction eq "+") {
3618                                                                    $Direction = "=>";
3619                                                            } else {
3620                                                                    $Direction = "<=";
3621                                                            }
3622                                                            my $Reaction = substr($SingletReactions[$i],1);
3623                                                            $ReactionData = FIGMODELObject->load($self->figmodel()->config("reaction directory")->[0].$Reaction,"\t");
3624                                                            $ReactionData->{"DIRECTIONS"}->[0] = $Direction;
3625                                                            $ReactionData->{"REACTIONS"}->[0] = $Reaction;
3626                                                            if (!defined($ReactionData->{"DEFINITION"}->[0])) {
3627                                                                    $ReactionData->{"DEFINITION"}->[0] = "UNKNOWN";
3628                                                            }
3629                                                            if (!defined($ReactionData->{"THERMODYNAMIC REVERSIBILITY"}->[0])) {
3630                                                                    $ReactionData->{"THERMODYNAMIC REVERSIBILITY"}->[0] = "UNKNOWN";
3631                                                            }
3632                                                            if (!defined($ReactionData->{"DELTAG"}->[0])) {
3633                                                                    $ReactionData->{"DELTAG"}->[0] = "UNKNOWN";
3634                                                            }
3635                                                            $ReactionDataHash->{$SingletReactions[$i]} = $ReactionData;
3636                                                    }
3637                                                    print RECONCILIATION $ReactionData->{"REACTIONS"}->[0].";".$ReactionData->{"DEFINITION"}->[0].";".$ReactionData->{"THERMODYNAMIC REVERSIBILITY"}->[0].";".$ReactionData->{"DELTAG"}->[0].";".$ReactionData->{"DIRECTIONS"}->[0].";".$ReactionSetHash->{$ReactionSet}->{$AltList->[$j]}->{"COUNT"};
3638                                                    for (my $k=0; $k < $SolutionCount; $k++) {
3639                                                            print RECONCILIATION ";";
3640                                                            if (defined($ReactionSetHash->{$ReactionSet}->{$AltList->[$j]}->{$k})) {
3641                                                                    if ($j == 0) {
3642                                                                            print RECONCILIATION "|".$k."|";
3643                                                                    } else {
3644                                                                            print RECONCILIATION "|".$Index->{$k}."|";
3645                                                                    }
3646                                                            }
3647                                                    }
3648                                                    print RECONCILIATION "\n";
3649                                            }
3650                                            #Adding the current new solutions to the new solutions array
3651                                            if (defined($CurrentNewSolutions) && @{$CurrentNewSolutions} > 0) {
3652                                                    push(@{$NewSolutions},@{$CurrentNewSolutions});
3653                                            }
3654                                    }
3655                            }
3656                            #Adding the base reactions to all existing solutions
3657                            for (my $j=0; $j < @{$Solutions}; $j++) {
3658                                    if (defined($ReactionSetHash->{$ReactionSet}->{$ReactionSet}->{$Solutions->[$j]->{"BASE"}})) {
3659                                            foreach my $SingleReaction (@{$BaseReactions}) {
3660                                                    $Solutions->[$j]->{$SingleReaction} = 1;
3661                                            }
3662                                    }
3663                            }
3664                            #Adding the new solutions to the set of existing solutions
3665                            push(@{$Solutions},@{$NewSolutions});
3666                    }
3667                    close(RECONCILIATION);
3668                    #Now printing a file that defines all of the solutions in a format the testsolutions function understands
3669                    open (RECONCILIATION, ">$OutputFilenameTwo");
3670                    print RECONCILIATION "Experiment;Solution index;Solution cost;Solution reactions\n";
3671                    for (my $i=0; $i < @{$Solutions}; $i++) {
3672                            delete($Solutions->[$i]->{"BASE"});
3673                            print RECONCILIATION "SR".$i.";".$i.";10;".join(",",keys(%{$Solutions->[$i]}))."\n";
3674                    }
3675                    close(RECONCILIATION);
3676    
3677                    $GrowMatchTable = $self->figmodel()->database()->LockDBTable("GROWMATCH TABLE");
3678                    $Row = $GrowMatchTable->get_row_by_key($self->genome(),"ORGANISM",1);
3679                    $Row->{"GF RECON TESTING TIMING"}->[0] = time()."-";
3680                    $Row->{"GF RECON SOLUTIONS"}->[0] = @{$Solutions};
3681                    $GrowMatchTable->save();
3682                    $self->figmodel()->database()->UnlockDBTable("GROWMATCH TABLE");
3683    
3684                    #Scheduling the solution testing
3685                    if ($GapFill == 1) {
3686                            system($self->figmodel()->config("scheduler executable")->[0]." \"add:testsolutions?".$self->id().$self->selected_version()."?-1?GFSR:BACK:fast:QSUB\"");
3687                    } else {
3688                            system($self->figmodel()->config("scheduler executable")->[0]." \"add:testsolutions?".$self->id().$self->selected_version()."?-1?GGSR:BACK:fast:QSUB\"");
3689                    }
3690            } else {
3691                    #Reading in the solution testing results
3692                    my $Data;
3693                    if ($GapFill == 1) {
3694                            $Data = $self->figmodel()->database()->load_single_column_file($self->directory().$self->id().$self->selected_version()."-GFSREM.txt","");
3695                    } else {
3696                            $Data = $self->figmodel()->database()->load_single_column_file($self->directory().$self->id().$self->selected_version()."-GGSREM.txt","");
3697                    }
3698    
3699                    #Reading in the preliminate reconciliation report
3700                    my $OutputData = $self->figmodel()->database()->load_single_column_file($OutputFilename,"");
3701                    #Replacing the file tags with actual performance data
3702                    my $Count = 0;
3703                    for (my $i=0; $i < @{$Data}; $i++) {
3704                            if ($Data->[$i] =~ m/^SR(\d+);.+;(\d+\/\d+);/) {
3705                                    my $Index = $1;
3706                                    my $Performance = $Index."/".$2;
3707                                    for (my $j=0; $j < @{$OutputData}; $j++) {
3708                                            $OutputData->[$j] =~ s/\|$Index\|/$Performance/g;
3709                                    }
3710                            }
3711                    }
3712                    $self->figmodel()->database()->print_array_to_file($OutputFilename,$OutputData);
3713    
3714                    my $GrowMatchTable = $self->figmodel()->database()->LockDBTable("GROWMATCH TABLE");
3715                    my $Row = $GrowMatchTable->get_row_by_key($self->genome(),"ORGANISM",1);
3716                    $Row->{"GF RECON TESTING TIMING"}->[0] .= time();
3717                    $GrowMatchTable->save();
3718                    $self->figmodel()->database()->UnlockDBTable("GROWMATCH TABLE");
3719            }
3720    
3721            return 1;
3722    }
3723    
3724  =head3 BuildSpecificBiomassReaction  =head3 BuildSpecificBiomassReaction
3725  Definition:  Definition:
3726          FIGMODELmodel->BuildSpecificBiomassReaction();          FIGMODELmodel->BuildSpecificBiomassReaction();
# Line 2755  Line 3733 
3733          my $OrganismID = $self->genome();          my $OrganismID = $self->genome();
3734          #Checking for a biomass override          #Checking for a biomass override
3735          if (defined($self->config("biomass reaction override")->{$OrganismID})) {          if (defined($self->config("biomass reaction override")->{$OrganismID})) {
3736                  $biomassrxn = $self->config("biomass reaction override")->{$OrganismID};                  my $biomassID = $self->config("biomass reaction override")->{$OrganismID};
3737                  print "Overriding biomass template and selecting ".$biomassrxn." for ".$OrganismID.".\n";                  my $tbl = $self->database()->get_table("BIOMASS",1);
3738                    $biomassrxn = $tbl->get_row_by_key($biomassID,"DATABASE");
3739                    print "Overriding biomass template and selecting ".$biomassID." for ".$OrganismID.".\n";
3740          } else {#Creating biomass reaction from the template          } else {#Creating biomass reaction from the template
3741                  #Getting the genome stats                  #Getting the genome stats
3742                  my $genomestats = $self->figmodel()->get_genome_stats($self->genome());                  my $genomestats = $self->figmodel()->get_genome_stats($self->genome());
# Line 3047  Line 4027 
4027    
4028                  #Adding the biomass equation to the biomass table                  #Adding the biomass equation to the biomass table
4029                  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());
4030                  $biomassrxn = $NewRow->{DATABASE}->[0];                  $biomassrxn = $NewRow;
                 print $biomassrxn."\n";  
4031          }          }
4032          print $biomassrxn."\n";          return $biomassrxn;
         my $BiomassRow = $self->figmodel()->add_model_to_biomass_reaction($biomassrxn,$self->id());  
         return $BiomassRow;  
4033  }  }
4034    
4035  =head3 PrintSBMLFile  =head3 PrintSBMLFile
# Line 3065  Line 4042 
4042          my($self) = @_;          my($self) = @_;
4043    
4044          #Opening the SBML file for printing          #Opening the SBML file for printing
4045          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";  
         }  
4046          if (!open (SBMLOUTPUT, ">$Filename")) {          if (!open (SBMLOUTPUT, ">$Filename")) {
4047                  return;                  return;
4048          }          }
4049    
4050          #Loading and parsing the model data          #Loading and parsing the model data
4051          my $ModelTable = $self->reaction_table();          my $mdlTbl = $self->reaction_table();
4052          if (!defined($ModelTable) || !defined($ModelTable->{"array"})) {          if (!defined($mdlTbl) || !defined($mdlTbl->{"array"})) {
4053                  print "Failed to load ".$self->id()."\n";                  return $self->fail();
                 return;  
4054          }          }
4055            my $rxnTbl = $self->figmodel()->database()->get_table("REACTIONS");
4056            my $bioTbl = $self->figmodel()->database()->get_table("BIOMASS");
4057            my $cpdTbl = $self->figmodel()->database()->get_table("COMPOUNDS");
4058            my $cmpTbl = $self->figmodel()->database()->get_table("COMPARTMENTS");
4059    
4060          #Adding intracellular metabolites that also need exchange fluxes to the exchange hash          #Adding intracellular metabolites that also need exchange fluxes to the exchange hash
4061          my $ExchangeHash = {"cpd11416" => "c"};          my $ExchangeHash = {"cpd11416" => "c"};
   
4062          my %CompartmentsPresent;          my %CompartmentsPresent;
4063          $CompartmentsPresent{"c"} = 1;          $CompartmentsPresent{"c"} = 1;
4064          my %CompoundList;          my %CompoundList;
4065          my @ReactionList;          my @ReactionList;
4066          my $ReactionTable = $self->figmodel()->database()->GetDBTable("REACTIONS");          for (my $i=0; $i < $mdlTbl->size(); $i++) {
4067          for (my $i=0; $i < $ModelTable->size(); $i++) {                  my $Reaction = $mdlTbl->get_row($i)->{"LOAD"}->[0];
4068                  my $Reaction = $ModelTable->get_row($i)->{"LOAD"}->[0];                  my $row = $rxnTbl->get_row_by_key($Reaction,"DATABASE");
4069                  if (defined($ReactionTable->get_row_by_key($Reaction,"DATABASE")) && defined($ReactionTable->get_row_by_key($Reaction,"DATABASE")->{"EQUATION"}->[0])) {                  if (!defined($row)) {
4070                            $row = $bioTbl->get_row_by_key($Reaction,"DATABASE");
4071                            if (!defined($row)) {
4072                                    next;
4073                            }
4074                    }
4075                    if (!defined($row->{"EQUATION"}->[0])) {
4076                            next;
4077                    }
4078                          push(@ReactionList,$Reaction);                          push(@ReactionList,$Reaction);
4079                          $_ = $ReactionTable->get_row_by_key($Reaction,"DATABASE")->{"EQUATION"}->[0];                  $_ = $row->{"EQUATION"}->[0];
4080                          my @MatchArray = /(cpd\d\d\d\d\d)/g;                          my @MatchArray = /(cpd\d\d\d\d\d)/g;
4081                          for (my $j=0; $j < @MatchArray; $j++) {                          for (my $j=0; $j < @MatchArray; $j++) {
4082                                  $CompoundList{$MatchArray[$j]}->{"c"} = 1;                                  $CompoundList{$MatchArray[$j]}->{"c"} = 1;
4083                          }                          }
4084                          $_ = $ReactionTable->get_row_by_key($Reaction,"DATABASE")->{"EQUATION"}->[0];                  $_ = $row->{"EQUATION"}->[0];
4085                          @MatchArray = /(cpd\d\d\d\d\d\[\D\])/g;                          @MatchArray = /(cpd\d\d\d\d\d\[\D\])/g;
4086                          for (my $j=0; $j < @MatchArray; $j++) {                          for (my $j=0; $j < @MatchArray; $j++) {
4087                                  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 4090 
4090                                  }                                  }
4091                          }                          }
4092                  }                  }
         }  
4093    
4094          #Printing header to SBML file          #Printing header to SBML file
4095          my $ModelName = $self->id();          my $ModelName = $self->id().$self->selected_version();
4096          $ModelName =~ s/\./_/;          $ModelName =~ s/\./_/;
4097          print SBMLOUTPUT '<?xml version="1.0" encoding="UTF-8"?>'."\n";          print SBMLOUTPUT '<?xml version="1.0" encoding="UTF-8"?>'."\n";
4098      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";
4099      if (defined($self->figmodel()->database()->GetDBTable("MODEL STATS")->{$self->id()}->[0]->{"Organism name"}->[0])) {          if (defined($self->name())) {
4100          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";
4101      } else {      } else {
4102          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";
4103      }      }
4104    
4105          #Printing the unit data          #Printing the unit data
# Line 3136  Line 4116 
4116      #Printing compartments for SBML file      #Printing compartments for SBML file
4117      print SBMLOUTPUT '<listOfCompartments>'."\n";      print SBMLOUTPUT '<listOfCompartments>'."\n";
4118      foreach my $Compartment (keys(%CompartmentsPresent)) {      foreach my $Compartment (keys(%CompartmentsPresent)) {
4119          if (defined($self->figmodel()->database()->GetDBTable("COMPARTMENTS")->{$Compartment}->[0]->{"Name"}->[0])) {                  my $row = $cmpTbl->get_row_by_key($Compartment,"Abbreviation");
4120                  my @OutsideList = split(/\//,$self->figmodel()->database()->GetDBTable("COMPARTMENTS")->{$Compartment}->[0]->{"Outside"}->[0]);                  if (!defined($row) && !defined($row->{"Name"}->[0])) {
4121                            next;
4122                    }
4123                    my @OutsideList = split(/\//,$row->{"Outside"}->[0]);
4124                  my $Printed = 0;                  my $Printed = 0;
4125                  foreach my $Outside (@OutsideList) {                  foreach my $Outside (@OutsideList) {
4126                                  if (defined($CompartmentsPresent{$Outside}) && defined($self->figmodel()->database()->GetDBTable("COMPARTMENTS")->{$Outside}->[0]->{"Name"}->[0])) {                          if (defined($CompartmentsPresent{$Outside}) && defined($row->{"Name"}->[0])) {
4127                                  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";
4128                                  $Printed = 1;                                  $Printed = 1;
4129                                  last;                                  last;
4130                          }                          }
4131                  }                  }
4132                  if ($Printed eq 0) {                  if ($Printed eq 0) {
4133                          print SBMLOUTPUT '<compartment id="'.$self->figmodel()->database()->GetDBTable("COMPARTMENTS")->{$Compartment}->[0]->{"Name"}->[0].'"/>'."\n";                          print SBMLOUTPUT '<compartment id="'.$row->{"Name"}->[0].'"/>'."\n";
                         }  
4134          }          }
4135      }      }
4136      print SBMLOUTPUT '</listOfCompartments>'."\n";      print SBMLOUTPUT '</listOfCompartments>'."\n";
# Line 3156  Line 4138 
4138      #Printing the list of metabolites involved in the model      #Printing the list of metabolites involved in the model
4139          print SBMLOUTPUT '<listOfSpecies>'."\n";          print SBMLOUTPUT '<listOfSpecies>'."\n";
4140      foreach my $Compound (keys(%CompoundList)) {      foreach my $Compound (keys(%CompoundList)) {
4141                    my $row = $cpdTbl->get_row_by_key($Compound,"DATABASE");
4142                    if (!defined($row)) {
4143                            next;
4144                    }
4145          my $Name = $Compound;          my $Name = $Compound;
4146                  my $Formula = "";                  my $Formula = "";
4147                  if (defined($self->figmodel()->database()->GetDBTable("COMPOUNDS")->{$Compound}->[0]->{"FORMULA"}->[0])) {                  if (defined($row->{"FORMULA"}->[0])) {
4148                          $Formula = $self->figmodel()->database()->GetDBTable("COMPOUNDS")->{$Compound}->[0]->{"FORMULA"}->[0];                          $Formula = $row->{"FORMULA"}->[0];
4149                  }                  }
4150                  if (defined($self->figmodel()->database()->GetDBTable("COMPOUNDS")->{$Compound}->[0]->{"NAME"}->[0])) {                  if (defined($row->{"NAME"}->[0])) {
4151                          $Name = $self->figmodel()->database()->GetDBTable("COMPOUNDS")->{$Compound}->[0]->{"NAME"}->[0];                          $Name = $row->{"NAME"}->[0];
4152                          $Name =~ s/\s/_/;                          $Name =~ s/\s/_/;
4153                          $Name .= "_".$Formula;                          $Name .= "_".$Formula;
4154                  }                  }
4155                  $Name =~ s/[<>;&\*]//;                  $Name =~ s/[<>;&\*]//;
4156                  my $Charge = 0;                  my $Charge = 0;
4157                  if (defined($self->figmodel()->database()->GetDBTable("COMPOUNDS")->{$Compound}->[0]->{"CHARGE"}->[0])) {                  if (defined($row->{"CHARGE"}->[0])) {
4158                          $Charge = $self->figmodel()->database()->GetDBTable("COMPOUNDS")->{$Compound}->[0]->{"CHARGE"}->[0];                          $Charge = $row->{"CHARGE"}->[0];
4159                  }                  }
4160                  foreach my $Compartment (keys(%{$CompoundList{$Compound}})) {                  foreach my $Compartment (keys(%{$CompoundList{$Compound}})) {
4161                  if ($Compartment eq "e") {                  if ($Compartment eq "e") {
4162                          $ExchangeHash->{$Compound} = "e";                          $ExchangeHash->{$Compound} = "e";
4163                  }                  }
4164                  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");
4165                            print SBMLOUTPUT '<species id="'.$Compound.'_'.$Compartment.'" name="'.$Name.'" compartment="'.$cmprow->{"Name"}->[0].'" charge="'.$Charge.'" boundaryCondition="false"/>'."\n";
4166          }          }
4167      }      }
4168    
4169          #Printing the boundary species          #Printing the boundary species
4170          foreach my $Compound (keys(%{$ExchangeHash})) {          foreach my $Compound (keys(%{$ExchangeHash})) {
4171                  my $Name = $Compound;                  my $Name = $Compound;
4172                  my $Formula = "";                  my $Formula = "";
4173                  if (defined($self->figmodel()->database()->GetDBTable("COMPOUNDS")->{$Compound}->[0]->{"FORMULA"}->[0])) {                  my $row = $cpdTbl->get_row_by_key($Compound,"DATABASE");
4174                          $Formula = $self->figmodel()->database()->GetDBTable("COMPOUNDS")->{$Compound}->[0]->{"FORMULA"}->[0];                  if (!defined($row)) {
4175                            next;
4176                    }
4177                    if (defined($row->{"FORMULA"}->[0])) {
4178                            $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                  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";
4191          }          }
# Line 3202  Line 4194 
4194      #Printing the list of reactions involved in the model      #Printing the list of reactions involved in the model
4195          my $ObjectiveCoef;          my $ObjectiveCoef;
4196      print SBMLOUTPUT '<listOfReactions>'."\n";      print SBMLOUTPUT '<listOfReactions>'."\n";
4197    
4198          foreach my $Reaction (@ReactionList) {          foreach my $Reaction (@ReactionList) {
4199          $ObjectiveCoef = "0.0";          $ObjectiveCoef = "0.0";
4200                  if (defined($self->figmodel()->database()->GetDBTable("REACTIONS")->{$Reaction}->[0]->{"EQUATION"}->[0])) {                  my $mdlrow = $mdlTbl->get_row_by_key($Reaction,"LOAD");
4201                    my $Reaction = $mdlrow->{"LOAD"}->[0];
4202                    my $row = $rxnTbl->get_row_by_key($Reaction,"DATABASE");
4203                    if (!defined($row)) {
4204                            $row = $bioTbl->get_row_by_key($Reaction,"DATABASE");
4205                            if (!defined($row)) {
4206                                    next;
4207                            }
4208                    }
4209                    if (!defined($row->{"EQUATION"}->[0])) {
4210                            next;
4211                    }
4212                  if ($Reaction =~ m/^bio/) {                  if ($Reaction =~ m/^bio/) {
4213                                  $ObjectiveCoef = "1.0";                                  $ObjectiveCoef = "1.0";
4214                          }                          }
4215                          my $LowerBound = -10000;                          my $LowerBound = -10000;
4216                  my $UpperBound = 10000;                  my $UpperBound = 10000;
4217                          my ($Reactants,$Products) = $self->figmodel()->GetReactionSubstrateData($Reaction);                  my ($Reactants,$Products) = $self->figmodel()->GetReactionSubstrateDataFromEquation($row->{"EQUATION"}->[0]);
4218                  my $Name = $Reaction;                  my $Name = $Reaction;
4219                  if (defined($self->figmodel()->database()->GetDBTable("REACTIONS")->{$Reaction}->[0]->{"NAME"}->[0])) {                  if (defined($row->{"NAME"}->[0])) {
4220                          $Name = $self->figmodel()->database()->GetDBTable("REACTIONS")->{$Reaction}->[0]->{"NAME"}->[0];                          $Name = $row->{"NAME"}->[0];
4221                                  $Name =~ s/[<>;&]//g;                                  $Name =~ s/[<>;&]//g;
4222                  }                  }
4223                  my $Reversibility = "true";                  my $Reversibility = "true";
4224                  if (defined($ModelTable->{$Reaction}->[0]->{"DIRECTIONALITY"}->[0])) {                  if (defined($mdlrow->{"DIRECTIONALITY"}->[0])) {
4225                          if ($ModelTable->{$Reaction}->[0]->{"DIRECTIONALITY"}->[0] ne "<=>") {                          if ($mdlrow->{"DIRECTIONALITY"}->[0] ne "<=>") {
4226                                  $LowerBound = 0;                                  $LowerBound = 0;
4227                                          $Reversibility = "false";                                          $Reversibility = "false";
4228                          }                          }
4229                          if ($ModelTable->{$Reaction}->[0]->{"DIRECTIONALITY"}->[0] eq "<=") {                          if ($mdlrow->{"DIRECTIONALITY"}->[0] eq "<=") {
4230                                  my $Temp = $Products;                                  my $Temp = $Products;
4231                                  $Products = $Reactants;                                  $Products = $Reactants;
4232                                  $Reactants = $Temp;                                  $Reactants = $Temp;
# Line 3231  Line 4235 
4235                          print SBMLOUTPUT '<reaction id="'.$Reaction.'" name="'.$Name.'" reversible="'.$Reversibility.'">'."\n";                          print SBMLOUTPUT '<reaction id="'.$Reaction.'" name="'.$Name.'" reversible="'.$Reversibility.'">'."\n";
4236                          print SBMLOUTPUT "<notes>\n";                          print SBMLOUTPUT "<notes>\n";
4237                          my $ECData = "";                          my $ECData = "";
4238                          if (defined($self->figmodel()->database()->GetDBTable("REACTIONS")->{$Reaction}->[0]->{"ENZYME"}->[0])) {                  if (defined($row->{"ENZYME"}->[0])) {
4239                                  $ECData = $self->figmodel()->database()->GetDBTable("REACTIONS")->{$Reaction}->[0]->{"ENZYME"}->[0];                          $ECData = $row->{"ENZYME"}->[0];
4240                          }                          }
4241                          my $SubsystemData = "";                          my $SubsystemData = "";
4242                          if (defined($ModelTable->{$Reaction}->[0]->{"SUBSYSTEM"}->[0])) {                  if (defined($mdlrow->{"SUBSYSTEM"}->[0])) {
4243                                  $SubsystemData = $ModelTable->{$Reaction}->[0]->{"SUBSYSTEM"}->[0];                          $SubsystemData = $mdlrow->{"SUBSYSTEM"}->[0];
4244                          }                          }
4245                          my $GeneAssociation = "";                          my $GeneAssociation = "";
4246                          my $ProteinAssociation = "";                          my $ProteinAssociation = "";
4247                          if (defined($ModelTable->{$Reaction}->[0]->{"ASSOCIATED PEG"}->[0])) {                  if (defined($mdlrow->{"ASSOCIATED PEG"}->[0])) {
4248                                  if (@{$ModelTable->{$Reaction}->[0]->{"ASSOCIATED PEG"}} == 1 && $ModelTable->{$Reaction}->[0]->{"ASSOCIATED PEG"}->[0] !~ m/\+/) {                          if (@{$mdlrow->{"ASSOCIATED PEG"}} == 1 && $mdlrow->{"ASSOCIATED PEG"}->[0] !~ m/\+/) {
4249                                          $GeneAssociation = $ModelTable->{$Reaction}->[0]->{"ASSOCIATED PEG"}->[0];                                  $GeneAssociation = $mdlrow->{"ASSOCIATED PEG"}->[0];
4250                                  } else {                                  } else {
4251                                          if (@{$ModelTable->{$Reaction}->[0]->{"ASSOCIATED PEG"}} > 1) {                                  if (@{$mdlrow->{"ASSOCIATED PEG"}} > 1) {
4252                                                  $GeneAssociation = "( ";                                                  $GeneAssociation = "( ";
4253                                          }                                          }
4254                                          for (my $i=0; $i < @{$ModelTable->{$Reaction}->[0]->{"ASSOCIATED PEG"}}; $i++) {                                  for (my $i=0; $i < @{$mdlrow->{"ASSOCIATED PEG"}}; $i++) {
4255                                                  if ($i > 0) {                                                  if ($i > 0) {
4256                                                          $GeneAssociation .= " )  or  ( ";                                                          $GeneAssociation .= " )  or  ( ";
4257                                                  }                                                  }
4258                                                  $GeneAssociation .= $ModelTable->{$Reaction}->[0]->{"ASSOCIATED PEG"}->[$i];                                          $GeneAssociation .= $mdlrow->{"ASSOCIATED PEG"}->[$i];
4259                                          }                                          }
4260                                          if (@{$ModelTable->{$Reaction}->[0]->{"ASSOCIATED PEG"}} > 1) {                                  if (@{$mdlrow->{"ASSOCIATED PEG"}} > 1) {
4261                                                  $GeneAssociation .= " )";                                                  $GeneAssociation .= " )";
4262                                          }                                          }
4263                                  }                                  }
# Line 3262  Line 4266 
4266                                          $GeneAssociation = "( ".$GeneAssociation." )";                                          $GeneAssociation = "( ".$GeneAssociation." )";
4267                                  }                                  }
4268                                  $ProteinAssociation = $GeneAssociation;                                  $ProteinAssociation = $GeneAssociation;
4269                                  if (defined($self->figmodel()->database()->GetDBTable("MODEL STATS")->{$self->id()}->[0]->{"Genome ID"}->[0])) {                          if (defined($self->genome())) {
4270                                          $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());
4271                                  }                                  }
4272                          }                          }
4273                          print SBMLOUTPUT "<html:p>GENE_ASSOCIATION:".$GeneAssociation."</html:p>\n";                          print SBMLOUTPUT "<html:p>GENE_ASSOCIATION:".$GeneAssociation."</html:p>\n";
# Line 3294  Line 4298 
4298              print SBMLOUTPUT "</kineticLaw>\n";              print SBMLOUTPUT "</kineticLaw>\n";
4299                          print SBMLOUTPUT '</reaction>'."\n";                          print SBMLOUTPUT '</reaction>'."\n";
4300                  }                  }
         }  
4301    
4302          my @ExchangeList = keys(%{$ExchangeHash});          my @ExchangeList = keys(%{$ExchangeHash});
4303          foreach my $ExCompound (@ExchangeList) {          foreach my $ExCompound (@ExchangeList) {
4304                  my $ExCompoundName = $ExCompound;                  my $ExCompoundName = $ExCompound;
4305                  my $Row = $self->figmodel()->database()->GetDBTable("COMPOUNDS")->get_row_by_key($ExCompound,"DATABASE");                  my $Row = $cpdTbl->get_row_by_key($ExCompound,"DATABASE");
4306                  if (defined($Row) && defined($Row->{"NAME"}->[0])) {                  if (defined($Row) && defined($Row->{"NAME"}->[0])) {
4307                          $ExCompoundName = $Row->{"NAME"}->[0];                          $ExCompoundName = $Row->{"NAME"}->[0];
4308                          $ExCompoundName =~ s/[<>;&]//g;                          $ExCompoundName =~ s/[<>;&]//g;
# Line 3339  Line 4342 
4342          close(SBMLOUTPUT);          close(SBMLOUTPUT);
4343  }  }
4344    
4345    =head3 PrintModelSimpleReactionTable
4346    Definition:
4347            success()/fail() FIGMODELmodel->PrintModelSimpleReactionTable();
4348    Description:
4349            Prints the table of model data
4350    =cut
4351    sub PrintModelSimpleReactionTable {
4352            my ($self) = @_;
4353    
4354            my $rxntbl = $self->reaction_table();
4355            my $tbl = $self->create_table_prototype("ModelSimpleReactionTable");
4356            for (my $i=0; $i < $rxntbl->size(); $i++) {
4357                    my $row = $rxntbl->get_row($i);
4358                    $row->{DATABASE} = $row->{LOAD};
4359                    $tbl->add_row($row);
4360            }
4361            $tbl->save();
4362    }
4363    
4364  =head3 PrintModelLPFile  =head3 PrintModelLPFile
4365  Definition:  Definition:
4366          success()/fail() FIGMODELmodel->PrintModelLPFile();          success()/fail() FIGMODELmodel->PrintModelLPFile();
# Line 3363  Line 4385 
4385          $self->figmodel()->clearing_output($UniqueFilename,"FBA-".$self->id().$self->selected_version().".lp");          $self->figmodel()->clearing_output($UniqueFilename,"FBA-".$self->id().$self->selected_version().".lp");
4386  }  }
4387    
4388    =head3 patch_model
4389    Definition:
4390            FIGMODELTable:patch results = FIGMODELmodel->patch_model(FIGMODELTable:patch table);
4391    Description:
4392    =cut
4393    sub patch_model {
4394            my ($self,$tbl) = @_;
4395    
4396            #Instantiating table
4397            my $results = FIGMODELTable->new(["Reactions","New genes","Old genes","Genes","Roles","Status"],$self->directory()."PatchResults-".$self->id().$self->selected_version().".tbl",["Reaction"],"\t",";",undef);
4398            #Getting genome annotations
4399            my $features = $self->figmodel()->database()->get_genome_feature_table($self->genome());
4400            #Gettubg reaction table
4401            my $reactions = $self->reaction_table();
4402            #Checking for patched roles
4403            for (my $i=0; $i < $tbl->size(); $i++) {
4404                    my $row = $tbl->get_row($i);
4405                    my @genes = $features->get_rows_by_key($row->{ROLE}->[0],"ROLES");
4406                    if (@genes > 0) {
4407                            for (my $j=0; $j < @{$row->{REACTIONS}};$j++) {
4408                                    my $resultrxn = $results->get_row_by_key($row->{REACTIONS}->[$j],"Reactions");
4409                                    if (!defined($resultrxn)) {
4410                                            $resultrxn = $results->add_row({"Reactions"=>[$row->{REACTIONS}->[$j]],"Roles"=>[$row->{ROLE}->[0]]});
4411                                    }
4412                                    my $rxnrow = $reactions->get_row_by_key($row->{REACTIONS}->[$j],"LOAD");
4413                                    if (defined($rxnrow) && !defined($resultrxn->{"Old genes"})) {
4414                                            $resultrxn->{"Old genes"} = $rxnrow->{"ASSOCIATED PEG"};
4415                                            if ($resultrxn->{"Old genes"}->[0] !~ m/GAP|BOF|UNIVERSAL|SPONTANEOUS/) {
4416                                                    push(@{$resultrxn->{"Genes"}},@{$resultrxn->{"Old genes"}});
4417                                            }
4418                                    }
4419                                    delete $resultrxn->{"Current gene set"};
4420                                    if (defined($resultrxn->{"Genes"})) {
4421                                            push(@{$resultrxn->{"Current gene set"}},@{$resultrxn->{"Genes"}});
4422                                    }
4423                                    for (my $k=0; $k < @genes; $k++) {
4424                                            if ($genes[$k]->{ID}->[0] =~ m/(peg\.\d+)/) {
4425                                                    my $gene = $1;
4426                                                    my $addgene = 1;
4427                                                    if (defined($resultrxn->{"Old genes"})) {
4428                                                            for (my $m=0; $m < @{$resultrxn->{"Old genes"}}; $m++) {
4429                                                                    if ($resultrxn->{"Old genes"}->[$m] =~ m/$gene/) {
4430                                                                            $addgene = 0;
4431                                                                    }
4432                                                            }
4433                                                    }
4434                                                    if ($addgene == 1) {
4435                                                            push(@{$resultrxn->{"New genes"}},$gene);
4436                                                            if ($row->{COMPLEX}->[0] ne "0" && defined($resultrxn->{"Current gene set"})) {
4437                                                                    my $added = 0;
4438                                                                    for (my $m=0; $m < @{$resultrxn->{"Current gene set"}}; $m++) {
4439                                                                            if ($row->{COMPLEX}->[0] eq "1") {
4440                                                                                    $resultrxn->{"Current gene set"}->[$m] = $resultrxn->{"Current gene set"}->[$m]."+".$gene;
4441                                                                                    $added = 1;
4442                                                                            } else {
4443                                                                                    my @geneset = split(/\+/,$resultrxn->{"Current gene set"}->[$m]);
4444                                                                                    for (my $n=0; $n < @geneset;$n++) {
4445                                                                                            if ($self->figmodel()->colocalized_genes($geneset[$n],$gene,$self->genome()) == 1) {
4446                                                                                                    $resultrxn->{"Current gene set"}->[$m] = $resultrxn->{"Current gene set"}->[$m]."+".$gene;
4447                                                                                                    $added = 1;
4448                                                                                                    last;
4449                                                                                            }
4450                                                                                    }
4451                                                                            }
4452                                                                    }
4453                                                                    if ($added == 0) {
4454                                                                            push(@{$resultrxn->{"Current gene set"}},$gene);
4455                                                                    }
4456                                                            } else {
4457                                                                    push(@{$resultrxn->{"Current gene set"}},$gene);
4458                                                            }
4459                                                    }
4460                                            }
4461