[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.16, Fri May 21 04:32:42 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 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                                    $class.="<br>[Flux: ".sprintf("%.3g",$min)." to ".sprintf("%.3g",$max)."]<br>";
249                          } elsif ($ClassRow->{CLASS}->[0] eq "Negative") {                          } elsif ($ClassRow->{CLASS}->[0] eq "Negative") {
250                                  $class = "Essential <=";                                  $class = "Essential <=";
251                                    $class.="<br>[Flux: ".sprintf("%.3g",$min)." to ".sprintf("%.3g",$max)."]<br>";
252                          } elsif ($ClassRow->{CLASS}->[0] eq "Positive variable") {                          } elsif ($ClassRow->{CLASS}->[0] eq "Positive variable") {
253                                  $class = "Active =>";                                  $class = "Active =>";
254                                    $class.="<br>[Flux: ".sprintf("%.3g",$min)." to ".sprintf("%.3g",$max)."]<br>";
255                          } elsif ($ClassRow->{CLASS}->[0] eq "Negative variable") {                          } elsif ($ClassRow->{CLASS}->[0] eq "Negative variable") {
256                                  $class = "Active <=";                                  $class = "Active <=";
257                                    $class.="<br>[Flux: ".sprintf("%.3g",$min)." to ".sprintf("%.3g",$max)."]<br>";
258                          } elsif ($ClassRow->{CLASS}->[0] eq "Variable") {                          } elsif ($ClassRow->{CLASS}->[0] eq "Variable") {
259                                  $class = "Active <=>";                                  $class = "Active <=>";
260                                    $class.="<br>[Flux: ".sprintf("%.3g",$min)." to ".sprintf("%.3g",$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") {                                  $NewClass.="<br>[Flux: ".sprintf("%.3g",$min)." to ".sprintf("%.3g",$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") {                                  $NewClass.="<br>[Flux: ".sprintf("%.3g",$min)." to ".sprintf("%.3g",$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") {                                  $NewClass.="<br>[Flux: ".sprintf("%.3g",$min)." to ".sprintf("%.3g",$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") {                                  $NewClass.="<br>[Flux: ".sprintf("%.3g",$min)." to ".sprintf("%.3g",$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") {                                  $NewClass.="<br>[Flux: ".sprintf("%.3g",$min)." to ".sprintf("%.3g",$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)) {
391                    $refresh = 1;
392            }
393            if ($refresh == 1) {
394                    delete $self->{"_".$name};
395            }
396            if (!defined($self->{"_".$name})) {
397                    my $tbldef = $self->figmodel()->config("$name");
398                    if (!defined($tbldef)) {
399                            return undef;
400                    }
401                    my $filename = $self->directory().$name."-".$self->id().$self->selected_version().".tbl";
402                    $self->{"_".$name} = $self->figmodel()->database()->load_table($filename,"\t","|",$tbldef->{headingline}->[0],$tbldef->{hashcolumns});
403                    if (!defined($self->{"_".$name})) {
404                            if (defined($tbldef->{prefix})) {
405                                    $self->{"_".$name} = FIGMODELTable->new($tbldef->{columns},$filename,$tbldef->{hashcolumns},"\t","|",join(@{$tbldef->{prefix}},"\n"));
406                            } else {
407                                    $self->{"_".$name} = FIGMODELTable->new($tbldef->{columns},$filename,$tbldef->{hashcolumns},"\t","|");
408                            }
409                    }
410            }
411            return $self->{"_".$name};
412    }
413    
414    =head3 create_table_prototype
415    
416    Definition:
417            FIGMODELTable::table = FIGMODELmodel->create_table_prototype(string::table);
418    Description:
419            Returns a empty FIGMODELTable with all the metadata associated with the input table name
420    
421    =cut
422    sub create_table_prototype {
423            my ($self,$TableName) = @_;
424    
425            #Checking if the table definition exists in the FIGMODELconfig file
426            if (!defined($self->figmodel()->config($TableName))) {
427                    $self->figmodel()->error_message("FIGMODELdatabase:create_table_prototype:Definition not found for ".$TableName);
428                    return undef;
429            }
430            #Checking that this is a database table
431            if (!defined($self->config($TableName)->{tabletype}) || $self->config($TableName)->{tabletype}->[0] ne "ModelTable") {
432                    $self->figmodel()->error_message("FIGMODELdatabase:create_table_prototype:".$TableName." is not a model table!");
433                    return undef;
434            }
435            if (!defined($self->config($TableName)->{delimiter})) {
436                    $self->config($TableName)->{delimiter}->[0] = ";";
437            }
438            if (!defined($self->config($TableName)->{itemdelimiter})) {
439                    $self->config($TableName)->{itemdelimiter}->[0] = "|";
440            }
441            my $prefix;
442            if (defined($self->config($TableName)->{prefix})) {
443                    $prefix = join("\n",@{$self->config($TableName)->{prefix}});
444            }
445            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);
446            return $tbl;
447    }
448    
449  =head3 get_reaction_number  =head3 get_reaction_number
450  Definition:  Definition:
451          int = FIGMODELmodel->get_reaction_number();          int = FIGMODELmodel->get_reaction_number();
# Line 374  Line 454 
454  =cut  =cut
455  sub get_reaction_number {  sub get_reaction_number {
456          my ($self) = @_;          my ($self) = @_;
   
457          if (!defined($self->reaction_table())) {          if (!defined($self->reaction_table())) {
458                  return 0;                  return 0;
459          }          }
   
460          return $self->reaction_table()->size();          return $self->reaction_table()->size();
461  }  }
462    
# Line 393  Line 471 
471    
472          if (!defined($self->{_reaction_data})) {          if (!defined($self->{_reaction_data})) {
473                  $self->{_reaction_data} = $self->figmodel()->database()->GetDBModel($self->id());                  $self->{_reaction_data} = $self->figmodel()->database()->GetDBModel($self->id());
474                    my $classTbl = $self->reaction_class_table();
475                    for (my $i=0; $i < $classTbl->size(); $i++) {
476                            my $row = $classTbl->get_row($i);
477                            my $rxnRow = $self->{_reaction_data}->get_row_by_key($row->{"REACTION"}->[0],"LOAD");
478                            for (my $j=0; $j < @{$row->{MEDIA}};$j++) {
479                                    my $class = "Active <=>";
480                                    if ($row->{CLASS}->[$j] eq "Positive") {
481                                            $class = "Essential =>";
482                                    } elsif ($row->{CLASS}->[$j] eq "Negative") {
483                                            $class = "Essential <=";
484                                    } elsif ($row->{CLASS}->[$j] eq "Blocked") {
485                                            $class = "Inactive";
486                                    } elsif ($row->{CLASS}->[$j] eq "Positive variable") {
487                                            $class = "Active =>";
488                                    } elsif ($row->{CLASS}->[$j] eq "Negative variable") {
489                                            $class = "Active <=";
490                                    } elsif ($row->{CLASS}->[$j] eq "Variable") {
491                                            $class = "Active <=>";
492                                    } elsif ($row->{CLASS}->[$j] eq "Dead") {
493                                            $class = "Dead";
494                                    }
495                                    push(@{$rxnRow->{PREDICTIONS}},$row->{MEDIA}->[$j].":".$class);
496                            }
497                    }
498          }          }
499    
500          return $self->{_reaction_data};          return $self->{_reaction_data};
501  }  }
502    
503    =head3 feature_table
504    Definition:
505            FIGMODELTable = FIGMODELmodel->feature_table();
506    Description:
507            Returns FIGMODELTable with the feature list for the model
508    =cut
509    sub feature_table {
510            my ($self) = @_;
511    
512            if (!defined($self->{_feature_data})) {
513                    #Getting the genome feature list
514                    my $FeatureTable = $self->figmodel()->GetGenomeFeatureTable($self->genome());
515                    if (!defined($FeatureTable)) {
516                            print STDERR "FIGMODELmodel:feature_table:Could not get features for genome ".$self->genome()." in database!";
517                            return undef;
518                    }
519                    #Getting the reaction table for the model
520                    my $rxnTable = $self->reaction_table();
521                    if (!defined($rxnTable)) {
522                    print STDERR "FIGMODELmodel:feature_table:Could not get reaction table for model ".$self->id()." in database!";
523                            return undef;
524                }
525                    #Cloning the feature table
526                    $self->{_feature_data} = $FeatureTable->clone_table_def();
527                    $self->{_feature_data}->add_headings(($self->id()."REACTIONS",$self->id()."PREDICTIONS"));
528                for (my $i=0; $i < $rxnTable->size(); $i++) {
529                    my $Row = $rxnTable->get_row($i);
530                    if (defined($Row) && defined($Row->{"ASSOCIATED PEG"})) {
531                            foreach my $GeneSet (@{$Row->{"ASSOCIATED PEG"}}) {
532                                    my $temp = $GeneSet;
533                                    $temp =~ s/\+/|/g;
534                                    $temp =~ s/\sAND\s/|/gi;
535                                    $temp =~ s/\sOR\s/|/gi;
536                                    $temp =~ s/[\(\)\s]//g;
537                                    my @GeneList = split(/\|/,$temp);
538                                    foreach my $Gene (@GeneList) {
539                                    my $FeatureRow = $self->{_feature_data}->get_row_by_key("fig|".$self->genome().".".$Gene,"ID");
540                                                    if (!defined($FeatureRow)) {
541                                                            $FeatureRow = $FeatureTable->get_row_by_key("fig|".$self->genome().".".$Gene,"ID");
542                                                            if (defined($FeatureRow)) {
543                                                                    $self->{_feature_data}->add_row($FeatureRow);
544                                                            }
545                                                    }
546                                                    if (defined($FeatureRow)) {
547                                                            $self->{_feature_data}->add_data($FeatureRow,$self->id()."REACTIONS",$Row->{"LOAD"}->[0],1);
548                                                    }
549                                    }
550                            }
551                    }
552                }
553                #Loading predictions
554                my @files = glob($self->directory()."EssentialGenes-".$self->id()."-*");
555                foreach my $file (@files) {
556                    if ($file =~ m/\-([^\-]+)\.tbl/) {
557                            my $media = $1;
558                            my $list = $self->figmodel()->database()->load_single_column_file($file,"");
559                            my $hash;
560                            foreach my $gene (@{$list}) {
561                                    $hash->{$gene} = 1;
562                            }
563                            for (my $i=0; $i < $self->{_feature_data}->size(); $i++) {
564                                    my $Row = $self->{_feature_data}->get_row($i);
565                                    if ($Row->{ID}->[0] =~ m/(peg\.\d+)/) {
566                                            my $gene = $1;
567                                            if (defined($hash->{$gene})) {
568                                                    push(@{$Row->{$self->id()."PREDICTIONS"}},$media.":essential");
569                                            } else {
570                                                    push(@{$Row->{$self->id()."PREDICTIONS"}},$media.":nonessential");
571                                            }
572                                    }
573                            }
574                    }
575                }
576            }
577            return $self->{_feature_data};
578    }
579    
580  =head3 reaction_class_table  =head3 reaction_class_table
581  Definition:  Definition:
582          FIGMODELTable = FIGMODELmodel->reaction_class_table();          FIGMODELTable = FIGMODELmodel->reaction_class_table();
# Line 438  Line 617 
617          return $self->{_compound_class_table};          return $self->{_compound_class_table};
618  }  }
619    
620    =head3 get_essential_genes
621    Definition:
622            [string::peg ID] = FIGMODELmodel->get_essential_genes(string::media condition);
623    Description:
624            Returns an reference to an array of the predicted essential genes during growth in the input media condition
625    =cut
626    sub get_essential_genes {
627            my ($self,$media) = @_;
628    
629            if (!defined($media)) {
630                    $media = "Complete";
631            }
632            if (!defined($self->{_essential_genes}->{$media})) {
633                    $self->{_essential_genes}->{$media} = undef;
634                    if (-e $self->directory()."EssentialGenes-".$self->id().$self->selected_version()."-".$media.".tbl") {
635                            $self->{_essential_genes}->{$media} = $self->figmodel()->database()->load_single_column_file($self->directory()."EssentialGenes-".$self->id().$self->selected_version()."-".$media.".tbl","");
636                    }
637            }
638    
639            return $self->{_essential_genes}->{$media};
640    }
641    
642  =head3 compound_table  =head3 compound_table
643  Definition:  Definition:
644          FIGMODELTable = FIGMODELmodel->compound_table();          FIGMODELTable = FIGMODELmodel->compound_table();
# Line 456  Line 657 
657    
658  =head3 get_compound_data  =head3 get_compound_data
659  Definition:  Definition:
660          string = FIGMODELmodel->get_compound_data(string::compound ID);          {string:key=>[string]:values} = FIGMODELmodel->get_compound_data(string::compound ID);
661  Description:  Description:
662          Returns model compound data          Returns model compound data
663  =cut  =cut
# Line 467  Line 668 
668                  return undef;                  return undef;
669          }          }
670          if ($compound =~ m/^\d+$/) {          if ($compound =~ m/^\d+$/) {
671                  $self->compound_table()->get_row($compound);                  return $self->compound_table()->get_row($compound);
672          }          }
673          return $self->compound_table()->get_row_by_key($compound,"DATABASE");          return $self->compound_table()->get_row_by_key($compound,"DATABASE");
674  }  }
675    
676    =head3 get_feature_data
677    Definition:
678            {string:key=>[string]:values} = FIGMODELmodel->get_feature_data(string::feature ID);
679    Description:
680            Returns model feature data
681    =cut
682    sub get_feature_data {
683            my ($self,$feature) = @_;
684            if (!defined($self->feature_table())) {
685                    return undef;
686            }
687            if ($feature =~ m/^\d+$/) {
688                    return $self->feature_table()->get_row($feature);
689            }
690            if ($feature =~ m/(peg\.\d+)/) {
691                    $feature = $1;
692            }
693            return $self->feature_table()->get_row_by_key("fig|".$self->genome().".".$feature,"ID");
694    }
695    
696  =head3 genome  =head3 genome
697  Definition:  Definition:
698          string = FIGMODELmodel->genome();          string = FIGMODELmodel->genome();
# Line 480  Line 701 
701  =cut  =cut
702  sub genome {  sub genome {
703          my ($self) = @_;          my ($self) = @_;
704          return $self->{_data}->{genome}->[0];          return $self->{_data}->genome();
705  }  }
706    
707  =head3 source  =head3 source
# Line 491  Line 712 
712  =cut  =cut
713  sub source {  sub source {
714          my ($self) = @_;          my ($self) = @_;
715          return $self->{_data}->{source}->[0];          return $self->{_data}->source();
716  }  }
717    
718  =head3 rights  =head3 rights
# Line 502  Line 723 
723  =cut  =cut
724  sub rights {  sub rights {
725          my ($self,$username) = @_;          my ($self,$username) = @_;
   
726          if ($self->public()) {          if ($self->public()) {
727                  return 1;                  return 1;
728          }          }
# Line 510  Line 730 
730                  return 0;                  return 0;
731          }          }
732          if (!defined($self->{_userrights}->{$username})) {          if (!defined($self->{_userrights}->{$username})) {
733                  if (defined($self->{_data}->{master})) {                  $self->{_userrights}->{$self->{_data}->owner()} = 1;
734                          for (my $i=0; $i < @{$self->{_data}->{master}};$i++) {                  my @users = split(/\|/,$self->{_data}->users());
735                                  $self->{_userrights}->{$self->{_data}->{master}->[$i]} = 1;                  for (my $i=0; $i < @users;$i++) {
736                          }                          $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;  
                         }  
737                  }                  }
738          }          }
739          return $self->{_userrights}->{$username};          return $self->{_userrights}->{$username};
# Line 532  Line 747 
747  =cut  =cut
748  sub public {  sub public {
749          my ($self) = @_;          my ($self) = @_;
750            if ($self->{_data}->users() eq "all") {
751          if (!defined($self->{_public})) {                  return 1;
                 $self->{_public} = 0;  
                 if (defined($self->{_data}->{users}->[0]) && $self->{_data}->{users}->[0] eq "all") {  
                         $self->{_public} = 1;  
                 }  
752          }          }
753          return $self->{_public};          return 0;
754  }  }
755    
756  =head3 directory  =head3 directory
# Line 587  Line 798 
798          return $self->directory().$self->id().$self->selected_version().".txt";          return $self->directory().$self->id().$self->selected_version().".txt";
799  }  }
800    
 =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};  
         }  
 }  
   
801  =head3 version  =head3 version
802  Definition:  Definition:
803          string = FIGMODELmodel->version();          string = FIGMODELmodel->version();
# Line 638  Line 809 
809    
810          if (!defined($self->{_version})) {          if (!defined($self->{_version})) {
811                  if (!defined($self->{_selectedversion})) {                  if (!defined($self->{_selectedversion})) {
812                          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];  
                         }  
813                  } else {                  } else {
814                          $self->{_version} = $self->{_selectedversion};                          $self->{_version} = $self->{_selectedversion};
815                  }                  }
# Line 671  Line 840 
840  =cut  =cut
841  sub modification_time {  sub modification_time {
842          my ($self) = @_;          my ($self) = @_;
843          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};  
844  }  }
845    
846  =head3 gene_reactions  =head3 gene_reactions
# Line 695  Line 851 
851  =cut  =cut
852  sub gene_reactions {  sub gene_reactions {
853          my ($self) = @_;          my ($self) = @_;
854            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};  
855  }  }
856    
857  =head3 total_compounds  =head3 total_compounds
# Line 714  Line 862 
862  =cut  =cut
863  sub total_compounds {  sub total_compounds {
864          my ($self) = @_;          my ($self) = @_;
865            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};  
866  }  }
867    
868  =head3 gapfilling_reactions  =head3 gapfilling_reactions
# Line 733  Line 873 
873  =cut  =cut
874  sub gapfilling_reactions {  sub gapfilling_reactions {
875          my ($self) = @_;          my ($self) = @_;
876            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};  
877  }  }
878    
879  =head3 total_reactions  =head3 total_reactions
# Line 752  Line 884 
884  =cut  =cut
885  sub total_reactions {  sub total_reactions {
886          my ($self) = @_;          my ($self) = @_;
887            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};  
888  }  }
889    
890  =head3 model_genes  =head3 model_genes
# Line 771  Line 895 
895  =cut  =cut
896  sub model_genes {  sub model_genes {
897          my ($self) = @_;          my ($self) = @_;
898            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};  
899  }  }
900    
901  =head3 class  =head3 class
# Line 790  Line 906 
906  =cut  =cut
907  sub class {  sub class {
908          my ($self) = @_;          my ($self) = @_;
909            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];  
                 }  
         }  
         return $self->{_class};  
910  }  }
911    
912  =head3 taxonomy  =head3 taxonomy
# Line 866  Line 974 
974                          if (defined($self->mgdata())) {                          if (defined($self->mgdata())) {
975                                  $self->{_genome_genes} = $self->mgdata()->genome_contig_count;                                  $self->{_genome_genes} = $self->mgdata()->genome_contig_count;
976                          }                          }
977                  } elsif (defined($self->stats())) {                  } else {
978                          $self->{_genome_genes} = $self->stats()->{'Total genes'}->[0];                          $self->{_genome_genes} = $self->figmodel()->get_genome_stats($self->genome())->{"TOTAL GENES"}->[0];
979                  }                  }
980          }          }
981    
# Line 892  Line 1000 
1000          #Checking that the table is defined and the output file exists          #Checking that the table is defined and the output file exists
1001          if (defined($result) && defined($result->get_row(0)->{"ESSENTIALGENES"})) {          if (defined($result) && defined($result->get_row(0)->{"ESSENTIALGENES"})) {
1002                  $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"}})]);
1003            } else {
1004                    $self->figmodel()->error_message("FIGMODELmodel:run_default_model_predictions:could not identify essential reactions for model ".$self->id().$self->selected_version().".");
1005                    return $self->figmodel()->fail();
1006          }          }
1007    
1008          #Classifying reactions and compounds          #Classifying reactions and compounds
1009          my $tbl = $self->classify_model_reactions($Media);          my $tbl = $self->classify_model_reactions($Media);
1010            if (!defined($tbl)) {
1011                    $self->figmodel()->error_message("FIGMODELmodel:run_default_model_predictions:could not classify reactions for model ".$self->id().$self->selected_version().".");
1012                    return $self->figmodel()->fail();
1013            }
1014          $tbl->save();          $tbl->save();
1015    
1016          return $self->figmodel()->success();          return $self->figmodel()->success();
1017  }  }
1018    
 =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();  
         }  
 }  
   
1019  =head3 update_stats_for_gap_filling  =head3 update_stats_for_gap_filling
1020  Definition:  Definition:
1021          {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 1023 
1023  =cut  =cut
1024  sub update_stats_for_gap_filling {  sub update_stats_for_gap_filling {
1025          my ($self,$gapfilltime) = @_;          my ($self,$gapfilltime) = @_;
1026            $self->{_data}->autoCompleteTime($gapfilltime);
1027          #preserving the stats for the now obselete model          $self->{_data}->autocompleteDate(time());
1028          $self->save_obsolete_stats();          $self->{_data}->modificationDate(time());
1029          my $stats = $self->update_model_stats(0);          my $version = $self->{_data}->autocompleteVersion();
1030          $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;  
1031  }  }
1032    
1033  =head3 update_stats_for_build  =head3 update_stats_for_build
# Line 948  Line 1037 
1037  =cut  =cut
1038  sub update_stats_for_build {  sub update_stats_for_build {
1039          my ($self) = @_;          my ($self) = @_;
1040            $self->{_data}->builtDate(time());
1041          #preserving the stats for the now obselete model          $self->{_data}->modificationDate(time());
1042          $self->save_obsolete_stats();          my $version = $self->{_data}->version();
1043          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;  
1044  }  }
1045    
1046  =head3 update_model_stats  =head3 update_model_stats
# Line 979  Line 1059 
1059          }          }
1060          my $cpdtbl = $self->compound_table();          my $cpdtbl = $self->compound_table();
1061    
1062          #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];  
         }  
   
1063          my %GeneHash;          my %GeneHash;
1064          my %NonpegHash;          my %NonpegHash;
1065          my %CompoundHash;          my %CompoundHash;
1066            my $spontaneousReactions = 0;
1067            my $gapFillReactions = 0;
1068            my $biologReactions = 0;
1069            my $transporters = 0;
1070            my $autoCompleteReactions = 0;
1071            my $associatedSubsystemGenes = 0;
1072          for (my $i=0; $i < $rxntbl->size(); $i++) {          for (my $i=0; $i < $rxntbl->size(); $i++) {
1073                  my $Row = $rxntbl->get_row($i);                  my $Row = $rxntbl->get_row($i);
1074                  if (defined($Row) && defined($Row->{"ASSOCIATED PEG"})) {                  if (defined($Row) && defined($Row->{"ASSOCIATED PEG"})) {
# Line 1037  Line 1076 
1076                          if (defined($ReactionRow->{"EQUATION"}->[0])) {                          if (defined($ReactionRow->{"EQUATION"}->[0])) {
1077                                  #Checking for extracellular metabolites which indicate that this is a transporter                                  #Checking for extracellular metabolites which indicate that this is a transporter
1078                                  if ($ReactionRow->{"EQUATION"}->[0] =~ m/\[e\]/) {                                  if ($ReactionRow->{"EQUATION"}->[0] =~ m/\[e\]/) {
1079                                          $CurrentStats->{"Transport reaction"}->[0]++;                                          $transporters++;
1080                                  }                                  }
1081                          }                          }
1082                          #Identifying spontaneous/biolog/gapfilling/gene associated reactions                          #Identifying spontaneous/biolog/gapfilling/gene associated reactions
1083                          if ($Row->{"ASSOCIATED PEG"}->[0] =~ m/BIOLOG/i) {                          if ($Row->{"ASSOCIATED PEG"}->[0] =~ m/BIOLOG/i) {
1084                                  $CurrentStats->{"Biolog gap filling reactions"}->[0]++;                                  $biologReactions++;
1085                            } elsif ($Row->{"ASSOCIATED PEG"}->[0] =~ m/GROW/i) {
1086                                    $gapFillReactions++;
1087                          } elsif ($Row->{"ASSOCIATED PEG"}->[0] =~ m/SPONTANEOUS/i) {                          } elsif ($Row->{"ASSOCIATED PEG"}->[0] =~ m/SPONTANEOUS/i) {
1088                                  $CurrentStats->{"Spontaneous"}->[0]++;                                  $spontaneousReactions++;
1089                          } 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) {
1090                                  $CurrentStats->{"Gap filling reactions"}->[0]++;                                  $autoCompleteReactions++;
1091                          } else {                          } else {
1092                                  foreach my $GeneSet (@{$Row->{"ASSOCIATED PEG"}}) {                                  foreach my $GeneSet (@{$Row->{"ASSOCIATED PEG"}}) {
1093                                          my @GeneList = split(/\+/,$GeneSet);                                          $_ = $GeneSet;
1094                                            my @GeneList = /(peg\.\d+)/g;
1095                                          foreach my $Gene (@GeneList) {                                          foreach my $Gene (@GeneList) {
1096                                                  if ($Gene =~ m/(peg\.\d+)/) {                                                  if ($Gene =~ m/(peg\.\d+)/) {
1097                                                          $GeneHash{$1} = 1;                                                          $GeneHash{$1} = 1;
# Line 1063  Line 1105 
1105          }          }
1106          my @genes = keys(%GeneHash);          my @genes = keys(%GeneHash);
1107          my @othergenes = keys(%NonpegHash);          my @othergenes = keys(%NonpegHash);
         $CurrentStats->{"Genes with reactions"}->[0] = @genes + @othergenes;  
1108    
1109          #Updating the stats stored in the table          #Setting the reaction count
1110          $self->figmodel()->database()->update_row("MODEL STATS",$CurrentStats,"Model ID");          $self->{_data}->reactions($rxntbl->size());
1111          $self->{_stats} = $CurrentStats;          #Setting the metabolite count
1112          return $CurrentStats;          $self->{_data}->compounds($rxntbl->size());
1113            #Setting the gene count
1114            my $geneCount = @genes + @othergenes;
1115            $self->{_data}->associatedGenes($geneCount);
1116            #Setting remaining stats
1117            $self->{_data}->spontaneousReactions($spontaneousReactions);
1118            $self->{_data}->gapFillReactions($gapFillReactions);
1119            $self->{_data}->biologReactions($biologReactions);
1120            $self->{_data}->transporters($transporters);
1121            $self->{_data}->autoCompleteReactions($autoCompleteReactions);
1122            $self->{_data}->associatedSubsystemGenes($associatedSubsystemGenes);
1123            #Setting the model class
1124            my $class = "";
1125            for (my $i=0; $i < @{$self->figmodel()->config("class list")}; $i++) {
1126                    if (defined($self->figmodel()->config($self->figmodel()->config("class list")->[$i]))) {
1127                            if (defined($self->figmodel()->config($self->figmodel()->config("class list")->[$i])->{$self->id()})) {
1128                                    $class = $self->figmodel()->config("class list")->[$i];
1129                                    last;
1130                            }
1131                            if ($class eq "" && defined($self->figmodel()->config($self->figmodel()->config("class list")->[$i])->{$self->genome()})) {
1132                                    $class = $self->figmodel()->config("class list")->[$i];
1133                            }
1134                    }
1135            }
1136            if ($class eq "") {
1137                    $class = $self->figmodel()->get_genome_stats($self->genome())->{CLASS}->[0];
1138            }
1139            if ($class eq "") {
1140                    $class = "unknown";
1141            }
1142            $self->{_data}->cellwalltype($class);
1143  }  }
1144    
1145  =head3 GapFillModel  =head3 GapFillModel
# Line 1119  Line 1190 
1190                          }                          }
1191                  }                  }
1192                  $MediaTable->save($self->config("Media directory")->[0].$UniqueFilename."TestMedia.txt");                  $MediaTable->save($self->config("Media directory")->[0].$UniqueFilename."TestMedia.txt");
1193                  system($self->figmodel()->GenerateMFAToolkitCommandLineCall($UniqueFilename,$self->id(),$UniqueFilename."TestMedia",["GapFilling"],{"Default max drain flux" => 0},"GapFill".$self->id().".log",undef));                  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));
1194                  unlink($self->config("Media directory")->[0].$UniqueFilename."TestMedia.txt");                  unlink($self->config("Media directory")->[0].$UniqueFilename."TestMedia.txt");
1195          } else {          } else {
1196                  system($self->figmodel()->GenerateMFAToolkitCommandLineCall($UniqueFilename,$self->id(),undef,["GapFilling"],undef,"GapFill".$self->id().".log",undef));                  system($self->figmodel()->GenerateMFAToolkitCommandLineCall($UniqueFilename,$self->id(),undef,["GapFilling"],{"Reactions to knockout" => $self->config("permanently knocked out reactions")->[0]},"GapFill".$self->id().".log",undef));
1197          }          }
1198    
1199          #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
# Line 1140  Line 1211 
1211          for (my $i=($SolutionData->size()-1); $i >=0; $i--) {          for (my $i=($SolutionData->size()-1); $i >=0; $i--) {
1212                  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/) {
1213                          my $AllSolutions = substr($SolutionData->get_row($i)->{"Notes"}->[0],15);                          my $AllSolutions = substr($SolutionData->get_row($i)->{"Notes"}->[0],15);
                         print "Solution:".$AllSolutions."\n";  
1214                          my @TempThree = split(/\|/,$AllSolutions);                          my @TempThree = split(/\|/,$AllSolutions);
1215                          if (@TempThree > 0 && $TempThree[0] =~ m/.+:(.+)/) {                          if (@TempThree > 0 && $TempThree[0] =~ m/.+:(.+)/) {
1216                                  my @TempFour = split(/,/,$1);                                  my @TempFour = split(/,/,$1);
# Line 1163  Line 1233 
1233                                                  push(@{$ReactionList},$ID);                                                  push(@{$ReactionList},$ID);
1234                                          }                                          }
1235                                  }                                  }
                                 print "Solution:".$TempThree[0]."\n";  
1236                                  $self->figmodel()->IntegrateGrowMatchSolution($self->id(),undef,$ReactionList,$DirectionList,"GAP FILLING",0,1);                                  $self->figmodel()->IntegrateGrowMatchSolution($self->id(),undef,$ReactionList,$DirectionList,"GAP FILLING",0,1);
1237                          }                          }
1238                          last;                          last;
# Line 1171  Line 1240 
1240          }          }
1241          #Updating model stats with gap filling results          #Updating model stats with gap filling results
1242          my $ElapsedTime = time() - $StartTime;          my $ElapsedTime = time() - $StartTime;
1243          $self->figmodel()->ClearDBModel($self->id(),1);          $self->figmodel()->database()->ClearDBModel($self->id(),1);
1244          #Determining why each gap filling reaction was added          #Determining why each gap filling reaction was added
1245          $self->figmodel()->IdentifyDependancyOfGapFillingReactions($self->id(),$Media);          $self->figmodel()->IdentifyDependancyOfGapFillingReactions($self->id(),$Media);
1246          if (!defined($donotclear) || $donotclear != 1) {          if (!defined($donotclear) || $donotclear != 1) {
# Line 1191  Line 1260 
1260          return $self->success();          return $self->success();
1261  }  }
1262    
1263    =head3 GapGenModel
1264    Definition:
1265            FIGMODELmodel->GapGenModel();
1266    Description:
1267            Runs the gap generation algorithm to correct a single false positive prediction. Results are loaded into a table.
1268    =cut
1269    
1270    sub GapGenModel {
1271            my ($self,$Media,$KOList,$NoKOList,$Experiment,$SolutionLimit) = @_;
1272    
1273            #Enforcing nonoptional arguments
1274            if (!defined($Media)) {
1275                    return undef;
1276            }
1277            if (!defined($KOList)) {
1278                    $KOList->[0] = "none";
1279            }
1280            if (!defined($NoKOList)) {
1281                    $NoKOList->[0] = "none";
1282            }
1283            if (!defined($Experiment)) {
1284                    $Experiment= "ReactionKO";
1285            }
1286            if (!defined($SolutionLimit)) {
1287                    $SolutionLimit = "10";
1288            }
1289    
1290            #Translating the KO lists into arrays
1291            if (ref($KOList) ne "ARRAY") {
1292                    my $temp = $KOList;
1293                    $KOList = ();
1294                    push(@{$KOList},split(/[,;]/,$temp));
1295            }
1296            my $noKOHash;
1297            if (defined($NoKOList) && ref($NoKOList) ne "ARRAY") {
1298                    my $temp = $NoKOList;
1299                    $NoKOList = ();
1300                    push(@{$NoKOList},split(/[,;]/,$temp));
1301                    foreach my $rxn (@{$NoKOList}) {
1302                            $noKOHash->{$rxn} = 1;
1303                    }
1304            }
1305    
1306            #Checking if solutions exist for the input parameters
1307            $self->aquireModelLock();
1308            my $tbl = $self->load_model_table("GapGenSolutions");
1309            my $solutionRow = $tbl->get_table_by_key($Experiment,"Experiment")->get_table_by_key($Media,"Media")->get_row_by_key(join(",",@{$KOList}),"KOlist");
1310            my $solutions;
1311            if (defined($solutionRow)) {
1312                    #Checking if any solutions conform to the no KO list
1313                    foreach my $solution (@{$solutionRow->{Solutions}}) {
1314                            my @reactions = split(/,/,$solution);
1315                            my $include = 1;
1316                            foreach my $rxn (@reactions) {
1317                                    if ($rxn =~ m/(rxn\d\d\d\d\d)/) {
1318                                            if (defined($noKOHash->{$1})) {
1319                                                    $include = 0;
1320                                            }
1321                                    }
1322                            }
1323                            if ($include == 1) {
1324                                    push(@{$solutions},$solution);
1325                            }
1326                    }
1327            } else {
1328                    $solutionRow = {Media => [$Media],Experiment => [$Experiment],KOlist => [join(",",@{$KOList})]};
1329                    $tbl->add_row($solutionRow);
1330                    $self->figmodel()->database()->save_table($tbl);
1331            }
1332            $self->releaseModelLock();
1333    
1334            #Returning solution list of solutions were found
1335            if (defined($solutions) && @{$solutions} > 0) {
1336                    return $solutions;
1337            }
1338    
1339            #Getting unique filename
1340            my $Filename = $self->figmodel()->filename();
1341    
1342            #Running the gap generation
1343            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));
1344            my $ProblemReport = $self->figmodel()->LoadProblemReport($Filename);
1345            if (!defined($ProblemReport)) {
1346                    $self->figmodel()->error_message("FIGMODEL:GapGenerationAlgorithm;No problem report;".$Filename.";".$self->id().$self->selected_version().";".$Media.";".$KOList.";".$NoKOList);
1347                    return undef;
1348            }
1349    
1350            #Clearing the output folder and log file
1351            $self->figmodel()->clearing_output($Filename,"Gapgeneration-".$self->id().$self->selected_version()."-".$Filename.".log");
1352    
1353            #Saving the solution
1354            $self->aquireModelLock();
1355            $tbl = $self->load_model_table("GapGenSolutions");
1356            $solutionRow = $tbl->get_table_by_key($Experiment,"Experiment")->get_table_by_key($Media,"Media")->get_row_by_key(join(",",@{$KOList}),"KOlist");
1357            for (my $j=0; $j < $ProblemReport->size(); $j++) {
1358                    if ($ProblemReport->get_row($j)->{"Notes"}->[0] =~ m/^Recursive\sMILP\s([^)]+)/) {
1359                            my @SolutionList = split(/\|/,$1);
1360                            for (my $k=0; $k < @SolutionList; $k++) {
1361                                    if ($SolutionList[$k] =~ m/(\d+):(.+)/) {
1362                                            push(@{$solutionRow->{Solutions}},$2);
1363                                            push(@{$solutions},$2);
1364                                    }
1365                            }
1366                    }
1367            }
1368            $self->figmodel()->database()->save_table($tbl);
1369            $self->releaseModelLock();
1370    
1371            return $solutions;
1372    }
1373    
1374  =head3 datagapfill  =head3 datagapfill
1375  Definition:  Definition:
1376          success()/fail() = FIGMODELmodel->datagapfill();          success()/fail() = FIGMODELmodel->datagapfill();
# Line 1201  Line 1381 
1381          my ($self,$GapFillingRunSpecs,$TansferFileSuffix) = @_;          my ($self,$GapFillingRunSpecs,$TansferFileSuffix) = @_;
1382          my $UniqueFilename = $self->figmodel()->filename();          my $UniqueFilename = $self->figmodel()->filename();
1383          if (defined($GapFillingRunSpecs) && @{$GapFillingRunSpecs} > 0) {          if (defined($GapFillingRunSpecs) && @{$GapFillingRunSpecs} > 0) {
                 print "Gap filling specs:\n".join("\n",@{$GapFillingRunSpecs})."\n\n";  
1384                  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));
   
1385                  #Checking that the solution exists                  #Checking that the solution exists
1386                  if (!-e $self->config("MFAToolkit output directory")->[0].$UniqueFilename."/GapFillingSolutionTable.txt") {                  if (!-e $self->config("MFAToolkit output directory")->[0].$UniqueFilename."/GapFillingSolutionTable.txt") {
1387                          $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 1391 
1391                  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);
1392                  if (defined($TansferFileSuffix)) {                  if (defined($TansferFileSuffix)) {
1393                          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");  
1394                  }                  }
   
1395                  #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
1396                  $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");
1397                  return $GapFillingRunSpecs;                  return $GapFillResultTable;
1398          }          }
1399          if (defined($TansferFileSuffix)) {          if (defined($TansferFileSuffix)) {
1400                  $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 1460 
1460                          push(@{$DirectionArray},$SolutionHash{$ReactionList[$k]});                          push(@{$DirectionArray},$SolutionHash{$ReactionList[$k]});
1461                  }                  }
1462                  print "Integrating solution!\n";                  print "Integrating solution!\n";
1463                  $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);
1464                  my $model = $self->get_model($self->id().$TempVersion);                  $self->PrintModelLPFile();
                 $model->PrintModelLPFile();  
1465                  #Running the model against all available experimental data                  #Running the model against all available experimental data
1466                  print "Running test model!\n";                  print "Running test model!\n";
1467                  my ($FalsePostives,$FalseNegatives,$CorrectNegatives,$CorrectPositives,$Errorvector,$HeadingVector) = $self->RunAllStudiesWithDataFast("All");                  my ($FalsePostives,$FalseNegatives,$CorrectNegatives,$CorrectPositives,$Errorvector,$HeadingVector) = $self->RunAllStudiesWithDataFast("All");
# Line 1367  Line 1542 
1542  sub CreateSingleGenomeReactionList {  sub CreateSingleGenomeReactionList {
1543          my ($self,$RunGapFilling) = @_;          my ($self,$RunGapFilling) = @_;
1544    
1545            #Creating directory
1546            if ($self->owner() ne "master" && !-d $self->figmodel()->config("organism directory")->[0].$self->owner()."/") {
1547                    system("mkdir ".$self->figmodel()->config("organism directory")->[0].$self->owner()."/");
1548            } elsif ($self->owner() eq "master" && !-d $self->figmodel()->config("organism directory")->[0].$self->genome()."/") {
1549                    system("mkdir ".$self->figmodel()->config("organism directory")->[0].$self->genome()."/");
1550            }
1551            if ($self->owner() ne "master" && !-d $self->figmodel()->config("organism directory")->[0].$self->owner()."/".$self->genome()."/") {
1552                    system("mkdir ".$self->figmodel()->config("organism directory")->[0].$self->owner()."/".$self->genome()."/");
1553            }
1554    
1555          #Getting genome stats          #Getting genome stats
1556          my $genomestats = $self->figmodel()->get_genome_stats($self->genome());          my $genomestats = $self->figmodel()->get_genome_stats($self->genome());
1557          my $FeatureTable = $self->figmodel()->GetGenomeFeatureTable($self->genome());          my $FeatureTable = $self->figmodel()->GetGenomeFeatureTable($self->genome());
# Line 1601  Line 1786 
1786          }          }
1787    
1788          #Checking if a biomass reaction already exists          #Checking if a biomass reaction already exists
1789          my $BiomassReactionRow = $self->figmodel()->database()->get_row_by_key("BIOMASS TABLE",$self->id(),"MODELS");          my $BiomassReactionRow = $self->BuildSpecificBiomassReaction();
         if (!defined($BiomassReactionRow)) {  
                 $BiomassReactionRow = $self->BuildSpecificBiomassReaction();  
1790                  if (!defined($BiomassReactionRow)) {                  if (!defined($BiomassReactionRow)) {
1791                          $self->set_status(-2,"Preliminary reconstruction failed: could not generate biomass reaction");                          $self->set_status(-2,"Preliminary reconstruction failed: could not generate biomass reaction");
1792                          $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()."!");
1793                          return $self->fail();                          return $self->fail();
1794                  }                  }
         }  
1795          my $ReactionList = $BiomassReactionRow->{"ESSENTIAL REACTIONS"};          my $ReactionList = $BiomassReactionRow->{"ESSENTIAL REACTIONS"};
1796          push(@{$ReactionList},$BiomassReactionRow->{DATABASE}->[0]);          push(@{$ReactionList},$BiomassReactionRow->{DATABASE}->[0]);
1797    
# Line 1702  Line 1884 
1884          $self->figmodel()->database()->save_table($NewModelTable);          $self->figmodel()->database()->save_table($NewModelTable);
1885          $self->{_reaction_data} = $NewModelTable;          $self->{_reaction_data} = $NewModelTable;
1886          #Clearing the previous model from the cache          #Clearing the previous model from the cache
1887          $self->figmodel()->ClearDBModel($self->id(),1);          $self->figmodel()->database()->ClearDBModel($self->id(),1);
1888          #Updating the model stats table          #Updating the model stats table
1889          $self->update_stats_for_build();          $self->update_stats_for_build();
1890          $self->PrintSBMLFile();          $self->PrintSBMLFile();
# Line 1823  Line 2005 
2005          }          }
2006    
2007          #Clearing the previous model from the cache          #Clearing the previous model from the cache
2008          $self->figmodel()->ClearDBModel($self->id(),1);          $self->figmodel()->database()->ClearDBModel($self->id(),1);
2009          $ModelTable->save();          $ModelTable->save();
2010    
2011          return $self->success();          return $self->success();
# Line 1839  Line 2021 
2021  sub ArchiveModel {  sub ArchiveModel {
2022          my ($self) = @_;          my ($self) = @_;
2023    
         #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();  
         }  
   
2024          #Checking that the model file exists          #Checking that the model file exists
2025          if (!(-e $self->filename())) {          if (!(-e $self->filename())) {
2026                  $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 2071 
2071          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
2072  =cut  =cut
2073  sub run_microarray_analysis {  sub run_microarray_analysis {
2074          my ($self,$media,$jobid,$index,$genecall) = @_;          my ($self,$media,$label,$index,$genecall) = @_;
2075          $genecall =~ s/_/:/g;          $genecall =~ s/_/:/g;
2076          $genecall =~ s/\//;/g;          $genecall =~ s/\//;/g;
2077          #print "\n\n".$genecall."\n\n";          my $uniqueFilename = $self->figmodel()->filename();
2078          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());
2079          #print $command."\n";          system($command);
2080            my $filename = $self->figmodel()->config("MFAToolkit output directory")->[0].$uniqueFilename."/MicroarrayOutput-".$index.".txt";
2081        if (-e $filename) {
2082            my $output = $self->figmodel()->database()->load_single_column_file($filename);
2083            if (defined($output->[0])) {
2084                    my @array = split(/;/,$output->[0]);
2085                    $self->figmodel()->clearing_output($uniqueFilename,"MicroarrayAnalysis-".$uniqueFilename.".txt");
2086                    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]);
2087            }
2088            print STDERR $filename." is empty!";
2089        }
2090        print STDERR $filename." not found!";
2091        $self->figmodel()->clearing_output($uniqueFilename,"MicroarrayAnalysis-".$uniqueFilename.".txt");
2092    
2093            return undef;
2094    }
2095    
2096    =head3 find_minimal_pathways
2097    Definition:
2098            int::status = FIGMODEL->find_minimal_pathways(string::media,string::objective);
2099    Description:
2100            Runs microarray analysis attempting to turn off genes that are inactive in the microarray
2101    =cut
2102    sub find_minimal_pathways {
2103            my ($self,$media,$objective,$solutionnum,$AllReversible,$additionalexchange) = @_;
2104    
2105            #Setting default media
2106            if (!defined($media)) {
2107                    $media = "Complete";
2108            }
2109    
2110            #Setting default solution number
2111            if (!defined($solutionnum)) {
2112                    $solutionnum = "5";
2113            }
2114    
2115            #Setting additional exchange fluxes
2116            if (!defined($additionalexchange) || length($additionalexchange) == 0) {
2117                    if ($self->id() eq "iAF1260") {
2118                            $additionalexchange = "cpd03422[c]:-100:100;cpd01997[c]:-100:100;cpd11416[c]:-100:0;cpd15378[c]:-100:0;cpd15486[c]:-100:0";
2119                    } else {
2120                            $additionalexchange = $self->figmodel()->config("default exchange fluxes")->[0];
2121                    }
2122            }
2123    
2124            #Translating objective
2125            my $objectivestring;
2126            if ($objective eq "ALL") {
2127                    #Getting the list of universal building blocks
2128                    my $buildingblocks = $self->config("universal building blocks");
2129                    my @objectives = keys(%{$buildingblocks});
2130                    #Getting the nonuniversal building blocks
2131                    my $otherbuildingblocks = $self->config("nonuniversal building blocks");
2132                    my @array = keys(%{$otherbuildingblocks});
2133                    if (defined($self->get_biomass()) && defined($self->figmodel()->get_reaction($self->get_biomass()->{"LOAD"}->[0]))) {
2134                            my $equation = $self->figmodel()->get_reaction($self->get_biomass()->{"LOAD"}->[0])->{"EQUATION"}->[0];
2135                            if (defined($equation)) {
2136                                    for (my $i=0; $i < @array; $i++) {
2137                                            if (CORE::index($equation,$array[$i]) > 0) {
2138                                                    push(@objectives,$array[$i]);
2139                                            }
2140                                    }
2141                            }
2142                    }
2143                    for (my $i=0; $i < @objectives; $i++) {
2144                            $self->find_minimal_pathways($media,$objectives[$i]);
2145                    }
2146                    return;
2147            } elsif ($objective eq "ENERGY") {
2148                    $objectivestring = "MAX;FLUX;rxn00062;c;1";
2149            } elsif ($objective =~ m/cpd\d\d\d\d\d/) {
2150                    if ($objective =~ m/\[(\w)\]/) {
2151                            $objectivestring = "MIN;DRAIN_FLUX;".$objective.";".$1.";1";
2152                            $additionalexchange .= ";".$objective."[".$1."]:-100:0";
2153                    } else {
2154                            $objectivestring = "MIN;DRAIN_FLUX;".$objective.";c;1";
2155                            $additionalexchange .= ";".$objective."[c]:-100:0";
2156                    }
2157            } elsif ($objective =~ m/(rxn\d\d\d\d\d)/) {
2158                    my ($Reactants,$Products) = $self->figmodel()->GetReactionSubstrateData($objective);
2159                    for (my $i=0; $i < @{$Products};$i++) {
2160                            my $temp = $Products->[$i]->{"DATABASE"}->[0];
2161                            if ($additionalexchange !~ m/$temp/) {
2162                                    #$additionalexchange .= ";".$temp."[c]:-100:0";
2163                            }
2164                    }
2165                    for (my $i=0; $i < @{$Reactants};$i++) {
2166                            print $Reactants->[$i]->{"DATABASE"}->[0]." started\n";
2167                            $self->find_minimal_pathways($media,$Reactants->[$i]->{"DATABASE"}->[0],$additionalexchange);
2168                            print $Reactants->[$i]->{"DATABASE"}->[0]." done\n";
2169                    }
2170                    return;
2171            }
2172    
2173            #Adding additional drains
2174            if (($objective eq "cpd15665" || $objective eq "cpd15667" || $objective eq "cpd15668" || $objective eq "cpd15669") && $additionalexchange !~ m/cpd15666/) {
2175                    $additionalexchange .= ";cpd15666[c]:0:100";
2176            } elsif ($objective eq "cpd11493" && $additionalexchange !~ m/cpd12370/) {
2177                    $additionalexchange .= ";cpd12370[c]:0:100";
2178            } elsif ($objective eq "cpd00166" && $additionalexchange !~ m/cpd01997/) {
2179                    $additionalexchange .= ";cpd01997[c]:0:100;cpd03422[c]:0:100";
2180            }
2181    
2182            #Running MFAToolkit
2183            my $filename = $self->figmodel()->filename();
2184            my $command;
2185            if (defined($AllReversible) && $AllReversible == 1) {
2186                    $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());
2187            } else {
2188                    $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());
2189            }
2190          system($command);          system($command);
2191          #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\"");  
2192            #Loading problem report
2193            my $results = $self->figmodel()->LoadProblemReport($filename);
2194            #Clearing output
2195            $self->figmodel()->clearing_output($filename,"MinimalPathways-".$media."-".$self->id()."-".$objective.".txt");
2196            if (!defined($results)) {
2197                    print STDERR $objective." pathway results not found!\n";
2198                    return;
2199            }
2200    
2201            #Parsing output
2202            my @Array;
2203            my $row = $results->get_row(1);
2204            if (defined($row->{"Notes"}->[0])) {
2205                    $_ = $row->{"Notes"}->[0];
2206                    @Array = /\d+:([^\|]+)\|/g;
2207            }
2208    
2209            #Writing output to file
2210            $self->figmodel()->database()->print_array_to_file($self->directory()."MinimalPathways-".$media."-".$objective."-".$self->id()."-".$AllReversible."-".$self->selected_version().".txt",[join("|",@Array)]);
2211  }  }
2212    
2213  =head3 find_minimal_pathways  =head3 find_minimal_pathways
# Line 1911  Line 2216 
2216  Description:  Description:
2217          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
2218  =cut  =cut
2219  sub find_minimal_pathways {  sub find_minimal_pathways_two {
2220          my ($self,$media,$objective,$solutionnum) = @_;          my ($self,$media,$objective,$solutionnum,$AllReversible,$additionalexchange) = @_;
2221    
2222          #Setting default media          #Setting default media
2223          if (!defined($media)) {          if (!defined($media)) {
# Line 1924  Line 2229 
2229                  $solutionnum = "5";                  $solutionnum = "5";
2230          }          }
2231    
2232            #Setting additional exchange fluxes
2233            if (!defined($additionalexchange) || length($additionalexchange) == 0) {
2234                    if ($self->id() eq "iAF1260") {
2235                            $additionalexchange = "cpd03422[c]:-100:100;cpd01997[c]:-100:100;cpd11416[c]:-100:0;cpd15378[c]:-100:0;cpd15486[c]:-100:0";
2236                    } else {
2237                            $additionalexchange = $self->figmodel()->config("default exchange fluxes")->[0];
2238                    }
2239            }
2240    
2241          #Translating objective          #Translating objective
2242          my $objectivestring;          my $objectivestring;
2243          if ($objective eq "ALL") {          if ($objective eq "ALL") {
# Line 1944  Line 2258 
2258                          }                          }
2259                  }                  }
2260                  for (my $i=0; $i < @objectives; $i++) {                  for (my $i=0; $i < @objectives; $i++) {
2261                          $self->find_minimal_pathways($media,$objectives[$i])                          $self->find_minimal_pathways($media,$objectives[$i]);
2262                  }                  }
2263                    return;
2264          } elsif ($objective eq "ENERGY") {          } elsif ($objective eq "ENERGY") {
2265                  $objectivestring = "MAX;FLUX;rxn00062;c;1";                  $objectivestring = "MAX;FLUX;rxn00062;c;1";
2266          } elsif ($objective =~ m/cpd\d\d\d\d\d/) {          } elsif ($objective =~ m/cpd\d\d\d\d\d/) {
2267                    if ($objective =~ m/\[(\w)\]/) {
2268                            $objectivestring = "MIN;DRAIN_FLUX;".$objective.";".$1.";1";
2269                            $additionalexchange .= ";".$objective."[".$1."]:-100:0";
2270                    } else {
2271                  $objectivestring = "MIN;DRAIN_FLUX;".$objective.";c;1";                  $objectivestring = "MIN;DRAIN_FLUX;".$objective.";c;1";
2272                            $additionalexchange .= ";".$objective."[c]:-100:0";
2273                    }
2274            } elsif ($objective =~ m/(rxn\d\d\d\d\d)/) {
2275                    my ($Reactants,$Products) = $self->figmodel()->GetReactionSubstrateData($objective);
2276                    for (my $i=0; $i < @{$Products};$i++) {
2277                            my $temp = $Products->[$i]->{"DATABASE"}->[0];
2278                            if ($additionalexchange !~ m/$temp/) {
2279                                    #$additionalexchange .= ";".$temp."[c]:-100:0";
2280                            }
2281                    }
2282                    for (my $i=0; $i < @{$Reactants};$i++) {
2283                            print $Reactants->[$i]->{"DATABASE"}->[0]." started\n";
2284                            $self->find_minimal_pathways($media,$Reactants->[$i]->{"DATABASE"}->[0],$additionalexchange);
2285                            print $Reactants->[$i]->{"DATABASE"}->[0]." done\n";
2286                    }
2287                    return;
2288          }          }
2289    
2290          #Setting additional exchange fluxes          #Adding additional drains
2291          my $additionalexchange = $self->config("default exchange fluxes")->[0];          if (($objective eq "cpd15665" || $objective eq "cpd15667" || $objective eq "cpd15668" || $objective eq "cpd15669") && $additionalexchange !~ m/cpd15666/) {
         if ($objective eq "cpd15665" || $objective eq "cpd15667" || $objective eq "cpd15668" || $objective eq "cpd15669") {  
2292                  $additionalexchange .= ";cpd15666[c]:0:100";                  $additionalexchange .= ";cpd15666[c]:0:100";
2293          } elsif ($objective eq "cpd11493") {          } elsif ($objective eq "cpd11493" && $additionalexchange !~ m/cpd12370/) {
2294                  $additionalexchange .= ";cpd12370[c]:0:100";                  $additionalexchange .= ";cpd12370[c]:0:100";
2295          } elsif ($objective eq "cpd00166") {          } elsif ($objective eq "cpd00166" && $additionalexchange !~ m/cpd01997/) {
2296                  $additionalexchange .= ";cpd01997[c]:0:100;cpd03422[c]:0:100";                  $additionalexchange .= ";cpd01997[c]:0:100;cpd03422[c]:0:100";
2297          }          }
2298    
2299          #Running MFAToolkit          #Running MFAToolkit
2300          my $filename = $self->figmodel()->filename();          my $filename = $self->figmodel()->filename();
2301          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;
2302            if (defined($AllReversible) && $AllReversible == 1) {
2303                    $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());
2304            } else {
2305                    $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());
2306            }
2307            print $command."\n";
2308          system($command);          system($command);
2309    
2310          #Loading problem report          #Loading problem report
# Line 1972  Line 2312 
2312          #Clearing output          #Clearing output
2313          $self->figmodel()->clearing_output($filename,"MinimalPathways-".$media."-".$self->id()."-".$objective.".txt");          $self->figmodel()->clearing_output($filename,"MinimalPathways-".$media."-".$self->id()."-".$objective.".txt");
2314          if (!defined($results)) {          if (!defined($results)) {
2315                    print STDERR $objective." pathway results not found!\n";
2316                  return;                  return;
2317          }          }
2318    
# Line 1983  Line 2324 
2324                  @Array = /\d+:([^\|]+)\|/g;                  @Array = /\d+:([^\|]+)\|/g;
2325          }          }
2326    
2327          # Storing data in a figmodel table          #Writing output to file
2328          my $TableObject;          $self->figmodel()->database()->print_array_to_file($self->directory()."MinimalPathways-".$media."-".$objective."-".$self->id()."-".$AllReversible."-".$self->selected_version().".txt",[join("|",@Array)]);
2329          if (-e $self->directory()."MinimalPathways-".$media."-".$self->id().$self->selected_version().".txt") {  }
2330                  $TableObject->load_table($self->directory()."MinimalPathways-".$media."-".$self->id().$self->selected_version().".txt",";","|",0,["OBJECTIVE"]);  
2331          } else {  sub combine_minimal_pathways {
2332                  $TableObject = FIGMODELTable->new(["OBJECTIVE","REACTIONS"],$self->directory()."MinimalPathways-".$media."-".$self->id().$self->selected_version().".txt",["OBJECTIVE"],";","|",undef);          my ($self) = @_;
2333          }  
2334          my $tablerow = $TableObject->get_row_by_key($objective,"OBJECTIVE",1);          my $tbl;
2335          push(@{$tablerow->{"REACTIONS"}},@Array);          if (-e $self->directory()."MinimalPathwayTable-".$self->id().$self->selected_version().".tbl") {
2336          $TableObject->save();                  $tbl = FIGMODELTable::load_table($self->directory()."MinimalPathwayTable-".$self->id().$self->selected_version().".tbl",";","|",0,["Objective","Media","Reversible"]);
2337            } else {
2338                    $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"],";","|");
2339            }
2340            my @files = glob($self->directory()."MinimalPathways-*");
2341            for (my $i=0; $i < @files;$i++) {
2342                    if ($files[$i] =~ m/MinimalPathways\-(\S+)\-(cpd\d\d\d\d\d)\-(\w+)\-(\d)\-/ || $files[$i] =~ m/MinimalPathways\-(\S+)\-(ENERGY)\-(\w+)\-(\d)\-/) {
2343                            my $reactions = $self->figmodel()->database()->load_single_column_file($files[$i],"");
2344                            if (defined($reactions) && @{$reactions} > 0 && length($reactions->[0]) > 0) {
2345                                    my $newrow = {"Objective"=>[$2],"Media"=>[$1],"Reversible"=>[$4]};
2346                                    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");
2347                                    if (!defined($row)) {
2348                                            $row = $tbl->add_row($newrow);
2349                                    }
2350                                    $row->{Reactions} = $self->figmodel()->database()->load_single_column_file($files[$i],"");
2351                                    delete($row->{"Shortest path"});
2352                                    delete($row->{"Number of essentials"});
2353                                    delete($row->{"Essentials"});
2354                                    delete($row->{"Length"});
2355                                    for (my $j=0; $j < @{$row->{Reactions}}; $j++) {
2356                                            my @array = split(/,/,$row->{Reactions}->[$j]);
2357                                            $row->{"Length"}->[$j] = @array;
2358                                            if (!defined($row->{"Shortest path"}->[0]) || $row->{"Length"}->[$j] < $row->{"Shortest path"}->[0]) {
2359                                                    $row->{"Shortest path"}->[0] = $row->{"Length"}->[$j];
2360                                            }
2361                                            $row->{"Number of essentials"}->[0] = 0;
2362                                            for (my $k=0; $k < @array;$k++) {
2363                                                    if ($array[$k] =~ m/(rxn\d\d\d\d\d)/) {
2364                                                            my $class = $self->get_reaction_class($1,1);
2365                                                            my $temp = $row->{Media}->[0].":Essential";
2366                                                            if ($class =~ m/$temp/) {
2367                                                                    $row->{"Number of essentials"}->[$j]++;
2368                                                                    if (!defined($row->{"Essentials"}->[$j]) && length($row->{"Essentials"}->[$j]) > 0) {
2369                                                                            $row->{"Essentials"}->[$j] = $array[$k];
2370                                                                    } else {
2371                                                                            $row->{"Essentials"}->[$j] .= ",".$array[$k];
2372                                                                    }
2373                                                            }
2374                                                    }
2375                                            }
2376                                    }
2377                            }
2378                    }
2379            }
2380            $tbl->save();
2381  }  }
2382    
2383  =head3 calculate_growth  =head3 calculate_growth
# Line 2036  Line 2421 
2421          7.) Dead: these reactions are disconnected from the network.          7.) Dead: these reactions are disconnected from the network.
2422  =cut  =cut
2423  sub classify_model_reactions {  sub classify_model_reactions {
2424          my ($self,$Media) = @_;          my ($self,$Media,$SaveChanges) = @_;
2425    
2426          #Getting unique file for printing model output          #Getting unique file for printing model output
2427          my $UniqueFilename = $self->figmodel()->filename();          my $UniqueFilename = $self->figmodel()->filename();
# Line 2123  Line 2508 
2508                                  $CpdRow->{MEDIA}->[$index] = $Media;                                  $CpdRow->{MEDIA}->[$index] = $Media;
2509                          }                          }
2510                  }                  }
2511                    if (!defined($SaveChanges) || $SaveChanges == 1) {
2512                  $cpdclasstable->save();                  $cpdclasstable->save();
2513          }          }
2514            }
2515          if (defined($ReactionTB)) {          if (defined($ReactionTB)) {
2516                  for (my $i=0; $i < $ReactionTB->size(); $i++) {                  for (my $i=0; $i < $ReactionTB->size(); $i++) {
2517                          my $Row = $ReactionTB->get_row($i);                          my $Row = $ReactionTB->get_row($i);
# Line 2179  Line 2566 
2566                                  $RxnRow->{MEDIA}->[$index] = $Media;                                  $RxnRow->{MEDIA}->[$index] = $Media;
2567                          }                          }
2568                  }                  }
2569                    if (!defined($SaveChanges) || $SaveChanges == 1) {
2570                  $rxnclasstable->save();                  $rxnclasstable->save();
2571          }          }
2572            }
2573          return ($rxnclasstable,$cpdclasstable);          return ($rxnclasstable,$cpdclasstable);
2574  }  }
2575    
# Line 2212  Line 2601 
2601    
2602          #Running simulations          #Running simulations
2603          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";  
2604          #Parsing the results          #Parsing the results
2605          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);
2606          if (!defined($Results)) {          if (!defined($Results)) {
# Line 2619  Line 3007 
3007                                          if (length($GapFillingRunSpecs) > 0) {                                          if (length($GapFillingRunSpecs) > 0) {
3008                                                  $GapFillingRunSpecs .= ";";                                                  $GapFillingRunSpecs .= ";";
3009                                          }                                          }
3010                                          $GapFillingRunSpecs .= $HeadingDataArray[2].":".$HeadingDataArray[1].".txt:".$HeadingDataArray[3];                                          $GapFillingRunSpecs .= $HeadingDataArray[2].":".$HeadingDataArray[1].":".$HeadingDataArray[3];
3011                                  } else {                                  } else {
3012                                          $SolutionExistedCount++;                                          $SolutionExistedCount++;
3013                                  }                                  }
# Line 2644  Line 3032 
3032          my $SolutionsFound = 0;          my $SolutionsFound = 0;
3033          my $GapFillingArray;          my $GapFillingArray;
3034          push(@{$GapFillingArray},split(/;/,$GapFillingRunSpecs));          push(@{$GapFillingArray},split(/;/,$GapFillingRunSpecs));
3035          $self->datagapfill($GapFillingArray);          my $GapFillingResults = $self->datagapfill($GapFillingArray,"GFS");
3036            if (defined($GapFillingResults)) {
3037                    $SolutionsFound = 1;
3038            }
3039    
3040          if (defined($RescuedPreviousResults) && @{$RescuedPreviousResults} > 0) {          if (defined($RescuedPreviousResults) && @{$RescuedPreviousResults} > 0) {
3041                  #Printing previous solutions to GFS file                  #Printing previous solutions to GFS file
# Line 2667  Line 3058 
3058          return $self->success();          return $self->success();
3059  }  }
3060    
3061    =head3 SolutionReconciliation
3062    Definition:
3063            FIGMODELmodel->SolutionReconciliation();
3064    Description:
3065            This is a wrapper for running the solution reconciliation algorithm on any model in the database.
3066            The algorithm performs a reconciliation of any gap filling solutions to identify the combination of solutions that results in the optimal model.
3067            This function prints out one output file in the Model directory: ReconciliationOutput.txt: this is a summary of the results of the reconciliation analysis
3068    =cut
3069    
3070    sub SolutionReconciliation {
3071            my ($self,$GapFill,$Stage) = @_;
3072    
3073            #Setting the output filenames
3074            my $OutputFilename;
3075            my $OutputFilenameTwo;
3076            if ($GapFill == 1) {
3077                    $OutputFilename = $self->directory().$self->id().$self->selected_version()."-GFReconciliation.txt";
3078                    $OutputFilenameTwo = $self->directory().$self->id().$self->selected_version()."-GFSRS.txt";
3079            } else {
3080                    $OutputFilename = $self->directory().$self->id().$self->selected_version()."-GGReconciliation.txt";
3081                    $OutputFilenameTwo = $self->directory().$self->id().$self->selected_version()."-GGSRS.txt";
3082            }
3083    
3084            #In stage one, we run the reconciliation and create a test file to check combined solution performance
3085            if (!defined($Stage) || $Stage == 1) {
3086                    my $GrowMatchTable = $self->figmodel()->database()->LockDBTable("GROWMATCH TABLE");
3087                    my $Row = $GrowMatchTable->get_row_by_key($self->genome(),"ORGANISM",1);
3088                    $Row->{"GF RECONCILATION TIMING"}->[0] = time()."-";
3089                    $GrowMatchTable->save();
3090                    $self->figmodel()->database()->UnlockDBTable("GROWMATCH TABLE");
3091    
3092                    #Getting a unique filename
3093                    my $UniqueFilename = $self->figmodel()->filename();
3094    
3095                    #Copying over the necessary files
3096                    if ($GapFill == 1) {
3097                            if (!-e $self->directory().$self->id().$self->selected_version()."-GFEM.txt") {
3098                                    print STDERR "FIGMODEL:SolutionReconciliation:".$self->directory().$self->id().$self->selected_version()."-GFEM.txt file not found. Could not reconcile!";
3099                                    return 0;
3100                            }
3101                            if (!-e $self->directory().$self->id().$self->selected_version()."-OPEM.txt") {
3102                                    print STDERR "FIGMODEL:SolutionReconciliation:".$self->directory().$self->id().$self->selected_version()."-OPEM.txt file not found. Could not reconcile!";
3103                                    return 0;
3104                            }
3105                            system("cp ".$self->directory().$self->id().$self->selected_version()."-GFEM.txt ".$self->figmodel()->config("MFAToolkit input files")->[0].$UniqueFilename."-GFEM.txt");
3106                            system("cp ".$self->directory().$self->id().$self->selected_version()."-OPEM.txt ".$self->figmodel()->config("MFAToolkit input files")->[0].$UniqueFilename."-OPEM.txt");
3107                            #Backing up and deleting the existing reconciliation file
3108                            if (-e $OutputFilename) {
3109                                    system("cp ".$OutputFilename." ".$self->directory().$self->id().$self->selected_version()."-OldGFReconciliation.txt");
3110                                    unlink($OutputFilename);
3111                            }
3112                    } else {
3113                            if (!-e $self->directory().$self->id().$self->selected_version()."-GGEM.txt") {
3114                                    print STDERR "FIGMODEL:SolutionReconciliation:".$self->directory().$self->id().$self->selected_version()."-GGEM.txt file not found. Could not reconcile!";
3115                                    return 0;
3116                            }
3117                            if (!-e $self->directory().$self->id().$self->selected_version()."-GGOPEM.txt") {
3118                                    print STDERR "FIGMODEL:SolutionReconciliation:".$self->directory().$self->id().$self->selected_version()."-GGOPEM.txt file not found. Could not reconcile!";
3119                                    return 0;
3120                            }
3121                            system("cp ".$self->directory().$self->id().$self->selected_version()."-GGEM.txt ".$self->figmodel()->config("MFAToolkit input files")->[0].$UniqueFilename."-GGEM.txt");
3122                            system("cp ".$self->directory().$self->id().$self->selected_version()."-GGOPEM.txt ".$self->figmodel()->config("MFAToolkit input files")->[0].$UniqueFilename."-OPEM.txt");
3123                            #Backing up and deleting the existing reconciliation file
3124                            if (-e $OutputFilename) {
3125                                    system("cp ".$OutputFilename." ".$self->directory().$self->id().$self->selected_version()."-OldGGReconciliation.txt");
3126                                    unlink($OutputFilename);
3127                            }
3128                    }
3129    
3130                    #Running the reconciliation
3131                    system($self->figmodel()->GenerateMFAToolkitCommandLineCall($UniqueFilename,$self->id(),"NONE",["SolutionReconciliation"],{"Solution data for model optimization" => $UniqueFilename},"Reconciliation".$UniqueFilename.".log",undef,$self->selected_version()));
3132                    $GrowMatchTable = $self->figmodel()->database()->LockDBTable("GROWMATCH TABLE");
3133                    $Row = $GrowMatchTable->get_row_by_key($self->genome(),"ORGANISM",1);
3134                    $Row->{"GF RECONCILATION TIMING"}->[0] .= time();
3135                    $GrowMatchTable->save();
3136                    $self->figmodel()->database()->UnlockDBTable("GROWMATCH TABLE");
3137    
3138                    #Loading the problem report from the reconciliation run
3139                    my $ReconciliatonOutput = $self->figmodel()->LoadProblemReport($UniqueFilename);
3140                    print $UniqueFilename."\n";
3141                    #Clearing output files
3142                    $self->figmodel()->clearing_output($UniqueFilename,"Reconciliation".$UniqueFilename.".log");
3143                    $ReconciliatonOutput->save("/home/chenry/Test.txt");
3144    
3145                    #Checking the a problem report was found and was loaded
3146                    if (!defined($ReconciliatonOutput) || $ReconciliatonOutput->size() < 1 || !defined($ReconciliatonOutput->get_row(0)->{"Notes"}->[0])) {
3147                            print STDERR "FIGMODEL:SolutionReconciliation: MFAToolkit output from SolutionReconciliation of ".$self->id()." not found!\n\n";
3148                            return 0;
3149                    }
3150    
3151                    #Processing the solutions
3152                    my $SolutionCount = 0;
3153                    my $ReactionSetHash;
3154                    my $SingleReactionHash;
3155                    my $ReactionDataHash;
3156                    for (my $n=0; $n < $ReconciliatonOutput->size(); $n++) {
3157                            if (defined($ReconciliatonOutput->get_row($n)->{"Notes"}->[0]) && $ReconciliatonOutput->get_row($n)->{"Notes"}->[0] =~ m/^Recursive\sMILP\s([^;]+)/) {
3158                                    #Breaking up the solution into reaction sets
3159                                    my @ReactionSets = split(/\|/,$1);
3160                                    #Creating reaction lists for each set
3161                                    my $SolutionHash;
3162                                    for (my $i=0; $i < @ReactionSets; $i++) {
3163                                            if (length($ReactionSets[$i]) > 0) {
3164                                                    my @Alternatives = split(/:/,$ReactionSets[$i]);
3165                                                    for (my $j=1; $j < @Alternatives; $j++) {
3166                                                            if (length($Alternatives[$j]) > 0) {
3167                                                                    push(@{$SolutionHash->{$Alternatives[$j]}},$Alternatives[0]);
3168                                                            }
3169                                                    }
3170                                                    if (@Alternatives == 1) {
3171                                                            $SingleReactionHash->{$Alternatives[0]}->{$SolutionCount} = 1;
3172                                                            if (!defined($SingleReactionHash->{$Alternatives[0]}->{"COUNT"})) {
3173                                                                    $SingleReactionHash->{$Alternatives[0]}->{"COUNT"} = 0;
3174                                                            }
3175                                                            $SingleReactionHash->{$Alternatives[0]}->{"COUNT"}++;
3176                                                    }
3177                                            }
3178                                    }
3179                                    #Identifying reactions sets and storing the sets in the reactions set hash
3180                                    foreach my $Solution (keys(%{$SolutionHash})) {
3181                                            my $SetKey = join(",",sort(@{$SolutionHash->{$Solution}}));
3182                                            if (!defined($ReactionSetHash->{$SetKey}->{$SetKey}->{$SolutionCount})) {
3183                                                    $ReactionSetHash->{$SetKey}->{$SetKey}->{$SolutionCount} = 1;
3184                                                    if (!defined($ReactionSetHash->{$SetKey}->{$SetKey}->{"COUNT"})) {
3185                                                            $ReactionSetHash->{$SetKey}->{$SetKey}->{"COUNT"} = 0;
3186                                                    }
3187                                                    $ReactionSetHash->{$SetKey}->{$SetKey}->{"COUNT"}++;
3188                                            }
3189                                            $ReactionSetHash->{$SetKey}->{$Solution}->{$SolutionCount} = 1;
3190                                            if (!defined($ReactionSetHash->{$SetKey}->{$Solution}->{"COUNT"})) {
3191                                                    $ReactionSetHash->{$SetKey}->{$Solution}->{"COUNT"} = 0;
3192                                            }
3193                                            $ReactionSetHash->{$SetKey}->{$Solution}->{"COUNT"}++;
3194                                    }
3195                                    $SolutionCount++;
3196                            }
3197                    }
3198    
3199                    #Handling the scenario where no solutions were found
3200                    if ($SolutionCount == 0) {
3201                            print STDERR "FIGMODEL:SolutionReconciliation: Reconciliation unsuccessful. No solution found.\n\n";
3202                            return 0;
3203                    }
3204    
3205                    #Printing results without solution performance figures. Also printing solution test file
3206                    open (RECONCILIATION, ">$OutputFilename");
3207                    #Printing the file heading
3208                    print RECONCILIATION "DATABASE;DEFINITION;REVERSIBLITY;DELTAG;DIRECTION;NUMBER OF SOLUTIONS";
3209                    for (my $i=0; $i < $SolutionCount; $i++) {
3210                            print RECONCILIATION ";Solution ".$i;
3211                    }
3212                    print RECONCILIATION "\n";
3213                    #Printing the singlet reactions first
3214                    my $Solutions;
3215                    print RECONCILIATION "SINGLET REACTIONS\n";
3216                    my @SingletReactions = keys(%{$SingleReactionHash});
3217                    for (my $j=0; $j < $SolutionCount; $j++) {
3218                            $Solutions->[$j]->{"BASE"} = $j;
3219                    }
3220                    for (my $i=0; $i < @SingletReactions; $i++) {
3221                            my $ReactionData;
3222                            if (defined($ReactionDataHash->{$SingletReactions[$i]})) {
3223                                    $ReactionData = $ReactionDataHash->{$SingletReactions[$i]};
3224                            } else {
3225                                    my $Direction = substr($SingletReactions[$i],0,1);
3226                                    if ($Direction eq "+") {
3227                                            $Direction = "=>";
3228                                    } else {
3229                                            $Direction = "<=";
3230                                    }
3231                                    my $Reaction = substr($SingletReactions[$i],1);
3232                                    $ReactionData = FIGMODELObject->load($self->figmodel()->config("reaction directory")->[0].$Reaction,"\t");
3233                                    $ReactionData->{"DIRECTIONS"}->[0] = $Direction;
3234                                    $ReactionData->{"REACTIONS"}->[0] = $Reaction;
3235                                    if (!defined($ReactionData->{"DEFINITION"}->[0])) {
3236                                            $ReactionData->{"DEFINITION"}->[0] = "UNKNOWN";
3237                                    }
3238                                    if (!defined($ReactionData->{"THERMODYNAMIC REVERSIBILITY"}->[0])) {
3239                                            $ReactionData->{"THERMODYNAMIC REVERSIBILITY"}->[0] = "UNKNOWN";
3240                                    }
3241                                    if (!defined($ReactionData->{"DELTAG"}->[0])) {
3242                                            $ReactionData->{"DELTAG"}->[0] = "UNKNOWN";
3243                                    }
3244                                    $ReactionDataHash->{$SingletReactions[$i]} = $ReactionData;
3245                            }
3246                            print RECONCILIATION $ReactionData->{"REACTIONS"}->[0].";".$ReactionData->{"DEFINITION"}->[0].";".$ReactionData->{"THERMODYNAMIC REVERSIBILITY"}->[0].";".$ReactionData->{"DELTAG"}->[0].";".$ReactionData->{"DIRECTIONS"}->[0].";".$SingleReactionHash->{$SingletReactions[$i]}->{"COUNT"};
3247                            for (my $j=0; $j < $SolutionCount; $j++) {
3248                                    print RECONCILIATION ";";
3249                                    if (defined($SingleReactionHash->{$SingletReactions[$i]}->{$j})) {
3250                                            $Solutions->[$j]->{$SingletReactions[$i]} = 1;
3251                                            $Solutions->[$j]->{"BASE"} = $j;
3252                                            print RECONCILIATION "|".$j."|";
3253                                    }
3254                            }
3255                            print RECONCILIATION "\n";
3256                    }
3257                    #Printing the reaction sets with alternatives
3258                    print RECONCILIATION "Reaction sets with alternatives\n";
3259                    my @ReactionSets = keys(%{$ReactionSetHash});
3260                    foreach my $ReactionSet (@ReactionSets) {
3261                            my $NewSolutions;
3262                            my $BaseReactions;
3263                            my $AltList = [$ReactionSet];
3264                            push(@{$AltList},keys(%{$ReactionSetHash->{$ReactionSet}}));
3265                            for (my $j=0; $j < @{$AltList}; $j++) {
3266                                    my $CurrentNewSolutions;
3267                                    my $Index;
3268                                    if ($j == 0) {
3269                                            print RECONCILIATION "NEW SET\n";
3270                                    } elsif ($AltList->[$j] ne $ReactionSet) {
3271                                            print RECONCILIATION "ALTERNATIVE SET\n";
3272                                            #For each base solution in which this set is represented, we copy the base solution to the new solution
3273                                            my $NewSolutionCount = 0;
3274                                            for (my $k=0; $k < $SolutionCount; $k++) {
3275                                                    if (defined($ReactionSetHash->{$ReactionSet}->{$AltList->[$j]}->{$k})) {
3276                                                            if (defined($Solutions)) {
3277                                                                    $Index->{$k} = @{$Solutions} + $NewSolutionCount;
3278                                                            } else {
3279                                                                    $Index->{$k} = $NewSolutionCount;
3280                                                            }
3281                                                            if (defined($NewSolutions) && @{$NewSolutions} > 0) {
3282                                                                    $Index->{$k} += @{$NewSolutions};
3283                                                            }
3284                                                            $CurrentNewSolutions->[$NewSolutionCount] = {};
3285                                                            foreach my $Reaction (keys(%{$Solutions->[$k]})) {
3286                                                                    $CurrentNewSolutions->[$NewSolutionCount]->{$Reaction} = $Solutions->[$k]->{$Reaction};
3287                                                            }
3288                                                            $NewSolutionCount++;
3289                                                    }
3290                                            }
3291                                    }
3292                                    if ($j == 0 || $AltList->[$j] ne $ReactionSet) {
3293                                            my @SingletReactions = split(/,/,$AltList->[$j]);
3294                                            for (my $i=0; $i < @SingletReactions; $i++) {
3295                                                    #Adding base reactions to base solutions and set reactions the new solutions
3296                                                    if ($j == 0) {
3297                                                            push(@{$BaseReactions},$SingletReactions[$i]);
3298                                                    } else {
3299                                                            for (my $k=0; $k < @{$CurrentNewSolutions}; $k++) {
3300                                                                    $CurrentNewSolutions->[$k]->{$SingletReactions[$i]} = 1;
3301                                                            }
3302                                                    }
3303                                                    #Getting reaction data and printing reaction in output file
3304                                                    my $ReactionData;
3305                                                    if (defined($ReactionDataHash->{$SingletReactions[$i]})) {
3306                                                            $ReactionData = $ReactionDataHash->{$SingletReactions[$i]};
3307                                                    } else {
3308                                                            my $Direction = substr($SingletReactions[$i],0,1);
3309                                                            if ($Direction eq "+") {
3310                                                                    $Direction = "=>";
3311                                                            } else {
3312                                                                    $Direction = "<=";
3313                                                            }
3314                                                            my $Reaction = substr($SingletReactions[$i],1);
3315                                                            $ReactionData = FIGMODELObject->load($self->figmodel()->config("reaction directory")->[0].$Reaction,"\t");
3316                                                            $ReactionData->{"DIRECTIONS"}->[0] = $Direction;
3317                                                            $ReactionData->{"REACTIONS"}->[0] = $Reaction;
3318                                                            if (!defined($ReactionData->{"DEFINITION"}->[0])) {
3319                                                                    $ReactionData->{"DEFINITION"}->[0] = "UNKNOWN";
3320                                                            }
3321                                                            if (!defined($ReactionData->{"THERMODYNAMIC REVERSIBILITY"}->[0])) {
3322                                                                    $ReactionData->{"THERMODYNAMIC REVERSIBILITY"}->[0] = "UNKNOWN";
3323                                                            }
3324                                                            if (!defined($ReactionData->{"DELTAG"}->[0])) {
3325                                                                    $ReactionData->{"DELTAG"}->[0] = "UNKNOWN";
3326                                                            }
3327                                                            $ReactionDataHash->{$SingletReactions[$i]} = $ReactionData;
3328                                                    }
3329                                                    print RECONCILIATION $ReactionData->{"REACTIONS"}->[0].";".$ReactionData->{"DEFINITION"}->[0].";".$ReactionData->{"THERMODYNAMIC REVERSIBILITY"}->[0].";".$ReactionData->{"DELTAG"}->[0].";".$ReactionData->{"DIRECTIONS"}->[0].";".$ReactionSetHash->{$ReactionSet}->{$AltList->[$j]}->{"COUNT"};
3330                                                    for (my $k=0; $k < $SolutionCount; $k++) {
3331                                                            print RECONCILIATION ";";
3332                                                            if (defined($ReactionSetHash->{$ReactionSet}->{$AltList->[$j]}->{$k})) {
3333                                                                    if ($j == 0) {
3334                                                                            print RECONCILIATION "|".$k."|";
3335                                                                    } else {
3336                                                                            print RECONCILIATION "|".$Index->{$k}."|";
3337                                                                    }
3338                                                            }
3339                                                    }
3340                                                    print RECONCILIATION "\n";
3341                                            }
3342                                            #Adding the current new solutions to the new solutions array
3343                                            if (defined($CurrentNewSolutions) && @{$CurrentNewSolutions} > 0) {
3344                                                    push(@{$NewSolutions},@{$CurrentNewSolutions});
3345                                            }
3346                                    }
3347                            }
3348                            #Adding the base reactions to all existing solutions
3349                            for (my $j=0; $j < @{$Solutions}; $j++) {
3350                                    if (defined($ReactionSetHash->{$ReactionSet}->{$ReactionSet}->{$Solutions->[$j]->{"BASE"}})) {
3351                                            foreach my $SingleReaction (@{$BaseReactions}) {
3352                                                    $Solutions->[$j]->{$SingleReaction} = 1;
3353                                            }
3354                                    }
3355                            }
3356                            #Adding the new solutions to the set of existing solutions
3357                            push(@{$Solutions},@{$NewSolutions});
3358                    }
3359                    close(RECONCILIATION);
3360                    #Now printing a file that defines all of the solutions in a format the testsolutions function understands
3361                    open (RECONCILIATION, ">$OutputFilenameTwo");
3362                    print RECONCILIATION "Experiment;Solution index;Solution cost;Solution reactions\n";
3363                    for (my $i=0; $i < @{$Solutions}; $i++) {
3364                            delete($Solutions->[$i]->{"BASE"});
3365                            print RECONCILIATION "SR".$i.";".$i.";10;".join(",",keys(%{$Solutions->[$i]}))."\n";
3366                    }
3367                    close(RECONCILIATION);
3368    
3369                    $GrowMatchTable = $self->figmodel()->database()->LockDBTable("GROWMATCH TABLE");
3370                    $Row = $GrowMatchTable->get_row_by_key($self->genome(),"ORGANISM",1);
3371                    $Row->{"GF RECON TESTING TIMING"}->[0] = time()."-";
3372                    $Row->{"GF RECON SOLUTIONS"}->[0] = @{$Solutions};
3373                    $GrowMatchTable->save();
3374                    $self->figmodel()->database()->UnlockDBTable("GROWMATCH TABLE");
3375    
3376                    #Scheduling the solution testing
3377                    if ($GapFill == 1) {
3378                            system($self->figmodel()->config("scheduler executable")->[0]." \"add:testsolutions?".$self->id().$self->selected_version()."?-1?GFSR:BACK:fast:QSUB\"");
3379                    } else {
3380                            system($self->figmodel()->config("scheduler executable")->[0]." \"add:testsolutions?".$self->id().$self->selected_version()."?-1?GGSR:BACK:fast:QSUB\"");
3381                    }
3382            } else {
3383                    #Reading in the solution testing results
3384                    my $Data;
3385                    if ($GapFill == 1) {
3386                            $Data = $self->figmodel()->database()->load_single_column_file($self->directory().$self->id().$self->selected_version()."-GFSREM.txt","");
3387                    } else {
3388                            $Data = $self->figmodel()->database()->load_single_column_file($self->directory().$self->id().$self->selected_version()."-GGSREM.txt","");
3389                    }
3390    
3391                    #Reading in the preliminate reconciliation report
3392                    my $OutputData = $self->figmodel()->database()->load_single_column_file($OutputFilename,"");
3393                    #Replacing the file tags with actual performance data
3394                    my $Count = 0;
3395                    for (my $i=0; $i < @{$Data}; $i++) {
3396                            if ($Data->[$i] =~ m/^SR(\d+);.+;(\d+\/\d+);/) {
3397                                    my $Index = $1;
3398                                    my $Performance = $Index."/".$2;
3399                                    for (my $j=0; $j < @{$OutputData}; $j++) {
3400                                            $OutputData->[$j] =~ s/\|$Index\|/$Performance/g;
3401                                    }
3402                            }
3403                    }
3404                    $self->figmodel()->database()->print_array_to_file($OutputFilename,$OutputData);
3405    
3406                    my $GrowMatchTable = $self->figmodel()->database()->LockDBTable("GROWMATCH TABLE");
3407                    my $Row = $GrowMatchTable->get_row_by_key($self->genome(),"ORGANISM",1);
3408                    $Row->{"GF RECON TESTING TIMING"}->[0] .= time();
3409                    $GrowMatchTable->save();
3410                    $self->figmodel()->database()->UnlockDBTable("GROWMATCH TABLE");
3411            }
3412    
3413            return 1;
3414    }
3415    
3416  =head3 BuildSpecificBiomassReaction  =head3 BuildSpecificBiomassReaction
3417  Definition:  Definition:
3418          FIGMODELmodel->BuildSpecificBiomassReaction();          FIGMODELmodel->BuildSpecificBiomassReaction();
# Line 2679  Line 3425 
3425          my $OrganismID = $self->genome();          my $OrganismID = $self->genome();
3426          #Checking for a biomass override          #Checking for a biomass override
3427          if (defined($self->config("biomass reaction override")->{$OrganismID})) {          if (defined($self->config("biomass reaction override")->{$OrganismID})) {
3428                  $biomassrxn = $self->config("biomass reaction override")->{$OrganismID};                  my $biomassID = $self->config("biomass reaction override")->{$OrganismID};
3429                  print "Overriding biomass template and selecting ".$biomassrxn." for ".$OrganismID.".\n";                  my $tbl = $self->database()->get_table("BIOMASS",1);
3430                    $biomassrxn = $tbl->get_row_by_key($biomassID,"DATABASE");
3431                    print "Overriding biomass template and selecting ".$biomassID." for ".$OrganismID.".\n";
3432          } else {#Creating biomass reaction from the template          } else {#Creating biomass reaction from the template
3433                  #Getting the genome stats                  #Getting the genome stats
3434                  my $genomestats = $self->figmodel()->get_genome_stats($self->genome());                  my $genomestats = $self->figmodel()->get_genome_stats($self->genome());
# Line 2971  Line 3719 
3719    
3720                  #Adding the biomass equation to the biomass table                  #Adding the biomass equation to the biomass table
3721                  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());
3722                  $biomassrxn = $NewRow->{DATABASE}->[0];                  $biomassrxn = $NewRow;
                 print $biomassrxn."\n";  
3723          }          }
3724          print $biomassrxn."\n";          return $biomassrxn;
         my $BiomassRow = $self->figmodel()->add_model_to_biomass_reaction($biomassrxn,$self->id());  
         return $BiomassRow;  
3725  }  }
3726    
3727  =head3 PrintSBMLFile  =head3 PrintSBMLFile
# Line 3263  Line 4008 
4008          close(SBMLOUTPUT);          close(SBMLOUTPUT);
4009  }  }
4010    
4011    =head3 PrintModelSimpleReactionTable
4012    Definition:
4013            success()/fail() FIGMODELmodel->PrintModelSimpleReactionTable();
4014    Description:
4015            Prints the table of model data
4016    =cut
4017    sub PrintModelSimpleReactionTable {
4018            my ($self) = @_;
4019    
4020            my $rxntbl = $self->reaction_table();
4021            my $tbl = $self->create_table_prototype("ModelSimpleReactionTable");
4022            for (my $i=0; $i < $rxntbl->size(); $i++) {
4023                    my $row = $rxntbl->get_row($i);
4024                    $row->{DATABASE} = $row->{LOAD};
4025                    $tbl->add_row($row);
4026            }
4027            $tbl->save();
4028            system("cp ".$tbl->filename()." ".$self->figmodel()->config("Model table download directory")->[0].$self->figmodel()->config("ModelSimpleReactionTable")->{filename_prefix}->[0]."-".$self->id().".txt");
4029    }
4030    
4031  =head3 PrintModelLPFile  =head3 PrintModelLPFile
4032  Definition:  Definition:
4033          success()/fail() FIGMODELmodel->PrintModelLPFile();          success()/fail() FIGMODELmodel->PrintModelLPFile();
# Line 3287  Line 4052 
4052          $self->figmodel()->clearing_output($UniqueFilename,"FBA-".$self->id().$self->selected_version().".lp");          $self->figmodel()->clearing_output($UniqueFilename,"FBA-".$self->id().$self->selected_version().".lp");
4053  }  }
4054    
4055    =head3 patch_model
4056    Definition:
4057            FIGMODELTable:patch results = FIGMODELmodel->patch_model(FIGMODELTable:patch table);
4058    Description:
4059    =cut
4060    sub patch_model {
4061            my ($self,$tbl) = @_;
4062    
4063            #Instantiating table
4064            my $results = FIGMODELTable->new(["Reactions","New genes","Old genes","Genes","Roles","Status"],$self->directory()."PatchResults-".$self->id().$self->selected_version().".tbl",["Reaction"],"\t",";",undef);
4065            #Getting genome annotations
4066            my $features = $self->figmodel()->database()->get_genome_feature_table($self->genome());
4067            #Gettubg reaction table
4068            my $reactions = $self->reaction_table();
4069            #Checking for patched roles
4070            for (my $i=0; $i < $tbl->size(); $i++) {
4071                    my $row = $tbl->get_row($i);
4072                    my @genes = $features->get_rows_by_key($row->{ROLE}->[0],"ROLES");
4073                    if (@genes > 0) {
4074                            for (my $j=0; $j < @{$row->{REACTIONS}};$j++) {
4075                                    my $resultrxn = $results->get_row_by_key($row->{REACTIONS}->[$j],"Reactions");
4076                                    if (!defined($resultrxn)) {
4077                                            $resultrxn = $results->add_row({"Reactions"=>[$row->{REACTIONS}->[$j]],"Roles"=>[$row->{ROLE}->[0]]});
4078                                    }
4079                                    my $rxnrow = $reactions->get_row_by_key($row->{REACTIONS}->[$j],"LOAD");
4080                                    if (defined($rxnrow) && !defined($resultrxn->{"Old genes"})) {
4081                                            $resultrxn->{"Old genes"} = $rxnrow->{"ASSOCIATED PEG"};
4082                                            if ($resultrxn->{"Old genes"}->[0] !~ m/GAP|BOF|UNIVERSAL|SPONTANEOUS/) {
4083                                                    push(@{$resultrxn->{"Genes"}},@{$resultrxn->{"Old genes"}});
4084                                            }
4085                                    }
4086                                    delete $resultrxn->{"Current gene set"};
4087                                    if (defined($resultrxn->{"Genes"})) {
4088                                            push(@{$resultrxn->{"Current gene set"}},@{$resultrxn->{"Genes"}});
4089                                    }
4090                                    for (my $k=0; $k < @genes; $k++) {
4091                                            if ($genes[$k]->{ID}->[0] =~ m/(peg\.\d+)/) {
4092                                                    my $gene = $1;
4093                                                    my $addgene = 1;
4094                                                    if (defined($resultrxn->{"Old genes"})) {
4095                                                            for (my $m=0; $m < @{$resultrxn->{"Old genes"}}; $m++) {
4096                                                                    if ($resultrxn->{"Old genes"}->[$m] =~ m/$gene/) {
4097                                                                            $addgene = 0;
4098                                                                    }
4099                                                            }
4100                                                    }
4101                                                    if ($addgene == 1) {
4102                                                            push(@{$resultrxn->{"New genes"}},$gene);
4103                                                            if ($row->{COMPLEX}->[0] ne "0" && defined($resultrxn->{"Current gene set"})) {
4104                                                                    my $added = 0;
4105                                                                    for (my $m=0; $m < @{$resultrxn->{"Current gene set"}}; $m++) {
4106                                                                            if ($row->{COMPLEX}->[0] eq "1") {
4107                                                                                    $resultrxn->{"Current gene set"}->[$m] = $resultrxn->{"Current gene set"}->[$m]."+".$gene;
4108                                                                                    $added = 1;
4109                                                                            } else {
4110                                                                                    my @geneset = split(/\+/,$resultrxn->{"Current gene set"}->[$m]);
4111                                                                                    for (my $n=0; $n < @geneset;$n++) {
4112                                                                                            if ($self->figmodel()->colocalized_genes($geneset[$n],$gene,$self->genome()) == 1) {
4113                                                                                                    $resultrxn->{"Current gene set"}->[$m] = $resultrxn->{"Current gene set"}->[$m]."+".$gene;
4114                                                                                                    $added = 1;
4115                                                                                                    last;
4116                                                                                            }
4117                                                                                    }
4118                                                                            }
4119                                                                    }
4120                                                                    if ($added == 0) {
4121                                                                            push(@{$resultrxn->{"Current gene set"}},$gene);
4122                                                                    }
4123                                                            } else {
4124                                                                    push(@{$resultrxn->{"Current gene set"}},$gene);
4125                                                            }
4126                                                    }
4127                                            }
4128                                    }
4129                                    delete $resultrxn->{"Genes"};
4130                                    push(@{$resultrxn->{"Genes"}},@{$resultrxn->{"Current gene set"}});
4131                            }
4132                    }
4133            }
4134    
4135            #Ensuring that the old model is preserved
4136            $self->ArchiveModel();
4137            #Modifing the reaction list
4138            for (my $i=0; $i < $results->size();$i++) {
4139                    my $row = $results->get_row($i);
4140                    my $rxnrow = $reactions->get_row_by_key($row->{"Reactions"}->[0],"LOAD");
4141                    if (defined($rxnrow)) {
4142                            $rxnrow->{"ASSOCIATED PEG"} = $row->{"Genes"};
4143                    } else {
4144                            $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"]});
4145                    }
4146            }
4147            $reactions->save();
4148            $results->save();
4149            $self->update_model_stats();
4150            $self->PrintModelLPFile();
4151            $self->run_default_model_predictions();
4152            #Returning results
4153            return $results;
4154    }
4155    
4156    =head3 translate_genes
4157    Definition:
4158            FIGMODELmodel->translate_genes();
4159    Description:
4160    =cut
4161    sub translate_genes {
4162            my ($self) = @_;
4163    
4164            #Loading gene translations
4165            if (!defined($self->{_gene_aliases})) {
4166                    #Loading gene aliases from feature table
4167                    my $tbl = $self->figmodel()->GetGenomeFeatureTable($self->genome());
4168                    if (defined($tbl)) {
4169                            for (my $i=0; $i < $tbl->size(); $i++) {
4170                                    my $row = $tbl->get_row($i);
4171                                    if ($row->{ID}->[0] =~ m/(peg\.\d+)/) {
4172                                            my $geneID = $1;
4173                                            for (my $j=0; $j < @{$row->{ALIASES}}; $j++) {
4174                                                    $self->{_gene_aliases}->{$row->{ALIASES}->[$j]} = $geneID;
4175                                            }
4176                                    }
4177                            }
4178                    }
4179                    #Loading additional gene aliases from the database
4180                    if (-e $self->figmodel()->config("Translation directory")->[0]."AdditionalAliases/".$self->genome().".txt") {
4181                            my $AdditionalAliases = $self->figmodel()->database()->load_multiple_column_file($self->figmodel()->config("Translation directory")->[0]."AdditionalAliases/".$self->genome().".txt","\t");
4182                            for (my $i=0; $i < @{$AdditionalAliases}; $i++) {
4183                                    $self->{_gene_aliases}->{$AdditionalAliases->[$i]->[1]} = $AdditionalAliases->[$i]->[0];
4184                            }
4185                    }
4186            }
4187    
4188            #Cycling through reactions and translating genes
4189            for (my $i=0; $i < $self->reaction_table()->size(); $i++) {
4190                    my $row = $self->reaction_table()->get_row($i);
4191                    if (defined($row->{"ASSOCIATED PEG"})) {
4192                            for (my $j=0; $j < @{$row->{"ASSOCIATED PEG"}}; $j++) {
4193                                    my $Original = $row->{"ASSOCIATED PEG"}->[$j];
4194                                    $Original =~ s/\sand\s/:/g;
4195                                    $Original =~ s/\sor\s/;/g;
4196                                    my @GeneNames = split(/[,\+\s\(\):;]/,$Original);
4197                                    foreach my $Gene (@GeneNames) {
4198                                            if (length($Gene) > 0 && defined($self->{_gene_aliases}->{$Gene})) {
4199                                                    my $Replace = $self->{_gene_aliases}->{$Gene};
4200                                                    $Original =~ s/([^\w])$Gene([^\w])/$1$Replace$2/g;
4201                                                    $Original =~ s/^$Gene([^\w])/$Replace$1/g;
4202                                                    $Original =~ s/([^\w])$Gene$/$1$Replace/g;
4203                                                    $Original =~ s/^$Gene$/$Replace/g;
4204                                            }
4205                                    }
4206                                    $Original =~ s/:/ and /g;
4207                                    $Original =~ s/;/ or /g;
4208                                    $row->{"ASSOCIATED PEG"}->[$j] = $Original;
4209                            }
4210                    }
4211            }
4212    
4213            #Archiving model and saving reaction table
4214            $self->ArchiveModel();
4215            $self->reaction_table()->save();
4216    }
4217    
4218    =head3 feature_web_data
4219    Definition:
4220            string:web output for feature/model connection = FIGMODELmodel->feature_web_data(FIGMODELfeature:feature);
4221    Description:
4222    =cut
4223    sub feature_web_data {
4224            my ($self,$feature) = @_;
4225    
4226            #First checking if the feature is in the model
4227            my $featureGenome = $feature->{GENOME}->[0];
4228            if ($feature->{GENOME}->[0] =~ m/\>(\d+\.\d+)\</) {
4229                    $featureGenome = $1;
4230            }
4231            if ($featureGenome ne $self->genome()) {
4232                    return "Not in model";
4233            }
4234            my $data = $self->get_feature_data($feature->{ID}->[0]);
4235            if (!defined($data)) {
4236                    return "Not in model";
4237            }
4238    
4239            my $output;
4240            #Printing predictions
4241            if (defined($data->{$self->id()."PREDICTIONS"})) {
4242                    #Parsing essentiality data
4243                    my $essentialityData;
4244                    if (defined($feature->{ESSENTIALITY})) {
4245                            for (my $i=0; $i < @{$feature->{ESSENTIALITY}};$i++) {
4246                                    my @temp = split(/:/,$feature->{ESSENTIALITY}->[$i]);
4247                                    $essentialityData->{$temp[0]} = $temp[1];
4248                            }
4249                    }
4250                    my $predictionHash;
4251                    for (my $i=0; $i < @{$data->{$self->id()."PREDICTIONS"}};$i++) {
4252                            my @temp = split(/:/,$data->{$self->id()."PREDICTIONS"}->[$i]);
4253                            if (defined($essentialityData->{$temp[0]})) {
4254                                    if ($temp[1] eq "essential" && $essentialityData->{$temp[0]} eq "essential") {
4255                                            push(@{$predictionHash->{"Correct negative"}},$temp[0]);
4256                                    } elsif ($temp[1] eq "nonessential" && $essentialityData->{$temp[0]} eq "essential") {
4257                                            push(@{$predictionHash->{"False positive"}},$temp[0]);
4258                                    } elsif ($temp[1] eq "essential" && $essentialityData->{$temp[0]} eq "nonessential") {
4259                                            push(@{$predictionHash->{"False negative"}},$temp[0]);
4260                                    } elsif ($temp[1] eq "nonessential" && $essentialityData->{$temp[0]} eq "nonessential") {
4261                                            push(@{$predictionHash->{"Correct positive"}},$temp[0]);
4262                                    }
4263                            } else {
4264                                    push(@{$predictionHash->{$temp[1]}},$temp[0]);
4265                            }
4266                    }
4267                    foreach my $key (keys(%{$predictionHash})) {
4268                            my $string = $key;
4269                            $string = ucfirst($string);
4270                            push(@{$output},'<span title="'.join(", ",@{$predictionHash->{$key}}).'">'.$string.'</span>');
4271                    }
4272            }
4273    
4274            #Printing reactions
4275            if (defined($data->{$self->id()."REACTIONS"})) {
4276                    for (my $i=0; $i < @{$data->{$self->id()."REACTIONS"}};$i++) {
4277                            my $rxnData = $self->get_reaction_data($data->{$self->id()."REACTIONS"}->[$i]);
4278                            my $reactionString = $self->figmodel()->web()->create_reaction_link($data->{$self->id()."REACTIONS"}->[$i],join(" or ",@{$rxnData->{"ASSOCIATED PEG"}}),$self->id());
4279                            if (defined($rxnData->{PREDICTIONS})) {
4280                                    my $predictionHash;
4281                                    for (my $i=0; $i < @{$rxnData->{PREDICTIONS}};$i++) {
4282                                            my @temp = split(/:/,$rxnData->{PREDICTIONS}->[$i]);
4283                                            push(@{$predictionHash->{$temp[1]}},$temp[0]);
4284                                    }
4285                                    $reactionString .= "(";
4286                                    foreach my $key (keys(%{$predictionHash})) {
4287                                            if ($key eq "Essential =>") {
4288                                                    $reactionString .= '<span title="Essential in '.join(",",@{$predictionHash->{$key}}).'">E=></span>,';
4289                                            } elsif ($key eq "Essential <=") {
4290                                                    $reactionString .= '<span title="Essential in '.join(",",@{$predictionHash->{$key}}).'">E<=</span>,';
4291                                            } elsif ($key eq "Active =>") {
4292                                                    $reactionString .= '<span title="Active in '.join(",",@{$predictionHash->{$key}}).'">A=></span>,';
4293                                            } elsif ($key eq "Active <=") {
4294                                                    $reactionString .= '<span title="Active in '.join(",",@{$predictionHash->{$key}}).'">A<=</span>,';
4295                                            } elsif ($key eq "Active <=>") {
4296                                                    $reactionString .= '<span title="Active in '.join(",",@{$predictionHash->{$key}}).'">A</span>,';
4297                                            } elsif ($key eq "Inactive") {
4298                                                    $reactionString .= '<span title="Inactive in '.join(",",@{$predictionHash->{$key}}).'">I</span>,';
4299                                            } elsif ($key eq "Dead") {
4300                                                    $reactionString .= '<span title="Dead">D</span>,';
4301                                            }
4302                                    }
4303                                    $reactionString =~ s/,$/)/;
4304                            }
4305                            push(@{$output},$reactionString);
4306                    }
4307            }
4308    
4309            #Returning output
4310            return join("<br>",@{$output});
4311    }
4312    
4313    =head3 remove_obsolete_reactions
4314    Definition:
4315            void FIGMODELmodel->remove_obsolete_reactions();
4316    Description:
4317    =cut
4318    sub remove_obsolete_reactions {
4319            my ($self) = @_;
4320    
4321            (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"));
4322            my $rxnTbl = $self->reaction_table();
4323            if (defined($rxnTbl)) {
4324                    for (my $i=0; $i < $rxnTbl->size(); $i++) {
4325                            my $row = $rxnTbl->get_row($i);
4326                            if (defined($translation->{$row->{LOAD}->[0]}) || defined($translation->{$row->{LOAD}->[0]."r"})) {
4327                                    my $direction = $row->{DIRECTION}->[0];
4328                                    my $newRxn;
4329                                    if (defined($translation->{$row->{LOAD}->[0]."r"})) {
4330                                            $newRxn = $translation->{$row->{LOAD}->[0]."r"};
4331                                            if ($direction eq "<=") {
4332                                                    $direction = "=>";
4333                                            } elsif ($direction eq "=>") {
4334                                                    $direction = "<=";
4335                                            }
4336                                    } else {
4337                                            $newRxn = $translation->{$row->{LOAD}->[0]};
4338                                    }
4339                                    #Checking if the new reaction is already in the model
4340                                    my $newRow = $rxnTbl->get_row_by_key($newRxn,"LOAD");
4341                                    if (defined($newRow)) {
4342                                            #Handling direction
4343                                            if ($newRow->{DIRECTION}->[0] ne $direction) {
4344                                                    $newRow->{DIRECTION}->[0] = "<=>";
4345                                            }
4346                                            push(@{$row->{"ASSOCIATED PEG"}},@{$rxnTbl->get_row($i)->{"ASSOCIATED PEG"}});
4347                                    } else {
4348                                            $rxnTbl->get_row($i)->{LOAD}->[0] = $newRxn;
4349                                            $rxnTbl->get_row($i)->{DIRECTION}->[0] = $direction;
4350                                    }
4351                            }
4352                    }
4353                    $rxnTbl->save();
4354            }
4355    }
4356    
4357  1;  1;

Legend:
Removed from v.1.2  
changed lines
  Added in v.1.16

MCS Webmaster
ViewVC Help
Powered by ViewVC 1.0.3