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

Diff of /FigKernelPackages/FIGMODELmodel.pm

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

revision 1.2, Fri Dec 11 21:37:02 2009 UTC revision 1.20, Tue Jun 15 04:04:01 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 14  Line 14 
14  =cut  =cut
15  sub new {  sub new {
16          my ($class,$figmodel,$id) = @_;          my ($class,$figmodel,$id) = @_;
17    
18          #Error checking first          #Error checking first
19          if (!defined($figmodel)) {          if (!defined($figmodel)) {
20                  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 27  Line 28 
28          }          }
29    
30          #Checking that the id exists          #Checking that the id exists
31          my $tbl = $self->figmodel()->database()->GetDBTable("MODELS");          my $modelHandle = $self->figmodel()->database()->get_object_manager("model");
32          if (!defined($tbl)) {          if (!defined($modelHandle)) {
33                  $self->figmodel()->error_message("FIGMODELmodel->new(figmodel,".$id."):could not load MODELS table. Check database!");                  $self->figmodel()->error_message("FIGMODELmodel->new(figmodel,".$id."):could not load MODELS table. Check database!");
34                  return undef;                  return undef;
35          }          }
36    
37          #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;  
38          if ($id =~ m/^\d+$/) {          if ($id =~ m/^\d+$/) {
39                  $self->{_data} = $tbl->get_row($id);                  my $objects = $modelHandle->get_objects();
40          } else {                  $self->{_data} = $objects->[$id];
41                  $self->{_data} = $tbl->get_row_by_key($id,"id");                  $self->figmodel()->{_models}->{$id} = $self;
42                  if (defined($self->{_data})) {          } else {
43                          $index = $tbl->row_index($self->{_data});                  my $objects = $modelHandle->get_objects({id => $id});
44                    if (!defined($objects->[0]) && $id =~ m/(.+)(V[^V]+)/) {
45                            $objects = $modelHandle->get_objects({id => $1});
46                            if (!defined($objects->[0])) {
47                                    $self->figmodel()->error_message("FIGMODELmodel->new(figmodel,".$id."):could not find model ".$id." in database!");
48                                    return undef;
49                            }
50                            $self->{_selectedversion} = $2;
51                    } elsif (!defined($objects->[0])) {
52                            $self->figmodel()->error_message("FIGMODELmodel->new(figmodel,".$id."):could not find model ".$id." in database!");
53                            return undef;
54                  }                  }
55                    $self->{_data} = $objects->[0];
56          }          }
57          if (!defined($self->{_data})) {          if (!defined($self->{_data})) {
58                  $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 specified id in database!");
59                  return undef;                  return undef;
60          }          }
         $self->{_index} = $index;  
61          $self->figmodel()->{_models}->{$self->id()} = $self;          $self->figmodel()->{_models}->{$self->id()} = $self;
         $self->figmodel()->{_models}->{$self->index()} = $self;  
62    
63          return $self;          return $self;
64  }  }
# Line 107  Line 116 
116  =cut  =cut
117  sub fig {  sub fig {
118          my ($self) = @_;          my ($self) = @_;
   
119          if (!defined($self->{_fig}) && $self->source() !~ /^MGRAST/) {          if (!defined($self->{_fig}) && $self->source() !~ /^MGRAST/) {
120                  if ($self->source() =~ /^RAST/) {                  if ($self->source() =~ /^RAST/) {
121                          $self->{"_fig"} = $self->figmodel()->fig();#$self->genome());                          $self->{"_fig"} = $self->figmodel()->fig();#$self->genome());
# Line 115  Line 123 
123                          $self->{"_fig"} = $self->figmodel()->fig();                          $self->{"_fig"} = $self->figmodel()->fig();
124                  }                  }
125          }          }
   
126          return $self->{"_fig"};          return $self->{"_fig"};
127  }  }
128    
129    =head3 aquireModelLock
130    
131    Definition:
132    
133            FIGMODELmodel->aquireModelLock();
134    
135    Description:
136    
137            Locks the database for alterations relating to the current model object
138    
139    =cut
140    sub aquireModelLock {
141            my ($self) = @_;
142            $self->figmodel()->database()->genericLock($self->id());
143    }
144    
145    =head3 releaseModelLock
146    
147    Definition:
148    
149            FIGMODELmodel->releaseModelLock();
150    
151    Description:
152    
153            Unlocks the database for alterations relating to the current model object
154    
155    =cut
156    sub releaseModelLock {
157            my ($self) = @_;
158            $self->figmodel()->database()->genericUnlock($self->id());
159    }
160    
161  =head3 mgdata  =head3 mgdata
162  Definition:  Definition:
163          FIGMODEL = FIGMODELmodel->mgdata();          FIGMODEL = FIGMODELmodel->mgdata();
# Line 127  Line 166 
166  =cut  =cut
167  sub mgdata {  sub mgdata {
168          my ($self) = @_;          my ($self) = @_;
   
169          if (!defined($self->{_mgdata}) && $self->source() =~ /^MGRAST/) {          if (!defined($self->{_mgdata}) && $self->source() =~ /^MGRAST/) {
170                  require MGRAST;                  require MGRAST;
171                  $self->{_mgdata} = $self->figmodel()->mgrast()->Job->get_objects( { 'genome_id' => $self->genome() } )                  $self->{_mgdata} = $self->figmodel()->mgrast()->Job->get_objects( { 'genome_id' => $self->genome() } )
172          }          }
   
173          return $self->{_mgdata};          return $self->{_mgdata};
174  }  }
175    
# Line 144  Line 181 
181  =cut  =cut
182  sub id {  sub id {
183          my ($self) = @_;          my ($self) = @_;
184          return $self->{_data}->{id}->[0];          return $self->{_data}->id();
185  }  }
186    
187  =head3 owner  =head3 owner
# Line 155  Line 192 
192  =cut  =cut
193  sub owner {  sub owner {
194          my ($self) = @_;          my ($self) = @_;
195          return $self->{_data}->{owner}->[0];          return $self->{_data}->owner();
 }  
   
 =head3 index  
 Definition:  
         string = FIGMODELmodel->index();  
 Description:  
         Returns model index  
 =cut  
 sub index {  
         my ($self) = @_;  
         return $self->{_index};  
196  }  }
197    
198  =head3 name  =head3 name
# Line 185  Line 211 
211                          if (defined($self->mgdata())) {                          if (defined($self->mgdata())) {
212                                  $self->{_name} = $self->mgdata()->genome_name;                                  $self->{_name} = $self->mgdata()->genome_name;
213                          }                          }
                 } elsif (defined($self->stats())) {  
                         $self->{_name} = $self->stats()->{'Organism name'}->[0];  
214                  } elsif ($source !~ /^RAST/) {                  } elsif ($source !~ /^RAST/) {
215                          $self->{_name} = $self->fig()->orgname_of_orgid($self->genome());                          $self->{_name} = $self->fig()->orgname_of_orgid($self->genome());
216                    } else {
217                            $self->{_name} = $self->figmodel()->get_genome_stats($self->genome())->{NAME}->[0];
218                  }                  }
219          }          }
220    
221          return $self->{_name};          return $self->{_name};
222  }  }
223    
 =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};  
 }  
   
224  =head3 get_reaction_class  =head3 get_reaction_class
225  Definition:  Definition:
226          string = FIGMODELmodel->get_reaction_class(string::reaction ID);          string = FIGMODELmodel->get_reaction_class(string::reaction ID);
# Line 217  Line 228 
228          Returns reaction class          Returns reaction class
229  =cut  =cut
230  sub get_reaction_class {  sub get_reaction_class {
231          my ($self,$reaction,$nohtml) = @_;          my ($self,$reaction,$nohtml,$brief_flux) = @_;
232    
233          if (!-e $self->directory()."ReactionClassification-".$self->id().".tbl") {          if (!-e $self->directory()."ReactionClassification-".$self->id().".tbl") {
234                  if (!defined($self->{_reaction_classes})) {                  if (!defined($self->{_reaction_classes})) {
# Line 230  Line 241 
241                  my $ClassRow = $self->{_reaction_classes}->get_row_by_key($reaction,"REACTION");                  my $ClassRow = $self->{_reaction_classes}->get_row_by_key($reaction,"REACTION");
242                  if (defined($ClassRow) && defined($ClassRow->{CLASS})) {                  if (defined($ClassRow) && defined($ClassRow->{CLASS})) {
243                          my $class;                          my $class;
244                            my $min = $ClassRow->{MIN}->[0];
245                            my $max = $ClassRow->{MAX}->[0];
246                          if ($ClassRow->{CLASS}->[0] eq "Positive") {                          if ($ClassRow->{CLASS}->[0] eq "Positive") {
247                                  $class = "Essential =>";                                  $class = "Essential =>";
248                                    $brief_flux ? $class.="<br>[Flux: ".sprintf("%.3g",$min)." to ".sprintf("%.3g",$max)."]<br>" : $class.="<br>[Flux: ".$min." to ".$max."]<br>";
249                          } elsif ($ClassRow->{CLASS}->[0] eq "Negative") {                          } elsif ($ClassRow->{CLASS}->[0] eq "Negative") {
250                                  $class = "Essential <=";                                  $class = "Essential <=";
251                                    $brief_flux ? $class.="<br>[Flux: ".sprintf("%.3g",$min)." to ".sprintf("%.3g",$max)."]<br>" : $class.="<br>[Flux: ".$min." to ".$max."]<br>";
252                          } elsif ($ClassRow->{CLASS}->[0] eq "Positive variable") {                          } elsif ($ClassRow->{CLASS}->[0] eq "Positive variable") {
253                                  $class = "Active =>";                                  $class = "Active =>";
254                                    $brief_flux ? $class.="<br>[Flux: ".sprintf("%.3g",$min)." to ".sprintf("%.3g",$max)."]<br>" : $class.="<br>[Flux: ".$min." to ".$max."]<br>";
255                          } elsif ($ClassRow->{CLASS}->[0] eq "Negative variable") {                          } elsif ($ClassRow->{CLASS}->[0] eq "Negative variable") {
256                                  $class = "Active <=";                                  $class = "Active <=";
257                                    $brief_flux ? $class.="<br>[Flux: ".sprintf("%.3g",$min)." to ".sprintf("%.3g",$max)."]<br>" : $class.="<br>[Flux: ".$min." to ".$max."]<br>";
258                          } elsif ($ClassRow->{CLASS}->[0] eq "Variable") {                          } elsif ($ClassRow->{CLASS}->[0] eq "Variable") {
259                                  $class = "Active <=>";                                  $class = "Active <=>";
260                                    $brief_flux ? $class.="<br>[Flux: ".sprintf("%.3g",$min)." to ".sprintf("%.3g",$max)."]<br>" : $class.="<br>[Flux: ".$min." to ".$max."]<br>";
261                          } elsif ($ClassRow->{CLASS}->[0] eq "Blocked") {                          } elsif ($ClassRow->{CLASS}->[0] eq "Blocked") {
262                                  $class = "Inactive";                                  $class = "Inactive";
263                          } elsif ($ClassRow->{CLASS}->[0] eq "Dead") {                          } elsif ($ClassRow->{CLASS}->[0] eq "Dead") {
264                                  $class = "Disconnected";                                  $class = "Disconnected";
265                          }                          }
266    
267                          if (!defined($nohtml) || $nohtml ne "1") {                          if (!defined($nohtml) || $nohtml ne "1") {
268                                  $class = "<span title=\"Flux:".$ClassRow->{MIN}->[0]." to ".$ClassRow->{MAX}->[0]."\">".$class."</span>";                                  $class = "<span title=\"Flux:".$min." to ".$max."\">".$class."</span>";
269                          }                          }
270    
271                          return $class;                          return $class;
272                  }                  }
273                  return undef;                  return undef;
# Line 268  Line 288 
288                                  $classstring .= "<br>";                                  $classstring .= "<br>";
289                          }                          }
290                          my $NewClass;                          my $NewClass;
291                            my $min = $ClassRow->{MIN}->[$i];
292                            my $max = $ClassRow->{MAX}->[$i];
293                          if ($ClassRow->{CLASS}->[$i] eq "Positive") {                          if ($ClassRow->{CLASS}->[$i] eq "Positive") {
294                                  $NewClass = $ClassRow->{MEDIA}->[$i].":Essential =>";                                  $NewClass = $ClassRow->{MEDIA}->[$i].":Essential =>";
295                                  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>";  
                                 }  
296                          } elsif ($ClassRow->{CLASS}->[$i] eq "Negative") {                          } elsif ($ClassRow->{CLASS}->[$i] eq "Negative") {
297                                  $NewClass = $ClassRow->{MEDIA}->[$i].":Essential <=";                                  $NewClass = $ClassRow->{MEDIA}->[$i].":Essential <=";
298                                  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>";  
                                 }  
299                          } elsif ($ClassRow->{CLASS}->[$i] eq "Positive variable") {                          } elsif ($ClassRow->{CLASS}->[$i] eq "Positive variable") {
300                                  $NewClass = $ClassRow->{MEDIA}->[$i].":Active =>";                                  $NewClass = $ClassRow->{MEDIA}->[$i].":Active =>";
301                                  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>";  
                                 }  
302                          } elsif ($ClassRow->{CLASS}->[$i] eq "Negative variable") {                          } elsif ($ClassRow->{CLASS}->[$i] eq "Negative variable") {
303                                  $NewClass = $ClassRow->{MEDIA}->[$i].":Active <=";                                  $NewClass = $ClassRow->{MEDIA}->[$i].":Active <=";
304                                  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>";  
                                 }  
305                          } elsif ($ClassRow->{CLASS}->[$i] eq "Variable") {                          } elsif ($ClassRow->{CLASS}->[$i] eq "Variable") {
306                                  $NewClass = $ClassRow->{MEDIA}->[$i].":Active <=>";                                  $NewClass = $ClassRow->{MEDIA}->[$i].":Active <=>";
307                                  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>";  
                                 }  
308                          } elsif ($ClassRow->{CLASS}->[$i] eq "Blocked") {                          } elsif ($ClassRow->{CLASS}->[$i] eq "Blocked") {
309                                  $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>";  
                                 }  
310                          } elsif ($ClassRow->{CLASS}->[$i] eq "Dead") {                          } elsif ($ClassRow->{CLASS}->[$i] eq "Dead") {
311                                  $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>";  
312                                  }                                  }
313    
314                            if (!defined($nohtml) || $nohtml ne "1") {
315                                    $NewClass = "<span title=\"Flux:".$min." to ".$max."\">".$NewClass."</span>";
316                          }                          }
317                          $classstring .= $NewClass;                          $classstring .= $NewClass;
318                  }                  }
# Line 321  Line 331 
331    
332          if (!defined($self->{_biomass})) {          if (!defined($self->{_biomass})) {
333                  my $rxntbl = $self->reaction_table();                  my $rxntbl = $self->reaction_table();
334                    if (defined($rxntbl)) {
335                  for (my $i=0; $i < $rxntbl->size(); $i++) {                  for (my $i=0; $i < $rxntbl->size(); $i++) {
336                          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/) {
337                                  $self->{_biomass} = $rxntbl->get_row($i)->{"LOAD"}->[0];                                  $self->{_biomass} = $rxntbl->get_row($i)->{"LOAD"}->[0];
# Line 328  Line 339 
339                          }                          }
340                  }                  }
341          }          }
342            }
343    
344          return $self->get_reaction_data($self->{_biomass});          return $self->get_reaction_data($self->{_biomass});
345  }  }
# Line 366  Line 378 
378          return $Data->{LOAD}->[0];          return $Data->{LOAD}->[0];
379  }  }
380    
381    =head3 load_model_table
382    
383    Definition: FIGMODELTable = FIGMODELmodel->load_model_table(string:table name,0/1:refresh the table));
384    
385    Description: Returns the table specified by the input filename. Table will be stored in a file in the model directory.
386    
387    =cut
388    sub load_model_table {
389            my ($self,$name,$refresh) = @_;
390            if (defined($refresh) && $refresh == 1) {
391                    delete $self->{"_".$name};
392            }
393            if (!defined($self->{"_".$name})) {
394                    my $tbldef = $self->figmodel()->config($name);
395                    if (!defined($tbldef)) {
396                            return undef;
397                    }
398                    my $itemDelim = "|";
399                    if (defined($tbldef->{itemdelimiter}->[0])) {
400                            $itemDelim = $tbldef->{itemdelimiter}->[0];
401                            if ($itemDelim eq "SC") {
402                                    $itemDelim = ";";
403                            }
404                    }
405                    my $columnDelim = "\t";
406                    if (defined($tbldef->{columndelimiter}->[0])) {
407                            $columnDelim = $tbldef->{columndelimiter}->[0];
408                            if ($columnDelim eq "SC") {
409                                    $columnDelim = ";";
410                            }
411                    }
412                    my $suffix = ".tbl";
413                    if (defined($tbldef->{filename_suffix}->[0])) {
414                            $suffix = $tbldef->{filename_suffix}->[0];
415                    }
416                    my $filename = $self->directory().$name."-".$self->id().$self->selected_version().$suffix;
417                    if (defined($tbldef->{filename_prefix}->[0])) {
418                            if ($tbldef->{filename_prefix}->[0] eq "NONE") {
419                                    $filename = $self->directory().$self->id().$self->selected_version().$suffix;
420                            } else {
421                                    $filename = $self->directory().$tbldef->{filename_prefix}->[0]."-".$self->id().$self->selected_version().$suffix;
422                            }
423                    }
424                    if (-e $filename) {
425                            $self->{"_".$name} = $self->figmodel()->database()->load_table($filename,$columnDelim,$itemDelim,$tbldef->{headingline}->[0],$tbldef->{hashcolumns});
426                    } else {
427                            if (defined($tbldef->{prefix})) {
428                                    $self->{"_".$name} = FIGMODELTable->new($tbldef->{columns},$filename,$tbldef->{hashcolumns},$columnDelim,$itemDelim,join(@{$tbldef->{prefix}},"\n"));
429                            } else {
430                                    $self->{"_".$name} = FIGMODELTable->new($tbldef->{columns},$filename,$tbldef->{hashcolumns},$columnDelim,$itemDelim);
431                            }
432                    }
433            }
434            return $self->{"_".$name};
435    }
436    
437    =head3 create_table_prototype
438    
439    Definition:
440            FIGMODELTable::table = FIGMODELmodel->create_table_prototype(string::table);
441    Description:
442            Returns a empty FIGMODELTable with all the metadata associated with the input table name
443    
444    =cut
445    sub create_table_prototype {
446            my ($self,$TableName) = @_;
447    
448            #Checking if the table definition exists in the FIGMODELconfig file
449            if (!defined($self->figmodel()->config($TableName))) {
450                    $self->figmodel()->error_message("FIGMODELdatabase:create_table_prototype:Definition not found for ".$TableName);
451                    return undef;
452            }
453            #Checking that this is a database table
454            if (!defined($self->config($TableName)->{tabletype}) || $self->config($TableName)->{tabletype}->[0] ne "ModelTable") {
455                    $self->figmodel()->error_message("FIGMODELdatabase:create_table_prototype:".$TableName." is not a model table!");
456                    return undef;
457            }
458            if (!defined($self->config($TableName)->{delimiter})) {
459                    $self->config($TableName)->{delimiter}->[0] = ";";
460            }
461            if (!defined($self->config($TableName)->{itemdelimiter})) {
462                    $self->config($TableName)->{itemdelimiter}->[0] = "|";
463            }
464            my $prefix;
465            if (defined($self->config($TableName)->{prefix})) {
466                    $prefix = join("\n",@{$self->config($TableName)->{prefix}});
467            }
468            my $tbl = FIGMODELTable->new($self->config($TableName)->{columns},$self->directory().$self->config($TableName)->{filename_prefix}->[0]."-".$self->id().$self->selected_version().".txt",$self->config($TableName)->{hashcolumns},$self->config($TableName)->{delimiter}->[0],$self->config($TableName)->{itemdelimiter}->[0],$prefix);
469            return $tbl;
470    }
471    
472  =head3 get_reaction_number  =head3 get_reaction_number
473  Definition:  Definition:
474          int = FIGMODELmodel->get_reaction_number();          int = FIGMODELmodel->get_reaction_number();
# Line 374  Line 477 
477  =cut  =cut
478  sub get_reaction_number {  sub get_reaction_number {
479          my ($self) = @_;          my ($self) = @_;
   
480          if (!defined($self->reaction_table())) {          if (!defined($self->reaction_table())) {
481                  return 0;                  return 0;
482          }          }
   
483          return $self->reaction_table()->size();          return $self->reaction_table()->size();
484  }  }
485    
# Line 389  Line 490 
490          Returns FIGMODELTable with the reaction list for the model          Returns FIGMODELTable with the reaction list for the model
491  =cut  =cut
492  sub reaction_table {  sub reaction_table {
493          my ($self) = @_;          my ($self,$clear) = @_;
494            my $tbl = $self->load_model_table("ModelReactions",$clear);
495          if (!defined($self->{_reaction_data})) {          my $classTbl = $self->reaction_class_table();
496                  $self->{_reaction_data} = $self->figmodel()->database()->GetDBModel($self->id());          if (defined($classTbl)) {
497                    for (my $i=0; $i < $classTbl->size(); $i++) {
498                            my $row = $classTbl->get_row($i);
499                            if (defined($row->{REACTION})) {
500                                    my $rxnRow = $tbl->get_row_by_key($row->{"REACTION"}->[0],"LOAD");
501                                    if (defined($row->{MEDIA})) {
502                                            for (my $j=0; $j < @{$row->{MEDIA}};$j++) {
503                                                    my $class = "Active <=>";
504                                                    if ($row->{CLASS}->[$j] eq "Positive") {
505                                                            $class = "Essential =>";
506                                                    } elsif ($row->{CLASS}->[$j] eq "Negative") {
507                                                            $class = "Essential <=";
508                                                    } elsif ($row->{CLASS}->[$j] eq "Blocked") {
509                                                            $class = "Inactive";
510                                                    } elsif ($row->{CLASS}->[$j] eq "Positive variable") {
511                                                            $class = "Active =>";
512                                                    } elsif ($row->{CLASS}->[$j] eq "Negative variable") {
513                                                            $class = "Active <=";
514                                                    } elsif ($row->{CLASS}->[$j] eq "Variable") {
515                                                            $class = "Active <=>";
516                                                    } elsif ($row->{CLASS}->[$j] eq "Dead") {
517                                                            $class = "Dead";
518                                                    }
519                                                    push(@{$rxnRow->{PREDICTIONS}},$row->{MEDIA}->[$j].":".$class);
520                                            }
521                                    }
522                            }
523                    }
524            }
525            return $tbl;
526          }          }
527    
528          return $self->{_reaction_data};  =head3 model_history
529    Definition:
530            FIGMODELTable = FIGMODELmodel->model_history();
531    Description:
532            Returns FIGMODELTable with the history of model changes
533    =cut
534    sub model_history {
535            my ($self,$clear) = @_;
536            return $self->load_model_table("ModelHistory",$clear);
537  }  }
538    
539  =head3 reaction_class_table  =head3 feature_table
540  Definition:  Definition:
541          FIGMODELTable = FIGMODELmodel->reaction_class_table();          FIGMODELTable = FIGMODELmodel->feature_table();
542  Description:  Description:
543          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
544  =cut  =cut
545  sub reaction_class_table {  sub feature_table {
546          my ($self) = @_;          my ($self) = @_;
547    
548          if (!defined($self->{_reaction_class_table})) {          if (!defined($self->{_feature_data})) {
549                  if (-e $self->directory()."ReactionClassification-".$self->id().$self->selected_version().".tbl") {                  #Getting the genome feature list
550                          $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());
551                    if (!defined($FeatureTable)) {
552                            print STDERR "FIGMODELmodel:feature_table:Could not get features for genome ".$self->genome()." in database!";
553                            return undef;
554                    }
555                    #Getting the reaction table for the model
556                    my $rxnTable = $self->reaction_table();
557                    if (!defined($rxnTable)) {
558                            print STDERR "FIGMODELmodel:feature_table:Could not get reaction table for model ".$self->id()." in database!";
559                            return undef;
560                    }
561                    #Cloning the feature table
562                    $self->{_feature_data} = $FeatureTable->clone_table_def();
563                    $self->{_feature_data}->add_headings(($self->id()."REACTIONS",$self->id()."PREDICTIONS"));
564                    for (my $i=0; $i < $rxnTable->size(); $i++) {
565                            my $Row = $rxnTable->get_row($i);
566                            if (defined($Row) && defined($Row->{"ASSOCIATED PEG"})) {
567                                    foreach my $GeneSet (@{$Row->{"ASSOCIATED PEG"}}) {
568                                            my $temp = $GeneSet;
569                                            $temp =~ s/\+/|/g;
570                                            $temp =~ s/\sAND\s/|/gi;
571                                            $temp =~ s/\sOR\s/|/gi;
572                                            $temp =~ s/[\(\)\s]//g;
573                                            my @GeneList = split(/\|/,$temp);
574                                            foreach my $Gene (@GeneList) {
575                                                    my $FeatureRow = $self->{_feature_data}->get_row_by_key("fig|".$self->genome().".".$Gene,"ID");
576                                                    if (!defined($FeatureRow)) {
577                                                            $FeatureRow = $FeatureTable->get_row_by_key("fig|".$self->genome().".".$Gene,"ID");
578                                                            if (defined($FeatureRow)) {
579                                                                    $self->{_feature_data}->add_row($FeatureRow);
580                                                            }
581                                                    }
582                                                    if (defined($FeatureRow)) {
583                                                            $self->{_feature_data}->add_data($FeatureRow,$self->id()."REACTIONS",$Row->{"LOAD"}->[0],1);
584                                                    }
585                                            }
586                                    }
587                            }
588                    }
589                    #Loading predictions
590                    my @files = glob($self->directory()."EssentialGenes-".$self->id()."-*");
591                    foreach my $file (@files) {
592                            if ($file =~ m/\-([^\-]+)\.tbl/) {
593                                    my $media = $1;
594                                    my $list = $self->figmodel()->database()->load_single_column_file($file,"");
595                                    my $hash;
596                                    foreach my $gene (@{$list}) {
597                                            $hash->{$gene} = 1;
598                                    }
599                                    for (my $i=0; $i < $self->{_feature_data}->size(); $i++) {
600                                            my $Row = $self->{_feature_data}->get_row($i);
601                                            if ($Row->{ID}->[0] =~ m/(peg\.\d+)/) {
602                                                    my $gene = $1;
603                                                    if (defined($hash->{$gene})) {
604                                                            push(@{$Row->{$self->id()."PREDICTIONS"}},$media.":essential");
605                  } else {                  } else {
606                          $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"}},$media.":nonessential");
607                  }                  }
608          }          }
609                                    }
610                            }
611                    }
612            }
613            return $self->{_feature_data};
614    }
615    
616          return $self->{_reaction_class_table};  =head3 reaction_class_table
617    Definition:
618            FIGMODELTable = FIGMODELmodel->reaction_class_table();
619    Description:
620            Returns FIGMODELTable with the reaction class data, and creates the table file  if it does not exist
621    =cut
622    sub reaction_class_table {
623            my ($self,$clear) = @_;
624            return $self->load_model_table("ModelReactionClasses",$clear);
625  }  }
626    
627  =head3 compound_class_table  =head3 compound_class_table
# Line 425  Line 631 
631          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
632  =cut  =cut
633  sub compound_class_table {  sub compound_class_table {
634          my ($self) = @_;          my ($self,$clear) = @_;
635            return $self->load_model_table("ModelCompoundClasses",$clear);
636    }
637    
638          if (!defined($self->{_compound_class_table})) {  =head3 get_essential_genes
639                  if (-e $self->directory()."CompoundClassification-".$self->id().$self->selected_version().".tbl") {  Definition:
640                          $self->{_compound_class_table} = $self->figmodel()->database()->load_table($self->directory()."CompoundClassification-".$self->id().$self->selected_version().".tbl",";","|",0,["COMPOUND","CLASS","MEDIA"]);          [string::peg ID] = FIGMODELmodel->get_essential_genes(string::media condition);
641                  } else {  Description:
642                          $self->{_compound_class_table} = FIGMODELTable->new(["COMPOUND","MEDIA","CLASS","MIN","MAX"],$self->directory()."CompoundClassification-".$self->id().$self->selected_version().".tbl",["COMPOUND","CLASS","MEDIA"],";","|",undef);          Returns an reference to an array of the predicted essential genes during growth in the input media condition
643    =cut
644    sub get_essential_genes {
645            my ($self,$media) = @_;
646    
647            if (!defined($media)) {
648                    $media = "Complete";
649            }
650            if (!defined($self->{_essential_genes}->{$media})) {
651                    $self->{_essential_genes}->{$media} = undef;
652                    if (-e $self->directory()."EssentialGenes-".$self->id().$self->selected_version()."-".$media.".tbl") {
653                            $self->{_essential_genes}->{$media} = $self->figmodel()->database()->load_single_column_file($self->directory()."EssentialGenes-".$self->id().$self->selected_version()."-".$media.".tbl","");
654                  }                  }
655          }          }
656    
657          return $self->{_compound_class_table};          return $self->{_essential_genes}->{$media};
658  }  }
659    
660  =head3 compound_table  =head3 compound_table
# Line 456  Line 675 
675    
676  =head3 get_compound_data  =head3 get_compound_data
677  Definition:  Definition:
678          string = FIGMODELmodel->get_compound_data(string::compound ID);          {string:key=>[string]:values} = FIGMODELmodel->get_compound_data(string::compound ID);
679  Description:  Description:
680          Returns model compound data          Returns model compound data
681  =cut  =cut
# Line 467  Line 686 
686                  return undef;                  return undef;
687          }          }
688          if ($compound =~ m/^\d+$/) {          if ($compound =~ m/^\d+$/) {
689                  $self->compound_table()->get_row($compound);                  return $self->compound_table()->get_row($compound);
690          }          }
691          return $self->compound_table()->get_row_by_key($compound,"DATABASE");          return $self->compound_table()->get_row_by_key($compound,"DATABASE");
692  }  }
693    
694    =head3 get_feature_data
695    Definition:
696            {string:key=>[string]:values} = FIGMODELmodel->get_feature_data(string::feature ID);
697    Description:
698            Returns model feature data
699    =cut
700    sub get_feature_data {
701            my ($self,$feature) = @_;
702            if (!defined($self->feature_table())) {
703                    return undef;
704            }
705            if ($feature =~ m/^\d+$/) {
706                    return $self->feature_table()->get_row($feature);
707            }
708            if ($feature =~ m/(peg\.\d+)/) {
709                    $feature = $1;
710            }
711            return $self->feature_table()->get_row_by_key("fig|".$self->genome().".".$feature,"ID");
712    }
713    
714  =head3 genome  =head3 genome
715  Definition:  Definition:
716          string = FIGMODELmodel->genome();          string = FIGMODELmodel->genome();
# Line 480  Line 719 
719  =cut  =cut
720  sub genome {  sub genome {
721          my ($self) = @_;          my ($self) = @_;
722          return $self->{_data}->{genome}->[0];          return $self->{_data}->genome();
723  }  }
724    
725  =head3 source  =head3 source
# Line 491  Line 730 
730  =cut  =cut
731  sub source {  sub source {
732          my ($self) = @_;          my ($self) = @_;
733          return $self->{_data}->{source}->[0];          return $self->{_data}->source();
734  }  }
735    
736  =head3 rights  =head3 rights
# Line 502  Line 741 
741  =cut  =cut
742  sub rights {  sub rights {
743          my ($self,$username) = @_;          my ($self,$username) = @_;
   
744          if ($self->public()) {          if ($self->public()) {
745                  return 1;                  return 1;
746          }          }
# Line 510  Line 748 
748                  return 0;                  return 0;
749          }          }
750          if (!defined($self->{_userrights}->{$username})) {          if (!defined($self->{_userrights}->{$username})) {
751                  if (defined($self->{_data}->{master})) {                  $self->{_userrights}->{$self->{_data}->owner()} = 1;
752                          for (my $i=0; $i < @{$self->{_data}->{master}};$i++) {                  my @users = split(/\|/,$self->{_data}->users());
753                                  $self->{_userrights}->{$self->{_data}->{master}->[$i]} = 1;                  for (my $i=0; $i < @users;$i++) {
754                          }                          $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;  
                         }  
755                  }                  }
756          }          }
757          return $self->{_userrights}->{$username};          return $self->{_userrights}->{$username};
# Line 532  Line 765 
765  =cut  =cut
766  sub public {  sub public {
767          my ($self) = @_;          my ($self) = @_;
768            if ($self->{_data}->users() eq "all") {
769          if (!defined($self->{_public})) {                  return 1;
                 $self->{_public} = 0;  
                 if (defined($self->{_data}->{users}->[0]) && $self->{_data}->{users}->[0] eq "all") {  
                         $self->{_public} = 1;  
                 }  
770          }          }
771          return $self->{_public};          return 0;
772  }  }
773    
774  =head3 directory  =head3 directory
# Line 587  Line 816 
816          return $self->directory().$self->id().$self->selected_version().".txt";          return $self->directory().$self->id().$self->selected_version().".txt";
817  }  }
818    
 =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};  
         }  
 }  
   
819  =head3 version  =head3 version
820  Definition:  Definition:
821          string = FIGMODELmodel->version();          string = FIGMODELmodel->version();
# Line 638  Line 827 
827    
828          if (!defined($self->{_version})) {          if (!defined($self->{_version})) {
829                  if (!defined($self->{_selectedversion})) {                  if (!defined($self->{_selectedversion})) {
830                          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];  
                         }  
831                  } else {                  } else {
832                          $self->{_version} = $self->{_selectedversion};                          $self->{_version} = $self->{_selectedversion};
833                  }                  }
# Line 671  Line 858 
858  =cut  =cut
859  sub modification_time {  sub modification_time {
860          my ($self) = @_;          my ($self) = @_;
861          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};  
862  }  }
863    
864  =head3 gene_reactions  =head3 gene_reactions
# Line 695  Line 869 
869  =cut  =cut
870  sub gene_reactions {  sub gene_reactions {
871          my ($self) = @_;          my ($self) = @_;
872            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};  
873  }  }
874    
875  =head3 total_compounds  =head3 total_compounds
# Line 714  Line 880 
880  =cut  =cut
881  sub total_compounds {  sub total_compounds {
882          my ($self) = @_;          my ($self) = @_;
883            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};  
884  }  }
885    
886  =head3 gapfilling_reactions  =head3 gapfilling_reactions
# Line 733  Line 891 
891  =cut  =cut
892  sub gapfilling_reactions {  sub gapfilling_reactions {
893          my ($self) = @_;          my ($self) = @_;
894            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};  
895  }  }
896    
897  =head3 total_reactions  =head3 total_reactions
# Line 752  Line 902 
902  =cut  =cut
903  sub total_reactions {  sub total_reactions {
904          my ($self) = @_;          my ($self) = @_;
905            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};  
906  }  }
907    
908  =head3 model_genes  =head3 model_genes
# Line 771  Line 913 
913  =cut  =cut
914  sub model_genes {  sub model_genes {
915          my ($self) = @_;          my ($self) = @_;
916            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};  
917  }  }
918    
919  =head3 class  =head3 class
# Line 790  Line 924 
924  =cut  =cut
925  sub class {  sub class {
926          my ($self) = @_;          my ($self) = @_;
927            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];  
                 }  
928          }          }
929          return $self->{_class};  
930    sub autocompleteMedia {
931            my ($self) = @_;
932            return $self->{_data}->autoCompleteMedia();
933  }  }
934    
935  =head3 taxonomy  =head3 taxonomy
# Line 866  Line 997 
997                          if (defined($self->mgdata())) {                          if (defined($self->mgdata())) {
998                                  $self->{_genome_genes} = $self->mgdata()->genome_contig_count;                                  $self->{_genome_genes} = $self->mgdata()->genome_contig_count;
999                          }                          }
1000                  } elsif (defined($self->stats())) {                  } else {
1001                          $self->{_genome_genes} = $self->stats()->{'Total genes'}->[0];                          $self->{_genome_genes} = $self->figmodel()->get_genome_stats($self->genome())->{"TOTAL GENES"}->[0];
1002                  }                  }
1003          }          }
1004    
# Line 892  Line 1023 
1023          #Checking that the table is defined and the output file exists          #Checking that the table is defined and the output file exists
1024          if (defined($result) && defined($result->get_row(0)->{"ESSENTIALGENES"})) {          if (defined($result) && defined($result->get_row(0)->{"ESSENTIALGENES"})) {
1025                  $self->figmodel()->database()->print_array_to_file($self->directory()."EssentialGenes-".$self->id()."-".$Media.".tbl",[join("\n",@{$result->get_row(0)->{"ESSENTIALGENES"}})]);                  $self->figmodel()->database()->print_array_to_file($self->directory()."EssentialGenes-".$self->id()."-".$Media.".tbl",[join("\n",@{$result->get_row(0)->{"ESSENTIALGENES"}})]);
1026            } else {
1027                    $self->figmodel()->error_message("FIGMODELmodel:run_default_model_predictions:could not identify essential reactions for model ".$self->id().$self->selected_version().".");
1028                    return $self->figmodel()->fail();
1029          }          }
1030    
1031          #Classifying reactions and compounds          #Classifying reactions and compounds
1032          my $tbl = $self->classify_model_reactions($Media);          my $tbl = $self->classify_model_reactions($Media);
1033            if (!defined($tbl)) {
1034                    $self->figmodel()->error_message("FIGMODELmodel:run_default_model_predictions:could not classify reactions for model ".$self->id().$self->selected_version().".");
1035                    return $self->figmodel()->fail();
1036            }
1037          $tbl->save();          $tbl->save();
1038    
1039          return $self->figmodel()->success();          return $self->figmodel()->success();
1040  }  }
1041    
 =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();  
         }  
 }  
   
1042  =head3 update_stats_for_gap_filling  =head3 update_stats_for_gap_filling
1043  Definition:  Definition:
1044          {string => [string]} = FIGMODELmodel->update_stats_for_gap_filling(int::gapfill time);          {string => [string]} = FIGMODELmodel->update_stats_for_gap_filling(int::gapfill time);
# Line 925  Line 1046 
1046  =cut  =cut
1047  sub update_stats_for_gap_filling {  sub update_stats_for_gap_filling {
1048          my ($self,$gapfilltime) = @_;          my ($self,$gapfilltime) = @_;
1049            $self->{_data}->autoCompleteTime($gapfilltime);
1050          #preserving the stats for the now obselete model          $self->{_data}->autocompleteDate(time());
1051          $self->save_obsolete_stats();          $self->{_data}->modificationDate(time());
1052          my $stats = $self->update_model_stats(0);          my $version = $self->{_data}->autocompleteVersion();
1053          $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;  
1054  }  }
1055    
1056  =head3 update_stats_for_build  =head3 update_stats_for_build
# Line 948  Line 1060 
1060  =cut  =cut
1061  sub update_stats_for_build {  sub update_stats_for_build {
1062          my ($self) = @_;          my ($self) = @_;
1063            $self->{_data}->builtDate(time());
1064          #preserving the stats for the now obselete model          $self->{_data}->modificationDate(time());
1065          $self->save_obsolete_stats();          my $version = $self->{_data}->version();
1066          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;  
1067  }  }
1068    
1069  =head3 update_model_stats  =head3 update_model_stats
# Line 979  Line 1082 
1082          }          }
1083          my $cpdtbl = $self->compound_table();          my $cpdtbl = $self->compound_table();
1084    
1085          #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];  
         }  
   
1086          my %GeneHash;          my %GeneHash;
1087          my %NonpegHash;          my %NonpegHash;
1088          my %CompoundHash;          my %CompoundHash;
1089            my $spontaneousReactions = 0;
1090            my $gapFillReactions = 0;
1091            my $biologReactions = 0;
1092            my $transporters = 0;
1093            my $autoCompleteReactions = 0;
1094            my $associatedSubsystemGenes = 0;
1095          for (my $i=0; $i < $rxntbl->size(); $i++) {          for (my $i=0; $i < $rxntbl->size(); $i++) {
1096                  my $Row = $rxntbl->get_row($i);                  my $Row = $rxntbl->get_row($i);
1097                  if (defined($Row) && defined($Row->{"ASSOCIATED PEG"})) {                  if (defined($Row) && defined($Row->{"ASSOCIATED PEG"})) {
# Line 1037  Line 1099 
1099                          if (defined($ReactionRow->{"EQUATION"}->[0])) {                          if (defined($ReactionRow->{"EQUATION"}->[0])) {
1100                                  #Checking for extracellular metabolites which indicate that this is a transporter                                  #Checking for extracellular metabolites which indicate that this is a transporter
1101                                  if ($ReactionRow->{"EQUATION"}->[0] =~ m/\[e\]/) {                                  if ($ReactionRow->{"EQUATION"}->[0] =~ m/\[e\]/) {
1102                                          $CurrentStats->{"Transport reaction"}->[0]++;                                          $transporters++;
1103                                  }                                  }
1104                          }                          }
1105                          #Identifying spontaneous/biolog/gapfilling/gene associated reactions                          #Identifying spontaneous/biolog/gapfilling/gene associated reactions
1106                          if ($Row->{"ASSOCIATED PEG"}->[0] =~ m/BIOLOG/i) {                          if ($Row->{"ASSOCIATED PEG"}->[0] =~ m/BIOLOG/i) {
1107                                  $CurrentStats->{"Biolog gap filling reactions"}->[0]++;                                  $biologReactions++;
1108                            } elsif ($Row->{"ASSOCIATED PEG"}->[0] =~ m/GROW/i) {
1109                                    $gapFillReactions++;
1110                          } elsif ($Row->{"ASSOCIATED PEG"}->[0] =~ m/SPONTANEOUS/i) {                          } elsif ($Row->{"ASSOCIATED PEG"}->[0] =~ m/SPONTANEOUS/i) {
1111                                  $CurrentStats->{"Spontaneous"}->[0]++;                                  $spontaneousReactions++;
1112                          } 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) {
1113                                  $CurrentStats->{"Gap filling reactions"}->[0]++;                                  $autoCompleteReactions++;
1114                          } else {                          } else {
1115                                  foreach my $GeneSet (@{$Row->{"ASSOCIATED PEG"}}) {                                  foreach my $GeneSet (@{$Row->{"ASSOCIATED PEG"}}) {
1116                                          my @GeneList = split(/\+/,$GeneSet);                                          $_ = $GeneSet;
1117                                            my @GeneList = /(peg\.\d+)/g;
1118                                          foreach my $Gene (@GeneList) {                                          foreach my $Gene (@GeneList) {
1119                                                  if ($Gene =~ m/(peg\.\d+)/) {                                                  if ($Gene =~ m/(peg\.\d+)/) {
1120                                                          $GeneHash{$1} = 1;                                                          $GeneHash{$1} = 1;
# Line 1063  Line 1128 
1128          }          }
1129          my @genes = keys(%GeneHash);          my @genes = keys(%GeneHash);
1130          my @othergenes = keys(%NonpegHash);          my @othergenes = keys(%NonpegHash);
         $CurrentStats->{"Genes with reactions"}->[0] = @genes + @othergenes;  
1131    
1132          #Updating the stats stored in the table          #Setting the reaction count
1133          $self->figmodel()->database()->update_row("MODEL STATS",$CurrentStats,"Model ID");          $self->{_data}->reactions($rxntbl->size());
1134          $self->{_stats} = $CurrentStats;          #Setting the metabolite count
1135          return $CurrentStats;          $self->{_data}->compounds($rxntbl->size());
1136            #Setting the gene count
1137            my $geneCount = @genes + @othergenes;
1138            $self->{_data}->associatedGenes($geneCount);
1139            #Setting remaining stats
1140            $self->{_data}->spontaneousReactions($spontaneousReactions);
1141            $self->{_data}->gapFillReactions($gapFillReactions);
1142            $self->{_data}->biologReactions($biologReactions);
1143            $self->{_data}->transporters($transporters);
1144            $self->{_data}->autoCompleteReactions($autoCompleteReactions);
1145            $self->{_data}->associatedSubsystemGenes($associatedSubsystemGenes);
1146            #Setting the model class
1147            my $class = "";
1148            for (my $i=0; $i < @{$self->figmodel()->config("class list")}; $i++) {
1149                    if (defined($self->figmodel()->config($self->figmodel()->config("class list")->[$i]))) {
1150                            if (defined($self->figmodel()->config($self->figmodel()->config("class list")->[$i])->{$self->id()})) {
1151                                    $class = $self->figmodel()->config("class list")->[$i];
1152                                    last;
1153                            }
1154                            if ($class eq "" && defined($self->figmodel()->config($self->figmodel()->config("class list")->[$i])->{$self->genome()})) {
1155                                    $class = $self->figmodel()->config("class list")->[$i];
1156                            }
1157                    }
1158            }
1159            if ($class eq "") {
1160                    $class = $self->figmodel()->get_genome_stats($self->genome())->{CLASS}->[0];
1161            }
1162            if ($class eq "") {
1163                    $class = "unknown";
1164            }
1165            $self->{_data}->cellwalltype($class);
1166  }  }
1167    
1168  =head3 GapFillModel  =head3 GapFillModel
# Line 1088  Line 1182 
1182          my $UniqueFilename = $self->figmodel()->filename();          my $UniqueFilename = $self->figmodel()->filename();
1183          my $StartTime = time();          my $StartTime = time();
1184    
1185          #Archiving the existing model          #Reading original reaction table
1186          $self->ArchiveModel();          my $OriginalRxn = $self->reaction_table();
1187            #Clearing the table
1188            $self->reaction_table(1);
1189    
1190          #Removing any gapfilling reactions that may be currently present in the model          #Removing any gapfilling reactions that may be currently present in the model
1191          if (!defined($donotclear) || $donotclear != 1) {          if (!defined($donotclear) || $donotclear != 1) {
1192                  my $ModelTable = $self->reaction_table();                  my $ModelTable = $self->reaction_table();
1193                  for (my $i=0; $i < $ModelTable->size(); $i++) {                  for (my $i=0; $i < $ModelTable->size(); $i++) {
1194                          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/) {
1195                                  $ModelTable->delete_row($i);                                  $ModelTable->delete_row($i);
1196                                  $i--;                                  $i--;
1197                          }                          }
# Line 1119  Line 1215 
1215                          }                          }
1216                  }                  }
1217                  $MediaTable->save($self->config("Media directory")->[0].$UniqueFilename."TestMedia.txt");                  $MediaTable->save($self->config("Media directory")->[0].$UniqueFilename."TestMedia.txt");
1218                  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";
1219                    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));
1220                  unlink($self->config("Media directory")->[0].$UniqueFilename."TestMedia.txt");                  unlink($self->config("Media directory")->[0].$UniqueFilename."TestMedia.txt");
1221          } else {          } else {
1222                  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";
1223                    system($self->figmodel()->GenerateMFAToolkitCommandLineCall($UniqueFilename,$self->id(),undef,["GapFilling"],{"Reactions to knockout" => $self->config("permanently knocked out reactions")->[0]},"GapFill".$self->id().".log",undef));
1224          }          }
1225    
1226          #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
1227          my $SolutionData = $self->figmodel()->LoadProblemReport($UniqueFilename);          my $SolutionData = $self->figmodel()->LoadProblemReport($UniqueFilename);
1228    
1229          #Clearing the mfatoolkit output and log file          #Clearing the mfatoolkit output and log file
1230          $self->figmodel()->clearing_output($UniqueFilename,"GapFill".$self->id().".log");          $self->figmodel()->clearing_output($UniqueFilename,"GapFill".$self->id().".log");
1231          if (!defined($SolutionData) || $SolutionData->size() == 0) {          if (!defined($SolutionData) || $SolutionData->size() == 0) {
# Line 1140  Line 1239 
1239          for (my $i=($SolutionData->size()-1); $i >=0; $i--) {          for (my $i=($SolutionData->size()-1); $i >=0; $i--) {
1240                  if (defined($SolutionData->get_row($i)->{"Notes"}) && $SolutionData->get_row($i)->{"Notes"}->[0] =~ m/^Recursive/) {                  if (defined($SolutionData->get_row($i)->{"Notes"}) && $SolutionData->get_row($i)->{"Notes"}->[0] =~ m/^Recursive/) {
1241                          my $AllSolutions = substr($SolutionData->get_row($i)->{"Notes"}->[0],15);                          my $AllSolutions = substr($SolutionData->get_row($i)->{"Notes"}->[0],15);
                         print "Solution:".$AllSolutions."\n";  
1242                          my @TempThree = split(/\|/,$AllSolutions);                          my @TempThree = split(/\|/,$AllSolutions);
1243                          if (@TempThree > 0 && $TempThree[0] =~ m/.+:(.+)/) {                          if (@TempThree > 0 && $TempThree[0] =~ m/.+:(.+)/) {
1244                                  my @TempFour = split(/,/,$1);                                  my @TempFour = split(/,/,$1);
# Line 1163  Line 1261 
1261                                                  push(@{$ReactionList},$ID);                                                  push(@{$ReactionList},$ID);
1262                                          }                                          }
1263                                  }                                  }
1264                                  print "Solution:".$TempThree[0]."\n";                                  $self->figmodel()->IntegrateGrowMatchSolution($self->id(),undef,$ReactionList,$DirectionList,"AUTOCOMPLETION",0,1);
                                 $self->figmodel()->IntegrateGrowMatchSolution($self->id(),undef,$ReactionList,$DirectionList,"GAP FILLING",0,1);  
1265                          }                          }
1266                          last;                          last;
1267                  }                  }
1268          }          }
1269    
1270          #Updating model stats with gap filling results          #Updating model stats with gap filling results
1271          my $ElapsedTime = time() - $StartTime;          my $ElapsedTime = time() - $StartTime;
1272          $self->figmodel()->ClearDBModel($self->id(),1);          $self->reaction_table(1);
1273            $self->calculate_model_changes($OriginalRxn,"AUTOCOMPLETION");
1274    
1275          #Determining why each gap filling reaction was added          #Determining why each gap filling reaction was added
1276          $self->figmodel()->IdentifyDependancyOfGapFillingReactions($self->id(),$Media);          $self->figmodel()->IdentifyDependancyOfGapFillingReactions($self->id(),$Media);
1277          if (!defined($donotclear) || $donotclear != 1) {          if (!defined($donotclear) || $donotclear != 1) {
# Line 1191  Line 1291 
1291          return $self->success();          return $self->success();
1292  }  }
1293    
1294    =head3 calculate_model_changes
1295    Definition:
1296            FIGMODELmodel->calculate_model_changes(FIGMODELTable:original reaction table,string:modification cause);
1297    Description:
1298    
1299    =cut
1300    
1301    sub calculate_model_changes {
1302            my ($self,$originalReactions,$cause,$tbl,$version) = @_;
1303            my $modTime = time();
1304            if (!defined($version)) {
1305                    $version = $self->selected_version();
1306            }
1307            my $user = $self->figmodel()->user();
1308            #Getting the history table
1309            my $histTbl = $self->model_history();
1310            #Checking for differences
1311            if (!defined($tbl)) {
1312                    $tbl = $self->reaction_table();
1313            }
1314            for (my $i=0; $i < $tbl->size(); $i++) {
1315                    my $row = $tbl->get_row($i);
1316                    my $orgRow = $originalReactions->get_row_by_key($row->{LOAD}->[0],"LOAD");
1317                    if (!defined($orgRow)) {
1318                            $histTbl->add_row({Reaction => [$row->{LOAD}->[0]], DirectionChange => $row->{DIRECTIONALITY}, GeneChange => $row->{"ASSOCIATED PEG"}, Action => ["ADDED"], ModificationTime => [$modTime], ModifcationCause => [$cause], User => [$user], Version => [$version]});
1319                    } else {
1320                            my $geneChanges;
1321                            my $directionChange;
1322                            if ($orgRow->{"DIRECTIONALITY"}->[0] ne $row->{"DIRECTIONALITY"}->[0]) {
1323                                    $directionChange = $orgRow->{"DIRECTIONALITY"}->[0]." to ".$row->{"DIRECTIONALITY"}->[0];
1324                            }
1325                            for (my $j=0; $j < @{$row->{"ASSOCIATED PEG"}}; $j++) {
1326                                    my $match = 0;
1327                                    if (defined($orgRow->{"ASSOCIATED PEG"})) {
1328                                            for (my $k=0; $k < @{$orgRow->{"ASSOCIATED PEG"}}; $k++) {
1329                                                    if ($row->{"ASSOCIATED PEG"}->[$j] eq $orgRow->{"ASSOCIATED PEG"}->[$k]) {
1330                                                            $match = 1;
1331                                                    }
1332                                            }
1333                                    }
1334                                    if ($match == 0) {
1335                                            push(@{$geneChanges},"Added ".$row->{"ASSOCIATED PEG"}->[$j]);
1336                                    }
1337                            }
1338                            if (defined($orgRow->{"ASSOCIATED PEG"})) {
1339                                    for (my $k=0; $k < @{$orgRow->{"ASSOCIATED PEG"}}; $k++) {
1340                                            my $match = 0;
1341                                            if (defined($row->{"ASSOCIATED PEG"})) {
1342                                                    for (my $j=0; $j < @{$row->{"ASSOCIATED PEG"}}; $j++) {
1343                                                            if ($row->{"ASSOCIATED PEG"}->[$j] eq $orgRow->{"ASSOCIATED PEG"}->[$k]) {
1344                                                                    $match = 1;
1345                                                            }
1346                                                    }
1347                                            }
1348                                            if ($match == 0) {
1349                                                    push(@{$geneChanges},"Removed ".$orgRow->{"ASSOCIATED PEG"}->[$k]);
1350                                            }
1351                                    }
1352                            }
1353                            if ((defined($directionChange) && length($directionChange) > 0) || defined($geneChanges) && @{$geneChanges} > 0) {
1354                                    $histTbl->add_row({Reaction => [$row->{LOAD}->[0]], DirectionChange => [$directionChange], GeneChange => $geneChanges, Action => ["CHANGE"], ModificationTime => [$modTime], ModifcationCause => [$cause], User => [$user], Version => [$version]});
1355                            }
1356                    }
1357            }
1358            #Looking for removed reactions
1359            for (my $i=0; $i < $originalReactions->size(); $i++) {
1360                    my $row = $originalReactions->get_row($i);
1361                    my $orgRow = $tbl->get_row_by_key($row->{LOAD}->[0],"LOAD");
1362                    if (!defined($orgRow)) {
1363                            $histTbl->add_row({Reaction => [$row->{LOAD}->[0]], DirectionChange => $row->{DIRECTIONALITY}, GeneChange => $row->{"ASSOCIATED PEG"}, Action => ["REMOVED"], ModificationTime => [$modTime], ModifcationCause => [$cause], User => [$user], Version => [$version]});
1364                    }
1365            }
1366            $histTbl->save();
1367    }
1368    
1369    =head3 GapGenModel
1370    Definition:
1371            FIGMODELmodel->GapGenModel();
1372    Description:
1373            Runs the gap generation algorithm to correct a single false positive prediction. Results are loaded into a table.
1374    =cut
1375    
1376    sub GapGenModel {
1377            my ($self,$Media,$KOList,$NoKOList,$Experiment,$SolutionLimit) = @_;
1378    
1379            #Enforcing nonoptional arguments
1380            if (!defined($Media)) {
1381                    return undef;
1382            }
1383            if (!defined($KOList)) {
1384                    $KOList->[0] = "none";
1385            }
1386            if (!defined($NoKOList)) {
1387                    $NoKOList->[0] = "none";
1388            }
1389            if (!defined($Experiment)) {
1390                    $Experiment= "ReactionKO";
1391            }
1392            if (!defined($SolutionLimit)) {
1393                    $SolutionLimit = "10";
1394            }
1395    
1396            #Translating the KO lists into arrays
1397            if (ref($KOList) ne "ARRAY") {
1398                    my $temp = $KOList;
1399                    $KOList = ();
1400                    push(@{$KOList},split(/[,;]/,$temp));
1401            }
1402            my $noKOHash;
1403            if (defined($NoKOList) && ref($NoKOList) ne "ARRAY") {
1404                    my $temp = $NoKOList;
1405                    $NoKOList = ();
1406                    push(@{$NoKOList},split(/[,;]/,$temp));
1407                    foreach my $rxn (@{$NoKOList}) {
1408                            $noKOHash->{$rxn} = 1;
1409                    }
1410            }
1411    
1412            #Checking if solutions exist for the input parameters
1413            $self->aquireModelLock();
1414            my $tbl = $self->load_model_table("GapGenSolutions");
1415            my $solutionRow = $tbl->get_table_by_key($Experiment,"Experiment")->get_table_by_key($Media,"Media")->get_row_by_key(join(",",@{$KOList}),"KOlist");
1416            my $solutions;
1417            if (defined($solutionRow)) {
1418                    #Checking if any solutions conform to the no KO list
1419                    foreach my $solution (@{$solutionRow->{Solutions}}) {
1420                            my @reactions = split(/,/,$solution);
1421                            my $include = 1;
1422                            foreach my $rxn (@reactions) {
1423                                    if ($rxn =~ m/(rxn\d\d\d\d\d)/) {
1424                                            if (defined($noKOHash->{$1})) {
1425                                                    $include = 0;
1426                                            }
1427                                    }
1428                            }
1429                            if ($include == 1) {
1430                                    push(@{$solutions},$solution);
1431                            }
1432                    }
1433            } else {
1434                    $solutionRow = {Media => [$Media],Experiment => [$Experiment],KOlist => [join(",",@{$KOList})]};
1435                    $tbl->add_row($solutionRow);
1436                    $self->figmodel()->database()->save_table($tbl);
1437            }
1438            $self->releaseModelLock();
1439    
1440            #Returning solution list of solutions were found
1441            if (defined($solutions) && @{$solutions} > 0) {
1442                    return $solutions;
1443            }
1444    
1445            #Getting unique filename
1446            my $Filename = $self->figmodel()->filename();
1447    
1448            #Running the gap generation
1449            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));
1450            my $ProblemReport = $self->figmodel()->LoadProblemReport($Filename);
1451            if (!defined($ProblemReport)) {
1452                    $self->figmodel()->error_message("FIGMODEL:GapGenerationAlgorithm;No problem report;".$Filename.";".$self->id().$self->selected_version().";".$Media.";".$KOList.";".$NoKOList);
1453                    return undef;
1454            }
1455    
1456            #Clearing the output folder and log file
1457            $self->figmodel()->clearing_output($Filename,"Gapgeneration-".$self->id().$self->selected_version()."-".$Filename.".log");
1458    
1459            #Saving the solution
1460            $self->aquireModelLock();
1461            $tbl = $self->load_model_table("GapGenSolutions");
1462            $solutionRow = $tbl->get_table_by_key($Experiment,"Experiment")->get_table_by_key($Media,"Media")->get_row_by_key(join(",",@{$KOList}),"KOlist");
1463            for (my $j=0; $j < $ProblemReport->size(); $j++) {
1464                    if ($ProblemReport->get_row($j)->{"Notes"}->[0] =~ m/^Recursive\sMILP\s([^)]+)/) {
1465                            my @SolutionList = split(/\|/,$1);
1466                            for (my $k=0; $k < @SolutionList; $k++) {
1467                                    if ($SolutionList[$k] =~ m/(\d+):(.+)/) {
1468                                            push(@{$solutionRow->{Solutions}},$2);
1469                                            push(@{$solutions},$2);
1470                                    }
1471                            }
1472                    }
1473            }
1474            $self->figmodel()->database()->save_table($tbl);
1475            $self->releaseModelLock();
1476    
1477            return $solutions;
1478    }
1479    
1480  =head3 datagapfill  =head3 datagapfill
1481  Definition:  Definition:
1482          success()/fail() = FIGMODELmodel->datagapfill();          success()/fail() = FIGMODELmodel->datagapfill();
# Line 1201  Line 1487 
1487          my ($self,$GapFillingRunSpecs,$TansferFileSuffix) = @_;          my ($self,$GapFillingRunSpecs,$TansferFileSuffix) = @_;
1488          my $UniqueFilename = $self->figmodel()->filename();          my $UniqueFilename = $self->figmodel()->filename();
1489          if (defined($GapFillingRunSpecs) && @{$GapFillingRunSpecs} > 0) {          if (defined($GapFillingRunSpecs) && @{$GapFillingRunSpecs} > 0) {
                 print "Gap filling specs:\n".join("\n",@{$GapFillingRunSpecs})."\n\n";  
1490                  system($self->figmodel()->GenerateMFAToolkitCommandLineCall($UniqueFilename,$self->id().$self->selected_version(),"NoBounds",["DataGapFilling"],{"Reactions to knockout" => $self->config("permanently knocked out reactions")->[0],"Gap filling runs" => join(";",@{$GapFillingRunSpecs})},"GapFilling-".$self->id().$self->selected_version()."-".$UniqueFilename.".log",undef,undef));                  system($self->figmodel()->GenerateMFAToolkitCommandLineCall($UniqueFilename,$self->id().$self->selected_version(),"NoBounds",["DataGapFilling"],{"Reactions to knockout" => $self->config("permanently knocked out reactions")->[0],"Gap filling runs" => join(";",@{$GapFillingRunSpecs})},"GapFilling-".$self->id().$self->selected_version()."-".$UniqueFilename.".log",undef,undef));
   
1491                  #Checking that the solution exists                  #Checking that the solution exists
1492                  if (!-e $self->config("MFAToolkit output directory")->[0].$UniqueFilename."/GapFillingSolutionTable.txt") {                  if (!-e $self->config("MFAToolkit output directory")->[0].$UniqueFilename."/GapFillingSolutionTable.txt") {
1493                          $self->figmodel()->error_message("FIGMODEL:GapFillingAlgorithm: Could not find MFA output file!");                          $self->figmodel()->error_message("FIGMODEL:GapFillingAlgorithm: Could not find MFA output file!");
# Line 1213  Line 1497 
1497                  my $GapFillResultTable = $self->figmodel()->database()->load_table($self->config("MFAToolkit output directory")->[0].$UniqueFilename."/GapFillingSolutionTable.txt",";","",0,undef);                  my $GapFillResultTable = $self->figmodel()->database()->load_table($self->config("MFAToolkit output directory")->[0].$UniqueFilename."/GapFillingSolutionTable.txt",";","",0,undef);
1498                  if (defined($TansferFileSuffix)) {                  if (defined($TansferFileSuffix)) {
1499                          system("cp ".$self->config("MFAToolkit output directory")->[0].$UniqueFilename."/GapFillingSolutionTable.txt ".$self->directory().$self->id().$self->selected_version()."-".$TansferFileSuffix.".txt");                          system("cp ".$self->config("MFAToolkit output directory")->[0].$UniqueFilename."/GapFillingSolutionTable.txt ".$self->directory().$self->id().$self->selected_version()."-".$TansferFileSuffix.".txt");
                         system("cp ".$self->config("MFAToolkit output directory")->[0].$UniqueFilename."/GapFillingReport.txt ".$self->directory().$self->id().$self->selected_version()."-".$TansferFileSuffix.".txt");  
1500                  }                  }
   
1501                  #If the system is not configured to preserve all logfiles, then the mfatoolkit output folder is deleted                  #If the system is not configured to preserve all logfiles, then the mfatoolkit output folder is deleted
1502                  $self->figmodel()->clearing_output($UniqueFilename,"GapFilling-".$self->id().$self->selected_version()."-".$UniqueFilename.".log");                  $self->figmodel()->clearing_output($UniqueFilename,"GapFilling-".$self->id().$self->selected_version()."-".$UniqueFilename.".log");
1503                  return $GapFillingRunSpecs;                  return $GapFillResultTable;
1504          }          }
1505          if (defined($TansferFileSuffix)) {          if (defined($TansferFileSuffix)) {
1506                  $self->figmodel()->database()->print_array_to_file($self->directory().$self->id().$self->selected_version()."-".$TansferFileSuffix.".txt",["Experiment;Solution index;Solution cost;Solution reactions"]);                  $self->figmodel()->database()->print_array_to_file($self->directory().$self->id().$self->selected_version()."-".$TansferFileSuffix.".txt",["Experiment;Solution index;Solution cost;Solution reactions"]);
# Line 1284  Line 1566 
1566                          push(@{$DirectionArray},$SolutionHash{$ReactionList[$k]});                          push(@{$DirectionArray},$SolutionHash{$ReactionList[$k]});
1567                  }                  }
1568                  print "Integrating solution!\n";                  print "Integrating solution!\n";
1569                  $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);
1570                  my $model = $self->get_model($self->id().$TempVersion);                  $self->PrintModelLPFile();
                 $model->PrintModelLPFile();  
1571                  #Running the model against all available experimental data                  #Running the model against all available experimental data
1572                  print "Running test model!\n";                  print "Running test model!\n";
1573                  my ($FalsePostives,$FalseNegatives,$CorrectNegatives,$CorrectPositives,$Errorvector,$HeadingVector) = $self->RunAllStudiesWithDataFast("All");                  my ($FalsePostives,$FalseNegatives,$CorrectNegatives,$CorrectPositives,$Errorvector,$HeadingVector) = $self->RunAllStudiesWithDataFast("All");
# Line 1322  Line 1603 
1603  =cut  =cut
1604  sub status {  sub status {
1605          my ($self) = @_;          my ($self) = @_;
1606          return $self->{_data}->{status}->[0];          return $self->{_data}->status();
1607  }  }
1608    
1609  =head3 message  =head3 message
# Line 1333  Line 1614 
1614  =cut  =cut
1615  sub message {  sub message {
1616          my ($self) = @_;          my ($self) = @_;
1617          return $self->{_data}->{message}->[0];          return $self->{_data}->message();
1618  }  }
1619    
1620  =head3 set_status  =head3 set_status
# Line 1348  Line 1629 
1629  =cut  =cut
1630  sub set_status {  sub set_status {
1631          my ($self,$NewStatus,$Message) = @_;          my ($self,$NewStatus,$Message) = @_;
1632            $self->{_data}->status($NewStatus);
1633          #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");  
1634          return $self->config("SUCCESS")->[0];          return $self->config("SUCCESS")->[0];
1635  }  }
1636    
# Line 1367  Line 1645 
1645  sub CreateSingleGenomeReactionList {  sub CreateSingleGenomeReactionList {
1646          my ($self,$RunGapFilling) = @_;          my ($self,$RunGapFilling) = @_;
1647    
1648            #Creating directory
1649            if ($self->owner() ne "master" && !-d $self->figmodel()->config("organism directory")->[0].$self->owner()."/") {
1650                    system("mkdir ".$self->figmodel()->config("organism directory")->[0].$self->owner()."/");
1651            } elsif ($self->owner() eq "master" && !-d $self->figmodel()->config("organism directory")->[0].$self->genome()."/") {
1652                    system("mkdir ".$self->figmodel()->config("organism directory")->[0].$self->genome()."/");
1653            }
1654            if ($self->owner() ne "master" && !-d $self->figmodel()->config("organism directory")->[0].$self->owner()."/".$self->genome()."/") {
1655                    system("mkdir ".$self->figmodel()->config("organism directory")->[0].$self->owner()."/".$self->genome()."/");
1656            }
1657    
1658          #Getting genome stats          #Getting genome stats
1659          my $genomestats = $self->figmodel()->get_genome_stats($self->genome());          my $genomestats = $self->figmodel()->get_genome_stats($self->genome());
1660          my $FeatureTable = $self->figmodel()->GetGenomeFeatureTable($self->genome());          my $FeatureTable = $self->figmodel()->GetGenomeFeatureTable($self->genome());
# Line 1381  Line 1669 
1669          }          }
1670          #Setting up needed variables          #Setting up needed variables
1671          my $OriginalModelTable = undef;          my $OriginalModelTable = undef;
1672          #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) {  
1673                  $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");  
1674                  return $self->fail();                  return $self->fail();
1675          }elsif ($Row->{status}->[0] == 1) {          }elsif ($self->status() == 1) {
1676                  $OriginalModelTable = $self->reaction_table();                  $OriginalModelTable = $self->reaction_table();
1677                  $self->ArchiveModel();                  $self->set_status(0,"Rebuilding preliminary reconstruction");
                 $Row->{status}->[0] = 0;  
                 $Row->{message}->[0] = "Rebuilding preliminary reconstruction";  
1678          } else {          } else {
1679                  $Row->{status}->[0] = 0;                  $self->set_status(0,"Preliminary reconstruction");
                 $Row->{message}->[0] = "Preliminary reconstruction";  
1680          }          }
         #Updating the status table  
         $self->figmodel()->database()->save_table($ModelTable);  
         $self->figmodel()->database()->UnlockDBTable("MODELS");  
1681          #Sorting GenomeData by gene location on the chromosome          #Sorting GenomeData by gene location on the chromosome
1682            my $ftrTbl = $self->figmodel()->database()->get_table("ROLERXNMAPPING");
1683          $FeatureTable->sort_rows("MIN LOCATION");          $FeatureTable->sort_rows("MIN LOCATION");
1684          my ($ComplexHash,$SuggestedMappings,$UnrecognizedReactions,$ReactionHash);          my ($ComplexHash,$SuggestedMappings,$UnrecognizedReactions,$ReactionHash);
1685          my %LastGenePosition;          my %LastGenePosition;
# Line 1476  Line 1751 
1751                          }                          }
1752                  }                  }
1753          }          }
   
1754          #Creating nonadjacent complexes          #Creating nonadjacent complexes
1755          my @ReactionList = keys(%{$ReactionHash});          my @ReactionList = keys(%{$ReactionHash});
1756          foreach my $Reaction (@ReactionList) {          foreach my $Reaction (@ReactionList) {
# Line 1582  Line 1856 
1856                  $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"]});
1857          }          }
1858    
1859            #Getting feature rows for features that are lumped
1860            my @rows = $ftrTbl->get_rows_by_key("2","MASTER");
1861            for (my $i=0; $i < @rows; $i++) {
1862                    my $rxn = $rows[$i]->{REACTION}->[0];
1863                    my $role = $rows[$i]->{ROLE}->[0];
1864                    my @orgrows = $FeatureTable->get_rows_by_key($role,"ROLES");
1865                    my $genes;
1866                    for (my $j=0; $j < @orgrows; $j++) {
1867                            if ($orgrows[$j]->{ID}->[0] =~ m/(peg\.\d+)/) {
1868                                    push(@{$genes},$1);
1869                            }
1870                    }
1871                    if (defined($genes) && @{$genes} > 0) {
1872                            my $row = $NewModelTable->get_row_by_key($rxn,"LOAD");
1873                            my $newGeneAssociations;
1874                            for (my $k=0; $k < @{$genes}; $k++) {
1875                                    for (my $j=0; $j < @{$row->{"ASSOCIATED PEG"}}; $j++) {
1876                                            my $peg = $genes->[$k];
1877                                            if ($row->{"ASSOCIATED PEG"}->[$j] !~ m/$peg/) {
1878                                                    push(@{$newGeneAssociations},$row->{"ASSOCIATED PEG"}->[$j]."+".$peg);
1879                                            }
1880                                    }
1881                            }
1882                            $row->{"ASSOCIATED PEG"} = $newGeneAssociations;
1883                    }
1884            }
1885    
1886          #Adding the spontaneous and universal reactions          #Adding the spontaneous and universal reactions
1887          foreach my $ReactionID (@{$self->config("spontaneous reactions")}) {          foreach my $ReactionID (@{$self->config("spontaneous reactions")}) {
1888                  #Getting the thermodynamic reversibility from the database                  #Getting the thermodynamic reversibility from the database
# Line 1601  Line 1902 
1902          }          }
1903    
1904          #Checking if a biomass reaction already exists          #Checking if a biomass reaction already exists
1905          my $BiomassReactionRow = $self->figmodel()->database()->get_row_by_key("BIOMASS TABLE",$self->id(),"MODELS");          my $BiomassReactionRow = $self->BuildSpecificBiomassReaction();
         if (!defined($BiomassReactionRow)) {  
                 $BiomassReactionRow = $self->BuildSpecificBiomassReaction();  
1906                  if (!defined($BiomassReactionRow)) {                  if (!defined($BiomassReactionRow)) {
1907                          $self->set_status(-2,"Preliminary reconstruction failed: could not generate biomass reaction");                          $self->set_status(-2,"Preliminary reconstruction failed: could not generate biomass reaction");
1908                          $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()."!");
1909                          return $self->fail();                          return $self->fail();
1910                  }                  }
         }  
1911          my $ReactionList = $BiomassReactionRow->{"ESSENTIAL REACTIONS"};          my $ReactionList = $BiomassReactionRow->{"ESSENTIAL REACTIONS"};
1912          push(@{$ReactionList},$BiomassReactionRow->{DATABASE}->[0]);          push(@{$ReactionList},$BiomassReactionRow->{DATABASE}->[0]);
1913    
# Line 1641  Line 1939 
1939                  }                  }
1940          }          }
1941    
1942            #If an original model exists, we copy the gap filling solution from that model
1943            if (defined($OriginalModelTable)) {
1944                    for (my $i=0; $i < $OriginalModelTable->size(); $i++) {
1945                            if ($OriginalModelTable->get_row($i)->{"ASSOCIATED PEG"}->[0] =~ m/GAP/ && $OriginalModelTable->get_row($i)->{"ASSOCIATED PEG"}->[0] ne "INITIAL GAP FILLING") {
1946                                    my $Row = $NewModelTable->get_row_by_key($OriginalModelTable->get_row($i)->{"LOAD"}->[0],"LOAD");
1947                                    if (!defined($Row)) {
1948                                            $NewModelTable->add_row($OriginalModelTable->get_row($i));
1949                                    }
1950                            }
1951                    }
1952            }
1953    
1954          #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
1955          if (defined($OriginalModelTable)) {          if (defined($OriginalModelTable)) {
1956                  my $PerfectMatch = 1;                  my $PerfectMatch = 1;
# Line 1700  Line 2010 
2010          #Saving the new model to file          #Saving the new model to file
2011          $self->set_status(1,"Preliminary reconstruction complete");          $self->set_status(1,"Preliminary reconstruction complete");
2012          $self->figmodel()->database()->save_table($NewModelTable);          $self->figmodel()->database()->save_table($NewModelTable);
2013          $self->{_reaction_data} = $NewModelTable;          $self->reaction_table(1);
         #Clearing the previous model from the cache  
         $self->figmodel()->ClearDBModel($self->id(),1);  
2014          #Updating the model stats table          #Updating the model stats table
2015          $self->update_stats_for_build();          $self->update_stats_for_build();
2016          $self->PrintSBMLFile();          $self->PrintSBMLFile();
2017            if (defined($OriginalModelTable)) {
2018                    $self->calculate_model_changes($OriginalModelTable,"REBUILD");
2019            }
2020    
2021          #Adding model to gapfilling queue          #Adding model to gapfilling queue
2022          if (defined($RunGapFilling) && $RunGapFilling == 1) {          if (defined($RunGapFilling) && $RunGapFilling == 1) {
# Line 1823  Line 2134 
2134          }          }
2135    
2136          #Clearing the previous model from the cache          #Clearing the previous model from the cache
2137          $self->figmodel()->ClearDBModel($self->id(),1);          $self->figmodel()->database()->ClearDBModel($self->id(),1);
2138          $ModelTable->save();          $ModelTable->save();
2139    
2140          return $self->success();          return $self->success();
# Line 1839  Line 2150 
2150  sub ArchiveModel {  sub ArchiveModel {
2151          my ($self) = @_;          my ($self) = @_;
2152    
         #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();  
         }  
   
2153          #Checking that the model file exists          #Checking that the model file exists
2154          if (!(-e $self->filename())) {          if (!(-e $self->filename())) {
2155                  $self->figmodel()->error_message("FIGMODEL:ArchiveModel: Model file ".$self->filename()." not found!");                  $self->figmodel()->error_message("FIGMODEL:ArchiveModel: Model file ".$self->filename()." not found!");
# Line 1895  Line 2200 
2200          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
2201  =cut  =cut
2202  sub run_microarray_analysis {  sub run_microarray_analysis {
2203          my ($self,$media,$jobid,$index,$genecall) = @_;          my ($self,$media,$label,$index,$genecall) = @_;
2204          $genecall =~ s/_/:/g;          $genecall =~ s/_/:/g;
2205          $genecall =~ s/\//;/g;          $genecall =~ s/\//;/g;
2206          #print "\n\n".$genecall."\n\n";          my $uniqueFilename = $self->figmodel()->filename();
2207          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";  
2208          system($command);          system($command);
2209          #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";
2210            if (-e $filename) {
2211                    my $output = $self->figmodel()->database()->load_single_column_file($filename);
2212                    if (defined($output->[0])) {
2213                            my @array = split(/;/,$output->[0]);
2214                            $self->figmodel()->clearing_output($uniqueFilename,"MicroarrayAnalysis-".$uniqueFilename.".txt");
2215                            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]);
2216                    }
2217                    print STDERR $filename." is empty!";
2218            }
2219            print STDERR $filename." not found!";
2220            $self->figmodel()->clearing_output($uniqueFilename,"MicroarrayAnalysis-".$uniqueFilename.".txt");
2221    
2222            return undef;
2223  }  }
2224    
2225  =head3 find_minimal_pathways  =head3 find_minimal_pathways
# Line 1912  Line 2229 
2229          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
2230  =cut  =cut
2231  sub find_minimal_pathways {  sub find_minimal_pathways {
2232          my ($self,$media,$objective,$solutionnum) = @_;          my ($self,$media,$objective,$solutionnum,$AllReversible,$additionalexchange) = @_;
2233    
2234          #Setting default media          #Setting default media
2235          if (!defined($media)) {          if (!defined($media)) {
# Line 1924  Line 2241 
2241                  $solutionnum = "5";                  $solutionnum = "5";
2242          }          }
2243    
2244            #Setting additional exchange fluxes
2245            if (!defined($additionalexchange) || length($additionalexchange) == 0) {
2246                    if ($self->id() eq "iAF1260") {
2247                            $additionalexchange = "cpd03422[c]:-100:100;cpd01997[c]:-100:100;cpd11416[c]:-100:0;cpd15378[c]:-100:0;cpd15486[c]:-100:0";
2248                    } else {
2249                            $additionalexchange = $self->figmodel()->config("default exchange fluxes")->[0];
2250                    }
2251            }
2252    
2253          #Translating objective          #Translating objective
2254          my $objectivestring;          my $objectivestring;
2255          if ($objective eq "ALL") {          if ($objective eq "ALL") {
# Line 1944  Line 2270 
2270                          }                          }
2271                  }                  }
2272                  for (my $i=0; $i < @objectives; $i++) {                  for (my $i=0; $i < @objectives; $i++) {
2273                          $self->find_minimal_pathways($media,$objectives[$i])                          $self->find_minimal_pathways($media,$objectives[$i]);
2274                  }                  }
2275                    return;
2276          } elsif ($objective eq "ENERGY") {          } elsif ($objective eq "ENERGY") {
2277                  $objectivestring = "MAX;FLUX;rxn00062;c;1";                  $objectivestring = "MAX;FLUX;rxn00062;c;1";
2278          } elsif ($objective =~ m/cpd\d\d\d\d\d/) {          } elsif ($objective =~ m/cpd\d\d\d\d\d/) {
2279                    if ($objective =~ m/\[(\w)\]/) {
2280                            $objectivestring = "MIN;DRAIN_FLUX;".$objective.";".$1.";1";
2281                            $additionalexchange .= ";".$objective."[".$1."]:-100:0";
2282                    } else {
2283                  $objectivestring = "MIN;DRAIN_FLUX;".$objective.";c;1";                  $objectivestring = "MIN;DRAIN_FLUX;".$objective.";c;1";
2284                            $additionalexchange .= ";".$objective."[c]:-100:0";
2285                    }
2286            } elsif ($objective =~ m/(rxn\d\d\d\d\d)/) {
2287                    my ($Reactants,$Products) = $self->figmodel()->GetReactionSubstrateData($objective);
2288                    for (my $i=0; $i < @{$Products};$i++) {
2289                            my $temp = $Products->[$i]->{"DATABASE"}->[0];
2290                            if ($additionalexchange !~ m/$temp/) {
2291                                    #$additionalexchange .= ";".$temp."[c]:-100:0";
2292                            }
2293                    }
2294                    for (my $i=0; $i < @{$Reactants};$i++) {
2295                            print $Reactants->[$i]->{"DATABASE"}->[0]." started\n";
2296                            $self->find_minimal_pathways($media,$Reactants->[$i]->{"DATABASE"}->[0],$additionalexchange);
2297                            print $Reactants->[$i]->{"DATABASE"}->[0]." done\n";
2298                    }
2299                    return;
2300            }
2301    
2302            #Adding additional drains
2303            if (($objective eq "cpd15665" || $objective eq "cpd15667" || $objective eq "cpd15668" || $objective eq "cpd15669") && $additionalexchange !~ m/cpd15666/) {
2304                    $additionalexchange .= ";cpd15666[c]:0:100";
2305            } elsif ($objective eq "cpd11493" && $additionalexchange !~ m/cpd12370/) {
2306                    $additionalexchange .= ";cpd12370[c]:0:100";
2307            } elsif ($objective eq "cpd00166" && $additionalexchange !~ m/cpd01997/) {
2308                    $additionalexchange .= ";cpd01997[c]:0:100;cpd03422[c]:0:100";
2309            }
2310    
2311            #Running MFAToolkit
2312            my $filename = $self->figmodel()->filename();
2313            my $command;
2314            if (defined($AllReversible) && $AllReversible == 1) {
2315                    $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());
2316            } else {
2317                    $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());
2318            }
2319            system($command);
2320    
2321            #Loading problem report
2322            my $results = $self->figmodel()->LoadProblemReport($filename);
2323            #Clearing output
2324            $self->figmodel()->clearing_output($filename,"MinimalPathways-".$media."-".$self->id()."-".$objective.".txt");
2325            if (!defined($results)) {
2326                    print STDERR $objective." pathway results not found!\n";
2327                    return;
2328            }
2329    
2330            #Parsing output
2331            my @Array;
2332            my $row = $results->get_row(1);
2333            if (defined($row->{"Notes"}->[0])) {
2334                    $_ = $row->{"Notes"}->[0];
2335                    @Array = /\d+:([^\|]+)\|/g;
2336            }
2337    
2338            #Writing output to file
2339            $self->figmodel()->database()->print_array_to_file($self->directory()."MinimalPathways-".$media."-".$objective."-".$self->id()."-".$AllReversible."-".$self->selected_version().".txt",[join("|",@Array)]);
2340    }
2341    
2342    =head3 find_minimal_pathways
2343    Definition:
2344            int::status = FIGMODEL->find_minimal_pathways(string::media,string::objective);
2345    Description:
2346            Runs microarray analysis attempting to turn off genes that are inactive in the microarray
2347    =cut
2348    sub find_minimal_pathways_two {
2349            my ($self,$media,$objective,$solutionnum,$AllReversible,$additionalexchange) = @_;
2350    
2351            #Setting default media
2352            if (!defined($media)) {
2353                    $media = "Complete";
2354            }
2355    
2356            #Setting default solution number
2357            if (!defined($solutionnum)) {
2358                    $solutionnum = "5";
2359          }          }
2360    
2361          #Setting additional exchange fluxes          #Setting additional exchange fluxes
2362          my $additionalexchange = $self->config("default exchange fluxes")->[0];          if (!defined($additionalexchange) || length($additionalexchange) == 0) {
2363          if ($objective eq "cpd15665" || $objective eq "cpd15667" || $objective eq "cpd15668" || $objective eq "cpd15669") {                  if ($self->id() eq "iAF1260") {
2364                            $additionalexchange = "cpd03422[c]:-100:100;cpd01997[c]:-100:100;cpd11416[c]:-100:0;cpd15378[c]:-100:0;cpd15486[c]:-100:0";
2365                    } else {
2366                            $additionalexchange = $self->figmodel()->config("default exchange fluxes")->[0];
2367                    }
2368            }
2369    
2370            #Translating objective
2371            my $objectivestring;
2372            if ($objective eq "ALL") {
2373                    #Getting the list of universal building blocks
2374                    my $buildingblocks = $self->config("universal building blocks");
2375                    my @objectives = keys(%{$buildingblocks});
2376                    #Getting the nonuniversal building blocks
2377                    my $otherbuildingblocks = $self->config("nonuniversal building blocks");
2378                    my @array = keys(%{$otherbuildingblocks});
2379                    if (defined($self->get_biomass()) && defined($self->figmodel()->get_reaction($self->get_biomass()->{"LOAD"}->[0]))) {
2380                            my $equation = $self->figmodel()->get_reaction($self->get_biomass()->{"LOAD"}->[0])->{"EQUATION"}->[0];
2381                            if (defined($equation)) {
2382                                    for (my $i=0; $i < @array; $i++) {
2383                                            if (CORE::index($equation,$array[$i]) > 0) {
2384                                                    push(@objectives,$array[$i]);
2385                                            }
2386                                    }
2387                            }
2388                    }
2389                    for (my $i=0; $i < @objectives; $i++) {
2390                            $self->find_minimal_pathways($media,$objectives[$i]);
2391                    }
2392                    return;
2393            } elsif ($objective eq "ENERGY") {
2394                    $objectivestring = "MAX;FLUX;rxn00062;c;1";
2395            } elsif ($objective =~ m/cpd\d\d\d\d\d/) {
2396                    if ($objective =~ m/\[(\w)\]/) {
2397                            $objectivestring = "MIN;DRAIN_FLUX;".$objective.";".$1.";1";
2398                            $additionalexchange .= ";".$objective."[".$1."]:-100:0";
2399                    } else {
2400                            $objectivestring = "MIN;DRAIN_FLUX;".$objective.";c;1";
2401                            $additionalexchange .= ";".$objective."[c]:-100:0";
2402                    }
2403            } elsif ($objective =~ m/(rxn\d\d\d\d\d)/) {
2404                    my ($Reactants,$Products) = $self->figmodel()->GetReactionSubstrateData($objective);
2405                    for (my $i=0; $i < @{$Products};$i++) {
2406                            my $temp = $Products->[$i]->{"DATABASE"}->[0];
2407                            if ($additionalexchange !~ m/$temp/) {
2408                                    #$additionalexchange .= ";".$temp."[c]:-100:0";
2409                            }
2410                    }
2411                    for (my $i=0; $i < @{$Reactants};$i++) {
2412                            print $Reactants->[$i]->{"DATABASE"}->[0]." started\n";
2413                            $self->find_minimal_pathways($media,$Reactants->[$i]->{"DATABASE"}->[0],$additionalexchange);
2414                            print $Reactants->[$i]->{"DATABASE"}->[0]." done\n";
2415                    }
2416                    return;
2417            }
2418    
2419            #Adding additional drains
2420            if (($objective eq "cpd15665" || $objective eq "cpd15667" || $objective eq "cpd15668" || $objective eq "cpd15669") && $additionalexchange !~ m/cpd15666/) {
2421                  $additionalexchange .= ";cpd15666[c]:0:100";                  $additionalexchange .= ";cpd15666[c]:0:100";
2422          } elsif ($objective eq "cpd11493") {          } elsif ($objective eq "cpd11493" && $additionalexchange !~ m/cpd12370/) {
2423                  $additionalexchange .= ";cpd12370[c]:0:100";                  $additionalexchange .= ";cpd12370[c]:0:100";
2424          } elsif ($objective eq "cpd00166") {          } elsif ($objective eq "cpd00166" && $additionalexchange !~ m/cpd01997/) {
2425                  $additionalexchange .= ";cpd01997[c]:0:100;cpd03422[c]:0:100";                  $additionalexchange .= ";cpd01997[c]:0:100;cpd03422[c]:0:100";
2426          }          }
2427    
2428          #Running MFAToolkit          #Running MFAToolkit
2429          my $filename = $self->figmodel()->filename();          my $filename = $self->figmodel()->filename();
2430          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;
2431            if (defined($AllReversible) && $AllReversible == 1) {
2432                    $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());
2433            } else {
2434                    $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());
2435            }
2436            print $command."\n";
2437          system($command);          system($command);
2438    
2439          #Loading problem report          #Loading problem report
# Line 1972  Line 2441 
2441          #Clearing output          #Clearing output
2442          $self->figmodel()->clearing_output($filename,"MinimalPathways-".$media."-".$self->id()."-".$objective.".txt");          $self->figmodel()->clearing_output($filename,"MinimalPathways-".$media."-".$self->id()."-".$objective.".txt");
2443          if (!defined($results)) {          if (!defined($results)) {
2444                    print STDERR $objective." pathway results not found!\n";
2445                  return;                  return;
2446          }          }
2447    
# Line 1983  Line 2453 
2453                  @Array = /\d+:([^\|]+)\|/g;                  @Array = /\d+:([^\|]+)\|/g;
2454          }          }
2455    
2456          # Storing data in a figmodel table          #Writing output to file
2457          my $TableObject;          $self->figmodel()->database()->print_array_to_file($self->directory()."MinimalPathways-".$media."-".$objective."-".$self->id()."-".$AllReversible."-".$self->selected_version().".txt",[join("|",@Array)]);
2458          if (-e $self->directory()."MinimalPathways-".$media."-".$self->id().$self->selected_version().".txt") {  }
2459                  $TableObject->load_table($self->directory()."MinimalPathways-".$media."-".$self->id().$self->selected_version().".txt",";","|",0,["OBJECTIVE"]);  
2460          } else {  sub combine_minimal_pathways {
2461                  $TableObject = FIGMODELTable->new(["OBJECTIVE","REACTIONS"],$self->directory()."MinimalPathways-".$media."-".$self->id().$self->selected_version().".txt",["OBJECTIVE"],";","|",undef);          my ($self) = @_;
2462          }  
2463          my $tablerow = $TableObject->get_row_by_key($objective,"OBJECTIVE",1);          my $tbl;
2464          push(@{$tablerow->{"REACTIONS"}},@Array);          if (-e $self->directory()."MinimalPathwayTable-".$self->id().$self->selected_version().".tbl") {
2465          $TableObject->save();                  $tbl = FIGMODELTable::load_table($self->directory()."MinimalPathwayTable-".$self->id().$self->selected_version().".tbl",";","|",0,["Objective","Media","Reversible"]);
2466            } else {
2467                    $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"],";","|");
2468            }
2469            my @files = glob($self->directory()."MinimalPathways-*");
2470            for (my $i=0; $i < @files;$i++) {
2471                    if ($files[$i] =~ m/MinimalPathways\-(\S+)\-(cpd\d\d\d\d\d)\-(\w+)\-(\d)\-/ || $files[$i] =~ m/MinimalPathways\-(\S+)\-(ENERGY)\-(\w+)\-(\d)\-/) {
2472                            my $reactions = $self->figmodel()->database()->load_single_column_file($files[$i],"");
2473                            if (defined($reactions) && @{$reactions} > 0 && length($reactions->[0]) > 0) {
2474                                    my $newrow = {"Objective"=>[$2],"Media"=>[$1],"Reversible"=>[$4]};
2475                                    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");
2476                                    if (!defined($row)) {
2477                                            $row = $tbl->add_row($newrow);
2478                                    }
2479                                    $row->{Reactions} = $self->figmodel()->database()->load_single_column_file($files[$i],"");
2480                                    delete($row->{"Shortest path"});
2481                                    delete($row->{"Number of essentials"});
2482                                    delete($row->{"Essentials"});
2483                                    delete($row->{"Length"});
2484                                    for (my $j=0; $j < @{$row->{Reactions}}; $j++) {
2485                                            my @array = split(/,/,$row->{Reactions}->[$j]);
2486                                            $row->{"Length"}->[$j] = @array;
2487                                            if (!defined($row->{"Shortest path"}->[0]) || $row->{"Length"}->[$j] < $row->{"Shortest path"}->[0]) {
2488                                                    $row->{"Shortest path"}->[0] = $row->{"Length"}->[$j];
2489                                            }
2490                                            $row->{"Number of essentials"}->[0] = 0;
2491                                            for (my $k=0; $k < @array;$k++) {
2492                                                    if ($array[$k] =~ m/(rxn\d\d\d\d\d)/) {
2493                                                            my $class = $self->get_reaction_class($1,1);
2494                                                            my $temp = $row->{Media}->[0].":Essential";
2495                                                            if ($class =~ m/$temp/) {
2496                                                                    $row->{"Number of essentials"}->[$j]++;
2497                                                                    if (!defined($row->{"Essentials"}->[$j]) && length($row->{"Essentials"}->[$j]) > 0) {
2498                                                                            $row->{"Essentials"}->[$j] = $array[$k];
2499                                                                    } else {
2500                                                                            $row->{"Essentials"}->[$j] .= ",".$array[$k];
2501                                                                    }
2502                                                            }
2503                                                    }
2504                                            }
2505                                    }
2506                            }
2507                    }
2508            }
2509            $tbl->save();
2510  }  }
2511    
2512  =head3 calculate_growth  =head3 calculate_growth
# Line 2002  Line 2516 
2516          Calculating growth in the input media          Calculating growth in the input media
2517  =cut  =cut
2518  sub calculate_growth {  sub calculate_growth {
2519          my ($self,$Media) = @_;          my ($self,$Media,$outputDirectory,$InParameters,$saveLPFile) = @_;
2520            #Setting the Media
2521            if (!defined($Media) || length($Media) == 0) {
2522                    $Media = $self->autocompleteMedia();
2523            }
2524            #Setting parameters for the run
2525            my $DefaultParameters = $self->figmodel()->defaultParameters();
2526            if (defined($InParameters)) {
2527                    my @parameters = keys(%{$InParameters});
2528                    for (my $i=0; $i < @parameters; $i++) {
2529                            $DefaultParameters->{$parameters[$i]} = $InParameters->{$parameters[$i]};
2530                    }
2531            }
2532            $DefaultParameters->{"optimize metabolite production if objective is zero"} = 1;
2533            #Setting filenames
2534          my $UniqueFilename = $self->figmodel()->filename();          my $UniqueFilename = $self->figmodel()->filename();
2535          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()));          if (!defined($outputDirectory)) {
2536                    $outputDirectory = $self->config("database message file directory")->[0];
2537            }
2538            my $fluxFilename = $outputDirectory."Fluxes-".$self->id()."-".$Media.".txt";
2539            my $cpdFluxFilename = $outputDirectory."CompoundFluxes-".$self->id()."-".$Media.".txt";
2540            #Running FBA
2541            #print $self->figmodel()->GenerateMFAToolkitCommandLineCall($UniqueFilename,$self->id(),$Media,["ProductionMFA"],$DefaultParameters,$self->id()."-".$Media."-GrowthTest.txt",undef,$self->selected_version())."\n";
2542            system($self->figmodel()->GenerateMFAToolkitCommandLineCall($UniqueFilename,$self->id(),$Media,["ProductionMFA"],$DefaultParameters,$self->id()."-".$Media."-GrowthTest.txt",undef,$self->selected_version()));
2543            #Saving LP file if requested
2544            if (defined($saveLPFile) && $saveLPFile == 1 && -e $self->figmodel()->{"MFAToolkit output directory"}->[0].$UniqueFilename."/CurrentProblem.lp") {
2545                    system("cp ".$self->figmodel()->config("MFAToolkit output directory")->[0].$UniqueFilename."/CurrentProblem.lp ".$self->directory().$self->id().".lp");
2546            }
2547          my $ProblemReport = $self->figmodel()->LoadProblemReport($UniqueFilename);          my $ProblemReport = $self->figmodel()->LoadProblemReport($UniqueFilename);
2548          my $Result;          my $Result;
2549          if (defined($ProblemReport)) {          if (defined($ProblemReport)) {
2550                  my $Row = $ProblemReport->get_row(0);                  my $Row = $ProblemReport->get_row(0);
2551                  if (defined($Row) && defined($Row->{"Objective"}->[0])) {                  if (defined($Row) && defined($Row->{"Objective"}->[0])) {
2552                          if ($Row->{"Objective"}->[0] < 0.00000001) {                          if ($Row->{"Objective"}->[0] < 0.00000001 || $Row->{"Objective"}->[0] == 1e7) {
2553                                  $Result = "NOGROWTH:".$Row->{"Individual metabolites with zero production"}->[0];                                  $Result = "NOGROWTH";
2554                                    if (defined($Row->{"Individual metabolites with zero production"}->[0]) && $Row->{"Individual metabolites with zero production"}->[0] =~ m/cpd\d\d\d\d\d/) {
2555                                            $Result .= ":".$Row->{"Individual metabolites with zero production"}->[0];
2556                                    }
2557                          } else {                          } else {
2558                                    if (-e $self->figmodel()->config("MFAToolkit output directory")->[0].$UniqueFilename."/MFAOutput/SolutionReactionData0.txt") {
2559                                            system("cp ".$self->figmodel()->config("MFAToolkit output directory")->[0].$UniqueFilename."/MFAOutput/SolutionReactionData0.txt ".$fluxFilename);
2560                                            system("cp ".$self->figmodel()->config("MFAToolkit output directory")->[0].$UniqueFilename."/MFAOutput/SolutionCompoundData0.txt ".$cpdFluxFilename);
2561                                    }
2562                                  $Result = $Row->{"Objective"}->[0];                                  $Result = $Row->{"Objective"}->[0];
2563                          }                          }
2564                  }                  }
2565          }          }
2566            #Deleting files if necessary
2567            if ($self->figmodel()->config("preserve all log files")->[0] ne "yes") {
2568                    $self->figmodel()->cleardirectory($UniqueFilename);
2569                    unlink($self->figmodel()->config("database message file directory")->[0].$self->id()."-".$Media."-GrowthTest.txt");
2570            }
2571            #Returning result
2572          return $Result;          return $Result;
2573  }  }
2574    
# Line 2036  Line 2588 
2588          7.) Dead: these reactions are disconnected from the network.          7.) Dead: these reactions are disconnected from the network.
2589  =cut  =cut
2590  sub classify_model_reactions {  sub classify_model_reactions {
2591          my ($self,$Media) = @_;          my ($self,$Media,$SaveChanges) = @_;
2592    
2593          #Getting unique file for printing model output          #Getting unique file for printing model output
2594          my $UniqueFilename = $self->figmodel()->filename();          my $UniqueFilename = $self->figmodel()->filename();
# Line 2123  Line 2675 
2675                                  $CpdRow->{MEDIA}->[$index] = $Media;                                  $CpdRow->{MEDIA}->[$index] = $Media;
2676                          }                          }
2677                  }                  }
2678                    if (!defined($SaveChanges) || $SaveChanges == 1) {
2679                  $cpdclasstable->save();                  $cpdclasstable->save();
2680          }          }
2681            }
2682          if (defined($ReactionTB)) {          if (defined($ReactionTB)) {
2683                  for (my $i=0; $i < $ReactionTB->size(); $i++) {                  for (my $i=0; $i < $ReactionTB->size(); $i++) {
2684                          my $Row = $ReactionTB->get_row($i);                          my $Row = $ReactionTB->get_row($i);
# Line 2179  Line 2733 
2733                                  $RxnRow->{MEDIA}->[$index] = $Media;                                  $RxnRow->{MEDIA}->[$index] = $Media;
2734                          }                          }
2735                  }                  }
2736                    if (!defined($SaveChanges) || $SaveChanges == 1) {
2737                  $rxnclasstable->save();                  $rxnclasstable->save();
2738          }          }
2739            }
2740          return ($rxnclasstable,$cpdclasstable);          return ($rxnclasstable,$cpdclasstable);
2741  }  }
2742    
# Line 2212  Line 2768 
2768    
2769          #Running simulations          #Running simulations
2770          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";  
2771          #Parsing the results          #Parsing the results
2772          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);
2773          if (!defined($Results)) {          if (!defined($Results)) {
# Line 2619  Line 3174 
3174                                          if (length($GapFillingRunSpecs) > 0) {                                          if (length($GapFillingRunSpecs) > 0) {
3175                                                  $GapFillingRunSpecs .= ";";                                                  $GapFillingRunSpecs .= ";";
3176                                          }                                          }
3177                                          $GapFillingRunSpecs .= $HeadingDataArray[2].":".$HeadingDataArray[1].".txt:".$HeadingDataArray[3];                                          $GapFillingRunSpecs .= $HeadingDataArray[2].":".$HeadingDataArray[1].":".$HeadingDataArray[3];
3178                                  } else {                                  } else {
3179                                          $SolutionExistedCount++;                                          $SolutionExistedCount++;
3180                                  }                                  }
# Line 2644  Line 3199 
3199          my $SolutionsFound = 0;          my $SolutionsFound = 0;
3200          my $GapFillingArray;          my $GapFillingArray;
3201          push(@{$GapFillingArray},split(/;/,$GapFillingRunSpecs));          push(@{$GapFillingArray},split(/;/,$GapFillingRunSpecs));
3202          $self->datagapfill($GapFillingArray);          my $GapFillingResults = $self->datagapfill($GapFillingArray,"GFS");
3203            if (defined($GapFillingResults)) {
3204                    $SolutionsFound = 1;
3205            }
3206    
3207          if (defined($RescuedPreviousResults) && @{$RescuedPreviousResults} > 0) {          if (defined($RescuedPreviousResults) && @{$RescuedPreviousResults} > 0) {
3208                  #Printing previous solutions to GFS file                  #Printing previous solutions to GFS file
# Line 2667  Line 3225 
3225          return $self->success();          return $self->success();
3226  }  }
3227    
3228  =head3 BuildSpecificBiomassReaction  =head3 SolutionReconciliation
3229  Definition:  Definition:
3230          FIGMODELmodel->BuildSpecificBiomassReaction();          FIGMODELmodel->SolutionReconciliation();
3231  Description:  Description:
3232            This is a wrapper for running the solution reconciliation algorithm on any model in the database.
3233            The algorithm performs a reconciliation of any gap filling solutions to identify the combination of solutions that results in the optimal model.
3234            This function prints out one output file in the Model directory: ReconciliationOutput.txt: this is a summary of the results of the reconciliation analysis
3235  =cut  =cut
 sub BuildSpecificBiomassReaction {  
         my ($self) = @_;  
3236    
3237          my $biomassrxn;  sub SolutionReconciliation {
3238          my $OrganismID = $self->genome();          my ($self,$GapFill,$Stage) = @_;
         #Checking for a biomass override  
         if (defined($self->config("biomass reaction override")->{$OrganismID})) {  
                 $biomassrxn = $self->config("biomass reaction override")->{$OrganismID};  
                 print "Overriding biomass template and selecting ".$biomassrxn." for ".$OrganismID.".\n";  
         } else {#Creating biomass reaction from the template  
                 #Getting the genome stats  
                 my $genomestats = $self->figmodel()->get_genome_stats($self->genome());  
                 my $Class = $genomestats->{CLASS}->[0];  
                 my $Name = $genomestats->{NAME}->[0];  
3239    
3240                  #Checking for phoenix variants          #Setting the output filenames
3241                  my $PhoenixVariantTable = $self->figmodel()->database()->GetDBTable("Phoenix variants table");          my $OutputFilename;
3242                  my $Phoenix = 0;          my $OutputFilenameTwo;
3243                  my @Rows = $PhoenixVariantTable->get_rows_by_key($OrganismID,"GENOME");          if ($GapFill == 1) {
3244                  my $VariantHash;                  $OutputFilename = $self->directory().$self->id().$self->selected_version()."-GFReconciliation.txt";
3245                  for (my $i=0; $i < @Rows; $i++) {                  $OutputFilenameTwo = $self->directory().$self->id().$self->selected_version()."-GFSRS.txt";
3246                          $Phoenix = 1;          } else {
3247                          if (defined($Rows[$i]->{"SUBSYSTEM"}) && defined($Rows[$i]->{"VARIANT"})) {                  $OutputFilename = $self->directory().$self->id().$self->selected_version()."-GGReconciliation.txt";
3248                                  $VariantHash->{$Rows[$i]->{"SUBSYSTEM"}->[0]} = $Rows[$i]->{"VARIANT"}->[0];                  $OutputFilenameTwo = $self->directory().$self->id().$self->selected_version()."-GGSRS.txt";
3249                          }          }
3250    
3251            #In stage one, we run the reconciliation and create a test file to check combined solution performance
3252            if (!defined($Stage) || $Stage == 1) {
3253                    my $GrowMatchTable = $self->figmodel()->database()->LockDBTable("GROWMATCH TABLE");
3254                    my $Row = $GrowMatchTable->get_row_by_key($self->genome(),"ORGANISM",1);
3255                    $Row->{"GF RECONCILATION TIMING"}->[0] = time()."-";
3256                    $GrowMatchTable->save();
3257                    $self->figmodel()->database()->UnlockDBTable("GROWMATCH TABLE");
3258    
3259                    #Getting a unique filename
3260                    my $UniqueFilename = $self->figmodel()->filename();
3261    
3262                    #Copying over the necessary files
3263                    if ($GapFill == 1) {
3264                            if (!-e $self->directory().$self->id().$self->selected_version()."-GFEM.txt") {
3265                                    print STDERR "FIGMODEL:SolutionReconciliation:".$self->directory().$self->id().$self->selected_version()."-GFEM.txt file not found. Could not reconcile!";
3266                                    return 0;
3267                            }
3268                            if (!-e $self->directory().$self->id().$self->selected_version()."-OPEM.txt") {
3269                                    print STDERR "FIGMODEL:SolutionReconciliation:".$self->directory().$self->id().$self->selected_version()."-OPEM.txt file not found. Could not reconcile!";
3270                                    return 0;
3271                            }
3272                            system("cp ".$self->directory().$self->id().$self->selected_version()."-GFEM.txt ".$self->figmodel()->config("MFAToolkit input files")->[0].$UniqueFilename."-GFEM.txt");
3273                            system("cp ".$self->directory().$self->id().$self->selected_version()."-OPEM.txt ".$self->figmodel()->config("MFAToolkit input files")->[0].$UniqueFilename."-OPEM.txt");
3274                            #Backing up and deleting the existing reconciliation file
3275                            if (-e $OutputFilename) {
3276                                    system("cp ".$OutputFilename." ".$self->directory().$self->id().$self->selected_version()."-OldGFReconciliation.txt");
3277                                    unlink($OutputFilename);
3278                            }
3279                    } else {
3280                            if (!-e $self->directory().$self->id().$self->selected_version()."-GGEM.txt") {
3281                                    print STDERR "FIGMODEL:SolutionReconciliation:".$self->directory().$self->id().$self->selected_version()."-GGEM.txt file not found. Could not reconcile!";
3282                                    return 0;
3283                            }
3284                            if (!-e $self->directory().$self->id().$self->selected_version()."-GGOPEM.txt") {
3285                                    print STDERR "FIGMODEL:SolutionReconciliation:".$self->directory().$self->id().$self->selected_version()."-GGOPEM.txt file not found. Could not reconcile!";
3286                                    return 0;
3287                            }
3288                            system("cp ".$self->directory().$self->id().$self->selected_version()."-GGEM.txt ".$self->figmodel()->config("MFAToolkit input files")->[0].$UniqueFilename."-GGEM.txt");
3289                            system("cp ".$self->directory().$self->id().$self->selected_version()."-GGOPEM.txt ".$self->figmodel()->config("MFAToolkit input files")->[0].$UniqueFilename."-OPEM.txt");
3290                            #Backing up and deleting the existing reconciliation file
3291                            if (-e $OutputFilename) {
3292                                    system("cp ".$OutputFilename." ".$self->directory().$self->id().$self->selected_version()."-OldGGReconciliation.txt");
3293                                    unlink($OutputFilename);
3294                            }
3295                    }
3296    
3297                    #Running the reconciliation
3298                    system($self->figmodel()->GenerateMFAToolkitCommandLineCall($UniqueFilename,$self->id(),"NONE",["SolutionReconciliation"],{"Solution data for model optimization" => $UniqueFilename},"Reconciliation".$UniqueFilename.".log",undef,$self->selected_version()));
3299                    $GrowMatchTable = $self->figmodel()->database()->LockDBTable("GROWMATCH TABLE");
3300                    $Row = $GrowMatchTable->get_row_by_key($self->genome(),"ORGANISM",1);
3301                    $Row->{"GF RECONCILATION TIMING"}->[0] .= time();
3302                    $GrowMatchTable->save();
3303                    $self->figmodel()->database()->UnlockDBTable("GROWMATCH TABLE");
3304    
3305                    #Loading the problem report from the reconciliation run
3306                    my $ReconciliatonOutput = $self->figmodel()->LoadProblemReport($UniqueFilename);
3307                    print $UniqueFilename."\n";
3308                    #Clearing output files
3309                    $self->figmodel()->clearing_output($UniqueFilename,"Reconciliation".$UniqueFilename.".log");
3310                    $ReconciliatonOutput->save("/home/chenry/Test.txt");
3311    
3312                    #Checking the a problem report was found and was loaded
3313                    if (!defined($ReconciliatonOutput) || $ReconciliatonOutput->size() < 1 || !defined($ReconciliatonOutput->get_row(0)->{"Notes"}->[0])) {
3314                            print STDERR "FIGMODEL:SolutionReconciliation: MFAToolkit output from SolutionReconciliation of ".$self->id()." not found!\n\n";
3315                            return 0;
3316                    }
3317    
3318                    #Processing the solutions
3319                    my $SolutionCount = 0;
3320                    my $ReactionSetHash;
3321                    my $SingleReactionHash;
3322                    my $ReactionDataHash;
3323                    for (my $n=0; $n < $ReconciliatonOutput->size(); $n++) {
3324                            if (defined($ReconciliatonOutput->get_row($n)->{"Notes"}->[0]) && $ReconciliatonOutput->get_row($n)->{"Notes"}->[0] =~ m/^Recursive\sMILP\s([^;]+)/) {
3325                                    #Breaking up the solution into reaction sets
3326                                    my @ReactionSets = split(/\|/,$1);
3327                                    #Creating reaction lists for each set
3328                                    my $SolutionHash;
3329                                    for (my $i=0; $i < @ReactionSets; $i++) {
3330                                            if (length($ReactionSets[$i]) > 0) {
3331                                                    my @Alternatives = split(/:/,$ReactionSets[$i]);
3332                                                    for (my $j=1; $j < @Alternatives; $j++) {
3333                                                            if (length($Alternatives[$j]) > 0) {
3334                                                                    push(@{$SolutionHash->{$Alternatives[$j]}},$Alternatives[0]);
3335                                                            }
3336                                                    }
3337                                                    if (@Alternatives == 1) {
3338                                                            $SingleReactionHash->{$Alternatives[0]}->{$SolutionCount} = 1;
3339                                                            if (!defined($SingleReactionHash->{$Alternatives[0]}->{"COUNT"})) {
3340                                                                    $SingleReactionHash->{$Alternatives[0]}->{"COUNT"} = 0;
3341                                                            }
3342                                                            $SingleReactionHash->{$Alternatives[0]}->{"COUNT"}++;
3343                                                    }
3344                                            }
3345                                    }
3346                                    #Identifying reactions sets and storing the sets in the reactions set hash
3347                                    foreach my $Solution (keys(%{$SolutionHash})) {
3348                                            my $SetKey = join(",",sort(@{$SolutionHash->{$Solution}}));
3349                                            if (!defined($ReactionSetHash->{$SetKey}->{$SetKey}->{$SolutionCount})) {
3350                                                    $ReactionSetHash->{$SetKey}->{$SetKey}->{$SolutionCount} = 1;
3351                                                    if (!defined($ReactionSetHash->{$SetKey}->{$SetKey}->{"COUNT"})) {
3352                                                            $ReactionSetHash->{$SetKey}->{$SetKey}->{"COUNT"} = 0;
3353                                                    }
3354                                                    $ReactionSetHash->{$SetKey}->{$SetKey}->{"COUNT"}++;
3355                                            }
3356                                            $ReactionSetHash->{$SetKey}->{$Solution}->{$SolutionCount} = 1;
3357                                            if (!defined($ReactionSetHash->{$SetKey}->{$Solution}->{"COUNT"})) {
3358                                                    $ReactionSetHash->{$SetKey}->{$Solution}->{"COUNT"} = 0;
3359                                            }
3360                                            $ReactionSetHash->{$SetKey}->{$Solution}->{"COUNT"}++;
3361                                    }
3362                                    $SolutionCount++;
3363                            }
3364                    }
3365    
3366                    #Handling the scenario where no solutions were found
3367                    if ($SolutionCount == 0) {
3368                            print STDERR "FIGMODEL:SolutionReconciliation: Reconciliation unsuccessful. No solution found.\n\n";
3369                            return 0;
3370                    }
3371    
3372                    #Printing results without solution performance figures. Also printing solution test file
3373                    open (RECONCILIATION, ">$OutputFilename");
3374                    #Printing the file heading
3375                    print RECONCILIATION "DATABASE;DEFINITION;REVERSIBLITY;DELTAG;DIRECTION;NUMBER OF SOLUTIONS";
3376                    for (my $i=0; $i < $SolutionCount; $i++) {
3377                            print RECONCILIATION ";Solution ".$i;
3378                    }
3379                    print RECONCILIATION "\n";
3380                    #Printing the singlet reactions first
3381                    my $Solutions;
3382                    print RECONCILIATION "SINGLET REACTIONS\n";
3383                    my @SingletReactions = keys(%{$SingleReactionHash});
3384                    for (my $j=0; $j < $SolutionCount; $j++) {
3385                            $Solutions->[$j]->{"BASE"} = $j;
3386                    }
3387                    for (my $i=0; $i < @SingletReactions; $i++) {
3388                            my $ReactionData;
3389                            if (defined($ReactionDataHash->{$SingletReactions[$i]})) {
3390                                    $ReactionData = $ReactionDataHash->{$SingletReactions[$i]};
3391                            } else {
3392                                    my $Direction = substr($SingletReactions[$i],0,1);
3393                                    if ($Direction eq "+") {
3394                                            $Direction = "=>";
3395                                    } else {
3396                                            $Direction = "<=";
3397                                    }
3398                                    my $Reaction = substr($SingletReactions[$i],1);
3399                                    $ReactionData = FIGMODELObject->load($self->figmodel()->config("reaction directory")->[0].$Reaction,"\t");
3400                                    $ReactionData->{"DIRECTIONS"}->[0] = $Direction;
3401                                    $ReactionData->{"REACTIONS"}->[0] = $Reaction;
3402                                    if (!defined($ReactionData->{"DEFINITION"}->[0])) {
3403                                            $ReactionData->{"DEFINITION"}->[0] = "UNKNOWN";
3404                                    }
3405                                    if (!defined($ReactionData->{"THERMODYNAMIC REVERSIBILITY"}->[0])) {
3406                                            $ReactionData->{"THERMODYNAMIC REVERSIBILITY"}->[0] = "UNKNOWN";
3407                                    }
3408                                    if (!defined($ReactionData->{"DELTAG"}->[0])) {
3409                                            $ReactionData->{"DELTAG"}->[0] = "UNKNOWN";
3410                                    }
3411                                    $ReactionDataHash->{$SingletReactions[$i]} = $ReactionData;
3412                            }
3413                            print RECONCILIATION $ReactionData->{"REACTIONS"}->[0].";".$ReactionData->{"DEFINITION"}->[0].";".$ReactionData->{"THERMODYNAMIC REVERSIBILITY"}->[0].";".$ReactionData->{"DELTAG"}->[0].";".$ReactionData->{"DIRECTIONS"}->[0].";".$SingleReactionHash->{$SingletReactions[$i]}->{"COUNT"};
3414                            for (my $j=0; $j < $SolutionCount; $j++) {
3415                                    print RECONCILIATION ";";
3416                                    if (defined($SingleReactionHash->{$SingletReactions[$i]}->{$j})) {
3417                                            $Solutions->[$j]->{$SingletReactions[$i]} = 1;
3418                                            $Solutions->[$j]->{"BASE"} = $j;
3419                                            print RECONCILIATION "|".$j."|";
3420                                    }
3421                            }
3422                            print RECONCILIATION "\n";
3423                    }
3424                    #Printing the reaction sets with alternatives
3425                    print RECONCILIATION "Reaction sets with alternatives\n";
3426                    my @ReactionSets = keys(%{$ReactionSetHash});
3427                    foreach my $ReactionSet (@ReactionSets) {
3428                            my $NewSolutions;
3429                            my $BaseReactions;
3430                            my $AltList = [$ReactionSet];
3431                            push(@{$AltList},keys(%{$ReactionSetHash->{$ReactionSet}}));
3432                            for (my $j=0; $j < @{$AltList}; $j++) {
3433                                    my $CurrentNewSolutions;
3434                                    my $Index;
3435                                    if ($j == 0) {
3436                                            print RECONCILIATION "NEW SET\n";
3437                                    } elsif ($AltList->[$j] ne $ReactionSet) {
3438                                            print RECONCILIATION "ALTERNATIVE SET\n";
3439                                            #For each base solution in which this set is represented, we copy the base solution to the new solution
3440                                            my $NewSolutionCount = 0;
3441                                            for (my $k=0; $k < $SolutionCount; $k++) {
3442                                                    if (defined($ReactionSetHash->{$ReactionSet}->{$AltList->[$j]}->{$k})) {
3443                                                            if (defined($Solutions)) {
3444                                                                    $Index->{$k} = @{$Solutions} + $NewSolutionCount;
3445                                                            } else {
3446                                                                    $Index->{$k} = $NewSolutionCount;
3447                                                            }
3448                                                            if (defined($NewSolutions) && @{$NewSolutions} > 0) {
3449                                                                    $Index->{$k} += @{$NewSolutions};
3450                                                            }
3451                                                            $CurrentNewSolutions->[$NewSolutionCount] = {};
3452                                                            foreach my $Reaction (keys(%{$Solutions->[$k]})) {
3453                                                                    $CurrentNewSolutions->[$NewSolutionCount]->{$Reaction} = $Solutions->[$k]->{$Reaction};
3454                                                            }
3455                                                            $NewSolutionCount++;
3456                                                    }
3457                                            }
3458                                    }
3459                                    if ($j == 0 || $AltList->[$j] ne $ReactionSet) {
3460                                            my @SingletReactions = split(/,/,$AltList->[$j]);
3461                                            for (my $i=0; $i < @SingletReactions; $i++) {
3462                                                    #Adding base reactions to base solutions and set reactions the new solutions
3463                                                    if ($j == 0) {
3464                                                            push(@{$BaseReactions},$SingletReactions[$i]);
3465                                                    } else {
3466                                                            for (my $k=0; $k < @{$CurrentNewSolutions}; $k++) {
3467                                                                    $CurrentNewSolutions->[$k]->{$SingletReactions[$i]} = 1;
3468                                                            }
3469                                                    }
3470                                                    #Getting reaction data and printing reaction in output file
3471                                                    my $ReactionData;
3472                                                    if (defined($ReactionDataHash->{$SingletReactions[$i]})) {
3473                                                            $ReactionData = $ReactionDataHash->{$SingletReactions[$i]};
3474                                                    } else {
3475                                                            my $Direction = substr($SingletReactions[$i],0,1);
3476                                                            if ($Direction eq "+") {
3477                                                                    $Direction = "=>";
3478                                                            } else {
3479                                                                    $Direction = "<=";
3480                                                            }
3481                                                            my $Reaction = substr($SingletReactions[$i],1);
3482                                                            $ReactionData = FIGMODELObject->load($self->figmodel()->config("reaction directory")->[0].$Reaction,"\t");
3483                                                            $ReactionData->{"DIRECTIONS"}->[0] = $Direction;
3484                                                            $ReactionData->{"REACTIONS"}->[0] = $Reaction;
3485                                                            if (!defined($ReactionData->{"DEFINITION"}->[0])) {
3486                                                                    $ReactionData->{"DEFINITION"}->[0] = "UNKNOWN";
3487                                                            }
3488                                                            if (!defined($ReactionData->{"THERMODYNAMIC REVERSIBILITY"}->[0])) {
3489                                                                    $ReactionData->{"THERMODYNAMIC REVERSIBILITY"}->[0] = "UNKNOWN";
3490                                                            }
3491                                                            if (!defined($ReactionData->{"DELTAG"}->[0])) {
3492                                                                    $ReactionData->{"DELTAG"}->[0] = "UNKNOWN";
3493                                                            }
3494                                                            $ReactionDataHash->{$SingletReactions[$i]} = $ReactionData;
3495                                                    }
3496                                                    print RECONCILIATION $ReactionData->{"REACTIONS"}->[0].";".$ReactionData->{"DEFINITION"}->[0].";".$ReactionData->{"THERMODYNAMIC REVERSIBILITY"}->[0].";".$ReactionData->{"DELTAG"}->[0].";".$ReactionData->{"DIRECTIONS"}->[0].";".$ReactionSetHash->{$ReactionSet}->{$AltList->[$j]}->{"COUNT"};
3497                                                    for (my $k=0; $k < $SolutionCount; $k++) {
3498                                                            print RECONCILIATION ";";
3499                                                            if (defined($ReactionSetHash->{$ReactionSet}->{$AltList->[$j]}->{$k})) {
3500                                                                    if ($j == 0) {
3501                                                                            print RECONCILIATION "|".$k."|";
3502                                                                    } else {
3503                                                                            print RECONCILIATION "|".$Index->{$k}."|";
3504                                                                    }
3505                                                            }
3506                                                    }
3507                                                    print RECONCILIATION "\n";
3508                                            }
3509                                            #Adding the current new solutions to the new solutions array
3510                                            if (defined($CurrentNewSolutions) && @{$CurrentNewSolutions} > 0) {
3511                                                    push(@{$NewSolutions},@{$CurrentNewSolutions});
3512                                            }
3513                                    }
3514                            }
3515                            #Adding the base reactions to all existing solutions
3516                            for (my $j=0; $j < @{$Solutions}; $j++) {
3517                                    if (defined($ReactionSetHash->{$ReactionSet}->{$ReactionSet}->{$Solutions->[$j]->{"BASE"}})) {
3518                                            foreach my $SingleReaction (@{$BaseReactions}) {
3519                                                    $Solutions->[$j]->{$SingleReaction} = 1;
3520                                            }
3521                                    }
3522                            }
3523                            #Adding the new solutions to the set of existing solutions
3524                            push(@{$Solutions},@{$NewSolutions});
3525                    }
3526                    close(RECONCILIATION);
3527                    #Now printing a file that defines all of the solutions in a format the testsolutions function understands
3528                    open (RECONCILIATION, ">$OutputFilenameTwo");
3529                    print RECONCILIATION "Experiment;Solution index;Solution cost;Solution reactions\n";
3530                    for (my $i=0; $i < @{$Solutions}; $i++) {
3531                            delete($Solutions->[$i]->{"BASE"});
3532                            print RECONCILIATION "SR".$i.";".$i.";10;".join(",",keys(%{$Solutions->[$i]}))."\n";
3533                    }
3534                    close(RECONCILIATION);
3535    
3536                    $GrowMatchTable = $self->figmodel()->database()->LockDBTable("GROWMATCH TABLE");
3537                    $Row = $GrowMatchTable->get_row_by_key($self->genome(),"ORGANISM",1);
3538                    $Row->{"GF RECON TESTING TIMING"}->[0] = time()."-";
3539                    $Row->{"GF RECON SOLUTIONS"}->[0] = @{$Solutions};
3540                    $GrowMatchTable->save();
3541                    $self->figmodel()->database()->UnlockDBTable("GROWMATCH TABLE");
3542    
3543                    #Scheduling the solution testing
3544                    if ($GapFill == 1) {
3545                            system($self->figmodel()->config("scheduler executable")->[0]." \"add:testsolutions?".$self->id().$self->selected_version()."?-1?GFSR:BACK:fast:QSUB\"");
3546                    } else {
3547                            system($self->figmodel()->config("scheduler executable")->[0]." \"add:testsolutions?".$self->id().$self->selected_version()."?-1?GGSR:BACK:fast:QSUB\"");
3548                    }
3549            } else {
3550                    #Reading in the solution testing results
3551                    my $Data;
3552                    if ($GapFill == 1) {
3553                            $Data = $self->figmodel()->database()->load_single_column_file($self->directory().$self->id().$self->selected_version()."-GFSREM.txt","");
3554                    } else {
3555                            $Data = $self->figmodel()->database()->load_single_column_file($self->directory().$self->id().$self->selected_version()."-GGSREM.txt","");
3556                    }
3557    
3558                    #Reading in the preliminate reconciliation report
3559                    my $OutputData = $self->figmodel()->database()->load_single_column_file($OutputFilename,"");
3560                    #Replacing the file tags with actual performance data
3561                    my $Count = 0;
3562                    for (my $i=0; $i < @{$Data}; $i++) {
3563                            if ($Data->[$i] =~ m/^SR(\d+);.+;(\d+\/\d+);/) {
3564                                    my $Index = $1;
3565                                    my $Performance = $Index."/".$2;
3566                                    for (my $j=0; $j < @{$OutputData}; $j++) {
3567                                            $OutputData->[$j] =~ s/\|$Index\|/$Performance/g;
3568                                    }
3569                            }
3570                    }
3571                    $self->figmodel()->database()->print_array_to_file($OutputFilename,$OutputData);
3572    
3573                    my $GrowMatchTable = $self->figmodel()->database()->LockDBTable("GROWMATCH TABLE");
3574                    my $Row = $GrowMatchTable->get_row_by_key($self->genome(),"ORGANISM",1);
3575                    $Row->{"GF RECON TESTING TIMING"}->[0] .= time();
3576                    $GrowMatchTable->save();
3577                    $self->figmodel()->database()->UnlockDBTable("GROWMATCH TABLE");
3578            }
3579    
3580            return 1;
3581    }
3582    
3583    =head3 BuildSpecificBiomassReaction
3584    Definition:
3585            FIGMODELmodel->BuildSpecificBiomassReaction();
3586    Description:
3587    =cut
3588    sub BuildSpecificBiomassReaction {
3589            my ($self) = @_;
3590    
3591            my $biomassrxn;
3592            my $OrganismID = $self->genome();
3593            #Checking for a biomass override
3594            if (defined($self->config("biomass reaction override")->{$OrganismID})) {
3595                    my $biomassID = $self->config("biomass reaction override")->{$OrganismID};
3596                    my $tbl = $self->database()->get_table("BIOMASS",1);
3597                    $biomassrxn = $tbl->get_row_by_key($biomassID,"DATABASE");
3598                    print "Overriding biomass template and selecting ".$biomassID." for ".$OrganismID.".\n";
3599            } else {#Creating biomass reaction from the template
3600                    #Getting the genome stats
3601                    my $genomestats = $self->figmodel()->get_genome_stats($self->genome());
3602                    my $Class = $genomestats->{CLASS}->[0];
3603                    my $Name = $genomestats->{NAME}->[0];
3604    
3605                    #Checking for phoenix variants
3606                    my $PhoenixVariantTable = $self->figmodel()->database()->GetDBTable("Phoenix variants table");
3607                    my $Phoenix = 0;
3608                    my @Rows = $PhoenixVariantTable->get_rows_by_key($OrganismID,"GENOME");
3609                    my $VariantHash;
3610                    for (my $i=0; $i < @Rows; $i++) {
3611                            $Phoenix = 1;
3612                            if (defined($Rows[$i]->{"SUBSYSTEM"}) && defined($Rows[$i]->{"VARIANT"})) {
3613                                    $VariantHash->{$Rows[$i]->{"SUBSYSTEM"}->[0]} = $Rows[$i]->{"VARIANT"}->[0];
3614                            }
3615                  }                  }
3616    
3617                  #Collecting genome data                  #Collecting genome data
# Line 2971  Line 3886 
3886    
3887                  #Adding the biomass equation to the biomass table                  #Adding the biomass equation to the biomass table
3888                  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());
3889                  $biomassrxn = $NewRow->{DATABASE}->[0];                  $biomassrxn = $NewRow;
                 print $biomassrxn."\n";  
3890          }          }
3891          print $biomassrxn."\n";          return $biomassrxn;
         my $BiomassRow = $self->figmodel()->add_model_to_biomass_reaction($biomassrxn,$self->id());  
         return $BiomassRow;  
3892  }  }
3893    
3894  =head3 PrintSBMLFile  =head3 PrintSBMLFile
# Line 2989  Line 3901 
3901          my($self) = @_;          my($self) = @_;
3902    
3903          #Opening the SBML file for printing          #Opening the SBML file for printing
3904          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";  
         }  
3905          if (!open (SBMLOUTPUT, ">$Filename")) {          if (!open (SBMLOUTPUT, ">$Filename")) {
3906                  return;                  return;
3907          }          }
3908    
3909          #Loading and parsing the model data          #Loading and parsing the model data
3910          my $ModelTable = $self->reaction_table();          my $mdlTbl = $self->reaction_table();
3911          if (!defined($ModelTable) || !defined($ModelTable->{"array"})) {          if (!defined($mdlTbl) || !defined($mdlTbl->{"array"})) {
3912                  print "Failed to load ".$self->id()."\n";                  return $self->fail();
                 return;  
3913          }          }
3914            my $rxnTbl = $self->figmodel()->database()->get_table("REACTIONS");
3915            my $bioTbl = $self->figmodel()->database()->get_table("BIOMASS");
3916            my $cpdTbl = $self->figmodel()->database()->get_table("COMPOUNDS");
3917            my $cmpTbl = $self->figmodel()->database()->get_table("COMPARTMENTS");
3918    
3919          #Adding intracellular metabolites that also need exchange fluxes to the exchange hash          #Adding intracellular metabolites that also need exchange fluxes to the exchange hash
3920          my $ExchangeHash = {"cpd11416" => "c"};          my $ExchangeHash = {"cpd11416" => "c"};
   
3921          my %CompartmentsPresent;          my %CompartmentsPresent;
3922          $CompartmentsPresent{"c"} = 1;          $CompartmentsPresent{"c"} = 1;
3923          my %CompoundList;          my %CompoundList;
3924          my @ReactionList;          my @ReactionList;
3925          my $ReactionTable = $self->figmodel()->database()->GetDBTable("REACTIONS");          for (my $i=0; $i < $mdlTbl->size(); $i++) {
3926          for (my $i=0; $i < $ModelTable->size(); $i++) {                  my $Reaction = $mdlTbl->get_row($i)->{"LOAD"}->[0];
3927                  my $Reaction = $ModelTable->get_row($i)->{"LOAD"}->[0];                  my $row = $rxnTbl->get_row_by_key($Reaction,"DATABASE");
3928                  if (defined($ReactionTable->get_row_by_key($Reaction,"DATABASE")) && defined($ReactionTable->get_row_by_key($Reaction,"DATABASE")->{"EQUATION"}->[0])) {                  if (!defined($row)) {
3929                            $row = $bioTbl->get_row_by_key($Reaction,"DATABASE");
3930                            if (!defined($row)) {
3931                                    next;
3932                            }
3933                    }
3934                    if (!defined($row->{"EQUATION"}->[0])) {
3935                            next;
3936                    }
3937                          push(@ReactionList,$Reaction);                          push(@ReactionList,$Reaction);
3938                          $_ = $ReactionTable->get_row_by_key($Reaction,"DATABASE")->{"EQUATION"}->[0];                  $_ = $row->{"EQUATION"}->[0];
3939                          my @MatchArray = /(cpd\d\d\d\d\d)/g;                          my @MatchArray = /(cpd\d\d\d\d\d)/g;
3940                          for (my $j=0; $j < @MatchArray; $j++) {                          for (my $j=0; $j < @MatchArray; $j++) {
3941                                  $CompoundList{$MatchArray[$j]}->{"c"} = 1;                                  $CompoundList{$MatchArray[$j]}->{"c"} = 1;
3942                          }                          }
3943                          $_ = $ReactionTable->get_row_by_key($Reaction,"DATABASE")->{"EQUATION"}->[0];                  $_ = $row->{"EQUATION"}->[0];
3944                          @MatchArray = /(cpd\d\d\d\d\d\[\D\])/g;                          @MatchArray = /(cpd\d\d\d\d\d\[\D\])/g;
3945                          for (my $j=0; $j < @MatchArray; $j++) {                          for (my $j=0; $j < @MatchArray; $j++) {
3946                                  if ($MatchArray[$j] =~ m/(cpd\d\d\d\d\d)\[(\D)\]/) {                                  if ($MatchArray[$j] =~ m/(cpd\d\d\d\d\d)\[(\D)\]/) {
# Line 3033  Line 3949 
3949                                  }                                  }
3950                          }                          }
3951                  }                  }
         }  
3952    
3953          #Printing header to SBML file          #Printing header to SBML file
3954          my $ModelName = $self->id();          my $ModelName = $self->id().$self->selected_version();
3955          $ModelName =~ s/\./_/;          $ModelName =~ s/\./_/;
3956          print SBMLOUTPUT '<?xml version="1.0" encoding="UTF-8"?>'."\n";          print SBMLOUTPUT '<?xml version="1.0" encoding="UTF-8"?>'."\n";
3957      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";
3958      if (defined($self->figmodel()->database()->GetDBTable("MODEL STATS")->{$self->id()}->[0]->{"Organism name"}->[0])) {          if (defined($self->name())) {
3959          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";
3960      } else {      } else {
3961          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";
3962      }      }
3963    
3964          #Printing the unit data          #Printing the unit data
# Line 3060  Line 3975 
3975      #Printing compartments for SBML file      #Printing compartments for SBML file
3976      print SBMLOUTPUT '<listOfCompartments>'."\n";      print SBMLOUTPUT '<listOfCompartments>'."\n";
3977      foreach my $Compartment (keys(%CompartmentsPresent)) {      foreach my $Compartment (keys(%CompartmentsPresent)) {
3978          if (defined($self->figmodel()->database()->GetDBTable("COMPARTMENTS")->{$Compartment}->[0]->{"Name"}->[0])) {                  my $row = $cmpTbl->get_row_by_key($Compartment,"Abbreviation");
3979                  my @OutsideList = split(/\//,$self->figmodel()->database()->GetDBTable("COMPARTMENTS")->{$Compartment}->[0]->{"Outside"}->[0]);                  if (!defined($row) && !defined($row->{"Name"}->[0])) {
3980                            next;
3981                    }
3982                    my @OutsideList = split(/\//,$row->{"Outside"}->[0]);
3983                  my $Printed = 0;                  my $Printed = 0;
3984                  foreach my $Outside (@OutsideList) {                  foreach my $Outside (@OutsideList) {
3985                                  if (defined($CompartmentsPresent{$Outside}) && defined($self->figmodel()->database()->GetDBTable("COMPARTMENTS")->{$Outside}->[0]->{"Name"}->[0])) {                          if (defined($CompartmentsPresent{$Outside}) && defined($row->{"Name"}->[0])) {
3986                                  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";
3987                                  $Printed = 1;                                  $Printed = 1;
3988                                  last;                                  last;
3989                          }                          }
3990                  }                  }
3991                  if ($Printed eq 0) {                  if ($Printed eq 0) {
3992                          print SBMLOUTPUT '<compartment id="'.$self->figmodel()->database()->GetDBTable("COMPARTMENTS")->{$Compartment}->[0]->{"Name"}->[0].'"/>'."\n";                          print SBMLOUTPUT '<compartment id="'.$row->{"Name"}->[0].'"/>'."\n";
                         }  
3993          }          }
3994      }      }
3995      print SBMLOUTPUT '</listOfCompartments>'."\n";      print SBMLOUTPUT '</listOfCompartments>'."\n";
# Line 3080  Line 3997 
3997      #Printing the list of metabolites involved in the model      #Printing the list of metabolites involved in the model
3998          print SBMLOUTPUT '<listOfSpecies>'."\n";          print SBMLOUTPUT '<listOfSpecies>'."\n";
3999      foreach my $Compound (keys(%CompoundList)) {      foreach my $Compound (keys(%CompoundList)) {
4000                    my $row = $cpdTbl->get_row_by_key($Compound,"DATABASE");
4001                    if (!defined($row)) {
4002                            next;
4003                    }
4004          my $Name = $Compound;          my $Name = $Compound;
4005                  my $Formula = "";                  my $Formula = "";
4006                  if (defined($self->figmodel()->database()->GetDBTable("COMPOUNDS")->{$Compound}->[0]->{"FORMULA"}->[0])) {                  if (defined($row->{"FORMULA"}->[0])) {
4007                          $Formula = $self->figmodel()->database()->GetDBTable("COMPOUNDS")->{$Compound}->[0]->{"FORMULA"}->[0];                          $Formula = $row->{"FORMULA"}->[0];
4008                  }                  }
4009                  if (defined($self->figmodel()->database()->GetDBTable("COMPOUNDS")->{$Compound}->[0]->{"NAME"}->[0])) {                  if (defined($row->{"NAME"}->[0])) {
4010                          $Name = $self->figmodel()->database()->GetDBTable("COMPOUNDS")->{$Compound}->[0]->{"NAME"}->[0];                          $Name = $row->{"NAME"}->[0];
4011                          $Name =~ s/\s/_/;                          $Name =~ s/\s/_/;
4012                          $Name .= "_".$Formula;                          $Name .= "_".$Formula;
4013                  }                  }
4014                  $Name =~ s/[<>;&\*]//;                  $Name =~ s/[<>;&\*]//;
4015                  my $Charge = 0;                  my $Charge = 0;
4016                  if (defined($self->figmodel()->database()->GetDBTable("COMPOUNDS")->{$Compound}->[0]->{"CHARGE"}->[0])) {                  if (defined($row->{"CHARGE"}->[0])) {
4017                          $Charge = $self->figmodel()->database()->GetDBTable("COMPOUNDS")->{$Compound}->[0]->{"CHARGE"}->[0];                          $Charge = $row->{"CHARGE"}->[0];
4018                  }                  }
4019                  foreach my $Compartment (keys(%{$CompoundList{$Compound}})) {                  foreach my $Compartment (keys(%{$CompoundList{$Compound}})) {
4020                  if ($Compartment eq "e") {                  if ($Compartment eq "e") {
4021                          $ExchangeHash->{$Compound} = "e";                          $ExchangeHash->{$Compound} = "e";
4022                  }                  }
4023                  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");
4024                            print SBMLOUTPUT '<species id="'.$Compound.'_'.$Compartment.'" name="'.$Name.'" compartment="'.$cmprow->{"Name"}->[0].'" charge="'.$Charge.'" boundaryCondition="false"/>'."\n";
4025          }          }
4026      }      }
4027    
4028          #Printing the boundary species          #Printing the boundary species
4029          foreach my $Compound (keys(%{$ExchangeHash})) {          foreach my $Compound (keys(%{$ExchangeHash})) {
4030                  my $Name = $Compound;                  my $Name = $Compound;
4031                  my $Formula = "";                  my $Formula = "";
4032                  if (defined($self->figmodel()->database()->GetDBTable("COMPOUNDS")->{$Compound}->[0]->{"FORMULA"}->[0])) {                  my $row = $cpdTbl->get_row_by_key($Compound,"DATABASE");
4033                          $Formula = $self->figmodel()->database()->GetDBTable("COMPOUNDS")->{$Compound}->[0]->{"FORMULA"}->[0];                  if (!defined($row)) {
4034                            next;
4035                    }
4036                    if (defined($row->{"FORMULA"}->[0])) {
4037                            $Formula = $row->{"FORMULA"}->[0];
4038                  }                  }
4039                  if (defined($self->figmodel()->database()->GetDBTable("COMPOUNDS")->{$Compound}->[0]->{"NAME"}->[0])) {                  if (defined($row->{"NAME"}->[0])) {
4040                          $Name = $self->figmodel()->database()->GetDBTable("COMPOUNDS")->{$Compound}->[0]->{"NAME"}->[0];                          $Name = $row->{"NAME"}->[0];
4041                          $Name =~ s/\s/_/;                          $Name =~ s/\s/_/;
4042                          $Name .= "_".$Formula;                          $Name .= "_".$Formula;
4043                  }                  }
4044                  $Name =~ s/[<>;&\*]//;                  $Name =~ s/[<>;&\*]//;
4045                  my $Charge = 0;                  my $Charge = 0;
4046                  if (defined($self->figmodel()->database()->GetDBTable("COMPOUNDS")->{$Compound}->[0]->{"CHARGE"}->[0])) {                  if (defined($row->{"CHARGE"}->[0])) {
4047                          $Charge = $self->figmodel()->database()->GetDBTable("COMPOUNDS")->{$Compound}->[0]->{"CHARGE"}->[0];                          $Charge = $row->{"CHARGE"}->[0];
4048                  }                  }
4049                  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";
4050          }          }
# Line 3126  Line 4053 
4053      #Printing the list of reactions involved in the model      #Printing the list of reactions involved in the model
4054          my $ObjectiveCoef;          my $ObjectiveCoef;
4055      print SBMLOUTPUT '<listOfReactions>'."\n";      print SBMLOUTPUT '<listOfReactions>'."\n";
4056    
4057          foreach my $Reaction (@ReactionList) {          foreach my $Reaction (@ReactionList) {
4058          $ObjectiveCoef = "0.0";          $ObjectiveCoef = "0.0";
4059                  if (defined($self->figmodel()->database()->GetDBTable("REACTIONS")->{$Reaction}->[0]->{"EQUATION"}->[0])) {                  my $mdlrow = $mdlTbl->get_row_by_key($Reaction,"LOAD");
4060                    my $Reaction = $mdlrow->{"LOAD"}->[0];
4061                    my $row = $rxnTbl->get_row_by_key($Reaction,"DATABASE");
4062                    if (!defined($row)) {
4063                            $row = $bioTbl->get_row_by_key($Reaction,"DATABASE");
4064                            if (!defined($row)) {
4065                                    next;
4066                            }
4067                    }
4068                    if (!defined($row->{"EQUATION"}->[0])) {
4069                            next;
4070                    }
4071                  if ($Reaction =~ m/^bio/) {                  if ($Reaction =~ m/^bio/) {
4072                                  $ObjectiveCoef = "1.0";                                  $ObjectiveCoef = "1.0";
4073                          }                          }
4074                          my $LowerBound = -10000;                          my $LowerBound = -10000;
4075                  my $UpperBound = 10000;                  my $UpperBound = 10000;
4076                          my ($Reactants,$Products) = $self->figmodel()->GetReactionSubstrateData($Reaction);                  my ($Reactants,$Products) = $self->figmodel()->GetReactionSubstrateDataFromEquation($row->{"EQUATION"}->[0]);
4077                  my $Name = $Reaction;                  my $Name = $Reaction;
4078                  if (defined($self->figmodel()->database()->GetDBTable("REACTIONS")->{$Reaction}->[0]->{"NAME"}->[0])) {                  if (defined($row->{"NAME"}->[0])) {
4079                          $Name = $self->figmodel()->database()->GetDBTable("REACTIONS")->{$Reaction}->[0]->{"NAME"}->[0];                          $Name = $row->{"NAME"}->[0];
4080                                  $Name =~ s/[<>;&]//g;                                  $Name =~ s/[<>;&]//g;
4081                  }                  }
4082                  my $Reversibility = "true";                  my $Reversibility = "true";
4083                  if (defined($ModelTable->{$Reaction}->[0]->{"DIRECTIONALITY"}->[0])) {                  if (defined($mdlrow->{"DIRECTIONALITY"}->[0])) {
4084                          if ($ModelTable->{$Reaction}->[0]->{"DIRECTIONALITY"}->[0] ne "<=>") {                          if ($mdlrow->{"DIRECTIONALITY"}->[0] ne "<=>") {
4085                                  $LowerBound = 0;                                  $LowerBound = 0;
4086                                          $Reversibility = "false";                                          $Reversibility = "false";
4087                          }                          }
4088                          if ($ModelTable->{$Reaction}->[0]->{"DIRECTIONALITY"}->[0] eq "<=") {                          if ($mdlrow->{"DIRECTIONALITY"}->[0] eq "<=") {
4089                                  my $Temp = $Products;                                  my $Temp = $Products;
4090                                  $Products = $Reactants;                                  $Products = $Reactants;
4091                                  $Reactants = $Temp;                                  $Reactants = $Temp;
# Line 3155  Line 4094 
4094                          print SBMLOUTPUT '<reaction id="'.$Reaction.'" name="'.$Name.'" reversible="'.$Reversibility.'">'."\n";                          print SBMLOUTPUT '<reaction id="'.$Reaction.'" name="'.$Name.'" reversible="'.$Reversibility.'">'."\n";
4095                          print SBMLOUTPUT "<notes>\n";                          print SBMLOUTPUT "<notes>\n";
4096                          my $ECData = "";                          my $ECData = "";
4097                          if (defined($self->figmodel()->database()->GetDBTable("REACTIONS")->{$Reaction}->[0]->{"ENZYME"}->[0])) {                  if (defined($row->{"ENZYME"}->[0])) {
4098                                  $ECData = $self->figmodel()->database()->GetDBTable("REACTIONS")->{$Reaction}->[0]->{"ENZYME"}->[0];                          $ECData = $row->{"ENZYME"}->[0];
4099                          }                          }
4100                          my $SubsystemData = "";                          my $SubsystemData = "";
4101                          if (defined($ModelTable->{$Reaction}->[0]->{"SUBSYSTEM"}->[0])) {                  if (defined($mdlrow->{"SUBSYSTEM"}->[0])) {
4102                                  $SubsystemData = $ModelTable->{$Reaction}->[0]->{"SUBSYSTEM"}->[0];                          $SubsystemData = $mdlrow->{"SUBSYSTEM"}->[0];
4103                          }                          }
4104                          my $GeneAssociation = "";                          my $GeneAssociation = "";
4105                          my $ProteinAssociation = "";                          my $ProteinAssociation = "";
4106                          if (defined($ModelTable->{$Reaction}->[0]->{"ASSOCIATED PEG"}->[0])) {                  if (defined($mdlrow->{"ASSOCIATED PEG"}->[0])) {
4107                                  if (@{$ModelTable->{$Reaction}->[0]->{"ASSOCIATED PEG"}} == 1 && $ModelTable->{$Reaction}->[0]->{"ASSOCIATED PEG"}->[0] !~ m/\+/) {                          if (@{$mdlrow->{"ASSOCIATED PEG"}} == 1 && $mdlrow->{"ASSOCIATED PEG"}->[0] !~ m/\+/) {
4108                                          $GeneAssociation = $ModelTable->{$Reaction}->[0]->{"ASSOCIATED PEG"}->[0];                                  $GeneAssociation = $mdlrow->{"ASSOCIATED PEG"}->[0];
4109                                  } else {                                  } else {
4110                                          if (@{$ModelTable->{$Reaction}->[0]->{"ASSOCIATED PEG"}} > 1) {                                  if (@{$mdlrow->{"ASSOCIATED PEG"}} > 1) {
4111                                                  $GeneAssociation = "( ";                                                  $GeneAssociation = "( ";
4112                                          }                                          }
4113                                          for (my $i=0; $i < @{$ModelTable->{$Reaction}->[0]->{"ASSOCIATED PEG"}}; $i++) {                                  for (my $i=0; $i < @{$mdlrow->{"ASSOCIATED PEG"}}; $i++) {
4114                                                  if ($i > 0) {                                                  if ($i > 0) {
4115                                                          $GeneAssociation .= " )  or  ( ";                                                          $GeneAssociation .= " )  or  ( ";
4116                                                  }                                                  }
4117                                                  $GeneAssociation .= $ModelTable->{$Reaction}->[0]->{"ASSOCIATED PEG"}->[$i];                                          $GeneAssociation .= $mdlrow->{"ASSOCIATED PEG"}->[$i];
4118                                          }                                          }
4119                                          if (@{$ModelTable->{$Reaction}->[0]->{"ASSOCIATED PEG"}} > 1) {                                  if (@{$mdlrow->{"ASSOCIATED PEG"}} > 1) {
4120                                                  $GeneAssociation .= " )";                                                  $GeneAssociation .= " )";
4121                                          }                                          }
4122                                  }                                  }
# Line 3186  Line 4125 
4125                                          $GeneAssociation = "( ".$GeneAssociation." )";                                          $GeneAssociation = "( ".$GeneAssociation." )";
4126                                  }                                  }
4127                                  $ProteinAssociation = $GeneAssociation;                                  $ProteinAssociation = $GeneAssociation;
4128                                  if (defined($self->figmodel()->database()->GetDBTable("MODEL STATS")->{$self->id()}->[0]->{"Genome ID"}->[0])) {                          if (defined($self->genome())) {
4129                                          $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());
4130                                  }                                  }
4131                          }                          }
4132                          print SBMLOUTPUT "<html:p>GENE_ASSOCIATION:".$GeneAssociation."</html:p>\n";                          print SBMLOUTPUT "<html:p>GENE_ASSOCIATION:".$GeneAssociation."</html:p>\n";
# Line 3218  Line 4157 
4157              print SBMLOUTPUT "</kineticLaw>\n";              print SBMLOUTPUT "</kineticLaw>\n";
4158                          print SBMLOUTPUT '</reaction>'."\n";                          print SBMLOUTPUT '</reaction>'."\n";
4159                  }                  }
         }  
4160    
4161          my @ExchangeList = keys(%{$ExchangeHash});          my @ExchangeList = keys(%{$ExchangeHash});
4162          foreach my $ExCompound (@ExchangeList) {          foreach my $ExCompound (@ExchangeList) {
4163                  my $ExCompoundName = $ExCompound;                  my $ExCompoundName = $ExCompound;
4164                  my $Row = $self->figmodel()->database()->GetDBTable("COMPOUNDS")->get_row_by_key($ExCompound,"DATABASE");                  my $Row = $cpdTbl->get_row_by_key($ExCompound,"DATABASE");
4165                  if (defined($Row) && defined($Row->{"NAME"}->[0])) {                  if (defined($Row) && defined($Row->{"NAME"}->[0])) {
4166                          $ExCompoundName = $Row->{"NAME"}->[0];                          $ExCompoundName = $Row->{"NAME"}->[0];
4167                          $ExCompoundName =~ s/[<>;&]//g;                          $ExCompoundName =~ s/[<>;&]//g;
# Line 3263  Line 4201 
4201          close(SBMLOUTPUT);          close(SBMLOUTPUT);
4202  }  }
4203    
4204    =head3 PrintModelSimpleReactionTable
4205    Definition:
4206            success()/fail() FIGMODELmodel->PrintModelSimpleReactionTable();
4207    Description:
4208            Prints the table of model data
4209    =cut
4210    sub PrintModelSimpleReactionTable {
4211            my ($self) = @_;
4212    
4213            my $rxntbl = $self->reaction_table();
4214            my $tbl = $self->create_table_prototype("ModelSimpleReactionTable");
4215            for (my $i=0; $i < $rxntbl->size(); $i++) {
4216                    my $row = $rxntbl->get_row($i);
4217                    $row->{DATABASE} = $row->{LOAD};
4218                    $tbl->add_row($row);
4219            }
4220            $tbl->save();
4221    }
4222    
4223  =head3 PrintModelLPFile  =head3 PrintModelLPFile
4224  Definition:  Definition:
4225          success()/fail() FIGMODELmodel->PrintModelLPFile();          success()/fail() FIGMODELmodel->PrintModelLPFile();
# Line 3287  Line 4244 
4244          $self->figmodel()->clearing_output($UniqueFilename,"FBA-".$self->id().$self->selected_version().".lp");          $self->figmodel()->clearing_output($UniqueFilename,"FBA-".$self->id().$self->selected_version().".lp");
4245  }  }
4246    
4247    =head3 patch_model
4248    Definition:
4249            FIGMODELTable:patch results = FIGMODELmodel->patch_model(FIGMODELTable:patch table);
4250    Description:
4251    =cut
4252    sub patch_model {
4253            my ($self,$tbl) = @_;
4254    
4255            #Instantiating table
4256            my $results = FIGMODELTable->new(["Reactions","New genes","Old genes","Genes","Roles","Status"],$self->directory()."PatchResults-".$self->id().$self->selected_version().".tbl",["Reaction"],"\t",";",undef);
4257            #Getting genome annotations
4258            my $features = $self->figmodel()->database()->get_genome_feature_table($self->genome());
4259            #Gettubg reaction table
4260            my $reactions = $self->reaction_table();
4261            #Checking for patched roles
4262            for (my $i=0; $i < $tbl->size(); $i++) {
4263                    my $row = $tbl->get_row($i);
4264                    my @genes = $features->get_rows_by_key($row->{ROLE}->[0],"ROLES");
4265                    if (@genes > 0) {
4266                            for (my $j=0; $j < @{$row->{REACTIONS}};$j++) {
4267                                    my $resultrxn = $results->get_row_by_key($row->{REACTIONS}->[$j],"Reactions");
4268                                    if (!defined($resultrxn)) {
4269                                            $resultrxn = $results->add_row({"Reactions"=>[$row->{REACTIONS}->[$j]],"Roles"=>[$row->{ROLE}->[0]]});
4270                                    }
4271                                    my $rxnrow = $reactions->get_row_by_key($row->{REACTIONS}->[$j],"LOAD");
4272                                    if (defined($rxnrow) && !defined($resultrxn->{"Old genes"})) {
4273                                            $resultrxn->{"Old genes"} = $rxnrow->{"ASSOCIATED PEG"};
4274                                            if ($resultrxn->{"Old genes"}->[0] !~ m/GAP|BOF|UNIVERSAL|SPONTANEOUS/) {
4275                                                    push(@{$resultrxn->{"Genes"}},@{$resultrxn->{"Old genes"}});
4276                                            }
4277                                    }
4278                                    delete $resultrxn->{"Current gene set"};
4279                                    if (defined($resultrxn->{"Genes"})) {
4280                                            push(@{$resultrxn->{"Current gene set"}},@{$resultrxn->{"Genes"}});
4281                                    }
4282                                    for (my $k=0; $k < @genes; $k++) {
4283                                            if ($genes[$k]->{ID}->[0] =~ m/(peg\.\d+)/) {
4284                                                    my $gene = $1;
4285                                                    my $addgene = 1;
4286                                                    if (defined($resultrxn->{"Old genes"})) {
4287                                                            for (my $m=0; $m < @{$resultrxn->{"Old genes"}}; $m++) {
4288                                                                    if ($resultrxn->{"Old genes"}->[$m] =~ m/$gene/) {
4289                                                                            $addgene = 0;
4290                                                                    }
4291                                                            }
4292                                                    }
4293                                                    if ($addgene == 1) {
4294                                                            push(@{$resultrxn->{"New genes"}},$gene);
4295                                                            if ($row->{COMPLEX}->[0] ne "0" && defined($resultrxn->{"Current gene set"})) {
4296                                                                    my $added = 0;
4297                                                                    for (my $m=0; $m < @{$resultrxn->{"Current gene set"}}; $m++) {
4298                                                                            if ($row->{COMPLEX}->[0] eq "1") {
4299                                                                                    $resultrxn->{"Current gene set"}->[$m] = $resultrxn->{"Current gene set"}->[$m]."+".$gene;
4300                                                                                    $added = 1;
4301                                                                            } else {
4302                                                                                    my @geneset = split(/\+/,$resultrxn->{"Current gene set"}->[$m]);
4303                                                                                    for (my $n=0; $n < @geneset;$n++) {
4304                                                                                            if ($self->figmodel()->colocalized_genes($geneset[$n],$gene,$self->genome()) == 1) {
4305                                                                                                    $resultrxn->{"Current gene set"}->[$m] = $resultrxn->{"Current gene set"}->[$m]."+".$gene;
4306                                                                                                    $added = 1;
4307                                                                                                    last;
4308                                                                                            }
4309                                                                                    }
4310                                                                            }
4311                                                                    }
4312                                                                    if ($added == 0) {
4313                                                                            push(@{$resultrxn->{"Current gene set"}},$gene);
4314                                                                    }
4315                                                            } else {
4316                                                                    push(@{$resultrxn->{"Current gene set"}},$gene);
4317                                                            }
4318                                                    }
4319                                            }
4320                                    }
4321                                    delete $resultrxn->{"Genes"};
4322                                    push(@{$resultrxn->{"Genes"}},@{$resultrxn->{"Current gene set"}});
4323                            }
4324                    }
4325            }
4326    
4327            #Ensuring that the old model is preserved
4328            $self->ArchiveModel();
4329            #Modifing the reaction list
4330            for (my $i=0; $i < $results->size();$i++) {
4331                    my $row = $results->get_row($i);
4332                    my $rxnrow = $reactions->get_row_by_key($row->{"Reactions"}->[0],"LOAD");
4333                    if (defined($rxnrow)) {
4334                            $rxnrow->{"ASSOCIATED PEG"} = $row->{"Genes"};
4335                    } else {
4336                            $reactions->add_row({LOAD=>[$row->{"Reactions"}->[0]],DIRECTIONALITY=>[$self->figmodel()->reversibility_of_reaction($row->{"Reactions"}->[0])],COMPARTMENT=>["c"],"ASSOCIATED PEG"=>$row->{"Genes"},SUBSYSTEM=>["NONE"],CONFIDENCE=>[2],REFERENCE=>["NONE"],NOTES=>["PATCH"]});
4337                    }
4338            }
4339            $reactions->save();
4340            $results->save();
4341            $self->update_model_stats();
4342            $self->PrintModelLPFile();
4343            $self->run_default_model_predictions();
4344            #Returning results
4345            return $results;
4346    }
4347    
4348    =head3 translate_genes
4349    Definition:
4350            FIGMODELmodel->translate_genes();
4351    Description:
4352    =cut
4353    sub translate_genes {
4354            my ($self) = @_;
4355    
4356            #Loading gene translations
4357            if (!defined($self->{_gene_aliases})) {
4358                    #Loading gene aliases from feature table
4359                    my $tbl = $self->figmodel()->GetGenomeFeatureTable($self->genome());
4360                    if (defined($tbl)) {
4361                            for (my $i=0; $i < $tbl->size(); $i++) {
4362                                    my $row = $tbl->get_row($i);
4363                                    if ($row->{ID}->[0] =~ m/(peg\.\d+)/) {
4364                                            my $geneID = $1;
4365                                            for (my $j=0; $j < @{$row->{ALIASES}}; $j++) {
4366                                                    $self->{_gene_aliases}->{$row->{ALIASES}->[$j]} = $geneID;
4367                                            }
4368                                    }
4369                            }
4370                    }
4371                    #Loading additional gene aliases from the database
4372                    if (-e $self->figmodel()->config("Translation directory")->[0]."AdditionalAliases/".$self->genome().".txt") {
4373                            my $AdditionalAliases = $self->figmodel()->database()->load_multiple_column_file($self->figmodel()->config("Translation directory")->[0]."AdditionalAliases/".$self->genome().".txt","\t");
4374                            for (my $i=0; $i < @{$AdditionalAliases}; $i++) {
4375                                    $self->{_gene_aliases}->{$AdditionalAliases->[$i]->[1]} = $AdditionalAliases->[$i]->[0];
4376                            }
4377                    }
4378            }
4379    
4380            #Cycling through reactions and translating genes
4381            for (my $i=0; $i < $self->reaction_table()->size(); $i++) {
4382                    my $row = $self->reaction_table()->get_row($i);
4383                    if (defined($row->{"ASSOCIATED PEG"})) {
4384                            for (my $j=0; $j < @{$row->{"ASSOCIATED PEG"}}; $j++) {
4385                                    my $Original = $row->{"ASSOCIATED PEG"}->[$j];
4386                                    $Original =~ s/\sand\s/:/g;
4387                                    $Original =~ s/\sor\s/;/g;
4388                                    my @GeneNames = split(/[,\+\s\(\):;]/,$Original);
4389                                    foreach my $Gene (@GeneNames) {
4390                                            if (length($Gene) > 0 && defined($self->{_gene_aliases}->{$Gene})) {
4391                                                    my $Replace = $self->{_gene_aliases}->{$Gene};
4392                                                    $Original =~ s/([^\w])$Gene([^\w])/$1$Replace$2/g;
4393                                                    $Original =~ s/^$Gene([^\w])/$Replace$1/g;
4394                                                    $Original =~ s/([^\w])$Gene$/$1$Replace/g;
4395                                                    $Original =~ s/^$Gene$/$Replace/g;
4396                                            }
4397                                    }
4398                                    $Original =~ s/:/ and /g;
4399                                    $Original =~ s/;/ or /g;
4400                                    $row->{"ASSOCIATED PEG"}->[$j] = $Original;
4401                            }
4402                    }
4403            }
4404    
4405            #Archiving model and saving reaction table
4406            $self->ArchiveModel();
4407            $self->reaction_table()->save();
4408    }
4409    
4410    =head3 feature_web_data
4411    Definition:
4412            string:web output for feature/model connection = FIGMODELmodel->feature_web_data(FIGMODELfeature:feature);
4413    Description:
4414    =cut
4415    sub feature_web_data {
4416            my ($self,$feature) = @_;
4417    
4418            #First checking if the feature is in the model
4419            my $featureGenome = $feature->{GENOME}->[0];
4420            if ($feature->{GENOME}->[0] =~ m/\>(\d+\.\d+)\</) {
4421                    $featureGenome = $1;
4422            }
4423            if ($featureGenome ne $self->genome()) {
4424                    return "Not in model";
4425            }
4426            my $data = $self->get_feature_data($feature->{ID}->[0]);
4427            if (!defined($data)) {
4428                    return "Not in model";
4429            }
4430    
4431            my $output;
4432            #Printing predictions
4433            if (defined($data->{$self->id()."PREDICTIONS"})) {
4434                    #Parsing essentiality data
4435                    my $essentialityData;
4436                    if (defined($feature->{ESSENTIALITY})) {
4437                            for (my $i=0; $i < @{$feature->{ESSENTIALITY}};$i++) {
4438                                    my @temp = split(/:/,$feature->{ESSENTIALITY}->[$i]);
4439                                    $essentialityData->{$temp[0]} = $temp[1];
4440                            }
4441                    }
4442                    my $predictionHash;
4443                    for (my $i=0; $i < @{$data->{$self->id()."PREDICTIONS"}};$i++) {
4444                            my @temp = split(/:/,$data->{$self->id()."PREDICTIONS"}->[$i]);
4445                            if (defined($essentialityData->{$temp[0]})) {
4446                                    if ($temp[1] eq "essential" && $essentialityData->{$temp[0]} eq "essential") {
4447                                            push(@{$predictionHash->{"Correct negative"}},$temp[0]);
4448                                    } elsif ($temp[1] eq "nonessential" && $essentialityData->{$temp[0]} eq "essential") {
4449                                            push(@{$predictionHash->{"False positive"}},$temp[0]);
4450                                    } elsif ($temp[1] eq "essential" && $essentialityData->{$temp[0]} eq "nonessential") {
4451                                            push(@{$predictionHash->{"False negative"}},$temp[0]);
4452                                    } elsif ($temp[1] eq "nonessential" && $essentialityData->{$temp[0]} eq "nonessential") {
4453                                            push(@{$predictionHash->{"Correct positive"}},$temp[0]);
4454                                    }
4455                            } else {
4456                                    push(@{$predictionHash->{$temp[1]}},$temp[0]);
4457                            }
4458                    }
4459                    foreach my $key (keys(%{$predictionHash})) {
4460                            my $string = $key;
4461                            $string = ucfirst($string);
4462                            push(@{$output},'<span title="'.join(", ",@{$predictionHash->{$key}}).'">'.$string.'</span>');
4463                    }
4464            }
4465    
4466            #Printing reactions
4467            if (defined($data->{$self->id()."REACTIONS"})) {
4468                    for (my $i=0; $i < @{$data->{$self->id()."REACTIONS"}};$i++) {
4469                            my $rxnData = $self->get_reaction_data($data->{$self->id()."REACTIONS"}->[$i]);
4470                            my $reactionString = $self->figmodel()->web()->create_reaction_link($data->{$self->id()."REACTIONS"}->[$i],join(" or ",@{$rxnData->{"ASSOCIATED PEG"}}),$self->id());
4471                            if (defined($rxnData->{PREDICTIONS})) {
4472                                    my $predictionHash;
4473                                    for (my $i=0; $i < @{$rxnData->{PREDICTIONS}};$i++) {
4474                                            my @temp = split(/:/,$rxnData->{PREDICTIONS}->[$i]);
4475                                            push(@{$predictionHash->{$temp[1]}},$temp[0]);
4476                                    }
4477                                    $reactionString .= "(";
4478                                    foreach my $key (keys(%{$predictionHash})) {
4479                                            if ($key eq "Essential =>") {
4480                                                    $reactionString .= '<span title="Essential in '.join(",",@{$predictionHash->{$key}}).'">E=></span>,';
4481                                            } elsif ($key eq "Essential <=") {
4482                                                    $reactionString .= '<span title="Essential in '.join(",",@{$predictionHash->{$key}}).'">E<=</span>,';
4483                                            } elsif ($key eq "Active =>") {
4484                                                    $reactionString .= '<span title="Active in '.join(",",@{$predictionHash->{$key}}).'">A=></span>,';
4485                                            } elsif ($key eq "Active <=") {
4486                                                    $reactionString .= '<span title="Active in '.join(",",@{$predictionHash->{$key}}).'">A<=</span>,';
4487                                            } elsif ($key eq "Active <=>") {
4488                                                    $reactionString .= '<span title="Active in '.join(",",@{$predictionHash->{$key}}).'">A</span>,';
4489                                            } elsif ($key eq "Inactive") {
4490                                                    $reactionString .= '<span title="Inactive in '.join(",",@{$predictionHash->{$key}}).'">I</span>,';
4491                                            } elsif ($key eq "Dead") {
4492                                                    $reactionString .= '<span title="Dead">D</span>,';
4493                                            }
4494                                    }
4495                                    $reactionString =~ s/,$/)/;
4496                            }
4497                            push(@{$output},$reactionString);
4498                    }
4499            }
4500    
4501            #Returning output
4502            return join("<br>",@{$output});
4503    }
4504    
4505    =head3 remove_obsolete_reactions
4506    Definition:
4507            void FIGMODELmodel->remove_obsolete_reactions();
4508    Description:
4509    =cut
4510    sub remove_obsolete_reactions {
4511            my ($self) = @_;
4512    
4513            (my $dummy,my $translation) = $self->figmodel()->put_two_column_array_in_hash($self->figmodel()->database()->load_multiple_column_file($self->figmodel()->config("Translation directory")->[0]."ObsoleteRxnIDs.txt","\t"));
4514            my $rxnTbl = $self->reaction_table();
4515            if (defined($rxnTbl)) {
4516                    for (my $i=0; $i < $rxnTbl->size(); $i++) {
4517                            my $row = $rxnTbl->get_row($i);
4518                            if (defined($translation->{$row->{LOAD}->[0]}) || defined($translation->{$row->{LOAD}->[0]."r"})) {
4519                                    my $direction = $row->{DIRECTION}->[0];
4520                                    my $newRxn;
4521                                    if (defined($translation->{$row->{LOAD}->[0]."r"})) {
4522                                            $newRxn = $translation->{$row->{LOAD}->[0]."r"};
4523                                            if ($direction eq "<=") {
4524                                                    $direction = "=>";
4525                                            } elsif ($direction eq "=>") {
4526                                                    $direction = "<=";
4527                                            }
4528                                    } else {
4529                                            $newRxn = $translation->{$row->{LOAD}->[0]};
4530                                    }
4531                                    #Checking if the new reaction is already in the model
4532                                    my $newRow = $rxnTbl->get_row_by_key($newRxn,"LOAD");
4533                                    if (defined($newRow)) {
4534                                            #Handling direction
4535                                            if ($newRow->{DIRECTION}->[0] ne $direction) {
4536                                                    $newRow->{DIRECTION}->[0] = "<=>";
4537                                            }
4538                                            push(@{$row->{"ASSOCIATED PEG"}},@{$rxnTbl->get_row($i)->{"ASSOCIATED PEG"}});
4539                                    } else {
4540                                            $rxnTbl->get_row($i)->{LOAD}->[0] = $newRxn;
4541                                            $rxnTbl->get_row($i)->{DIRECTION}->[0] = $direction;
4542                                    }
4543                            }
4544                    }
4545                    $rxnTbl->save();
4546            }
4547    }
4548    
4549    =pod
4550    
4551    =item * [string]:I<list of essential genes> = B<run_geneKO_slow> (string:I<media>,0/1:I<max growth>,0/1:I<save results>);
4552    
4553    =cut
4554    
4555    sub run_geneKO_slow {
4556            my ($self,$media,$maxGrowth,$save) = @_;
4557            my $output;
4558            my $UniqueFilename = $self->figmodel()->filename();
4559            if (defined($maxGrowth) && $maxGrowth == 1) {
4560                    system($self->figmodel()->GenerateMFAToolkitCommandLineCall($UniqueFilename,$self->id(),$media,["ProductionMFA"],{"perform single KO experiments" => 1,"MFASolver" => "GLPK","Constrain objective to this fraction of the optimal value" => 0.999},"SlowGeneKO-".$self->id().$self->selected_version()."-".$UniqueFilename.".log",undef,$self->selected_version()));
4561            } else {
4562                    system($self->figmodel()->GenerateMFAToolkitCommandLineCall($UniqueFilename,$self->id(),$media,["ProductionMFA"],{"perform single KO experiments" => 1,"MFASolver" => "GLPK","Constrain objective to this fraction of the optimal value" => 0.1},"SlowGeneKO-".$self->id().$self->selected_version()."-".$UniqueFilename.".log",undef,$self->selected_version()));
4563            }
4564            if (!-e $self->config("MFAToolkit output directory")->[0].$UniqueFilename."DeletionStudyResults.txt") {
4565                    print "Deletion study file not found!.\n";
4566                    return undef;
4567            }
4568            my $deltbl = $self->figmodel()->database()->load_table($self->config("MFAToolkit output directory")->[0].$UniqueFilename."DeletionStudyResults.txt",";","|",1,["Experiment"]);
4569            for (my $i=0; $i < $deltbl->size(); $i++) {
4570                    my $row = $deltbl->get_row($i);
4571                    if ($row->{"Insilico growth"}->[0] < 0.0000001) {
4572                            push(@{$output},$row->{Experiment}->[0]);
4573                    }
4574            }
4575            if (defined($output)) {
4576                    if (defined($save) && $save == 1) {
4577                            my $tbl = $self->load_model_table("EssentialGenes");
4578                            my $row = $tbl->get_table_by_key("MEDIA",$media)->get_row_by_key("MAXGROWTH",$maxGrowth);
4579                            if (defined($row)) {
4580                                    $row->{GENES} = $output;
4581                            } else {
4582                                    $tbl->add_row({GENES => $output,MEDIA => [$media],MAXGROWTH => [$maxGrowth]});
4583                            }
4584                            $tbl->save();
4585                    }
4586            }
4587