[Bio] / FigKernelScripts / TransactFeatures.pl Repository:
ViewVC logotype

Diff of /FigKernelScripts/TransactFeatures.pl

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

revision 1.2, Tue Aug 9 00:57:48 2005 UTC revision 1.16, Mon Dec 5 18:56:37 2005 UTC
# Line 1  Line 1 
1  #!/usr/bin/perl -w  #!/usr/bin/perl -w
2    #
3    # Copyright (c) 2003-2006 University of Chicago and Fellowship
4    # for Interpretations of Genomes. All Rights Reserved.
5    #
6    # This file is part of the SEED Toolkit.
7    #
8    # The SEED Toolkit is free software. You can redistribute
9    # it and/or modify it under the terms of the SEED Toolkit
10    # Public License.
11    #
12    # You should have received a copy of the SEED Toolkit Public License
13    # along with this program; if not write to the University of Chicago
14    # at info@ci.uchicago.edu or the Fellowship for Interpretation of
15    # Genomes at veronika@thefig.info or download a copy from
16    # http://www.theseed.org/LICENSE.TXT.
17    #
18    
19    
20  =head1 Add / Delete / Change Features  =head1 Add / Delete / Change Features
21    
# Line 7  Line 24 
24  a command. The second specifies a directory full of transaction files. The third  a command. The second specifies a directory full of transaction files. The third
25  specifies a file that tells us which feature IDs are available for each organism.  specifies a file that tells us which feature IDs are available for each organism.
26    
27  C<TransactFeatures> I<[options]> I<command> I<transactionDirectory> I<idFile>  C<TransactFeatures> [I<options>] I<command> I<transactionDirectory> I<idFile>
28    
29  The supported commands are  The supported commands are
30    
# Line 16  Line 33 
33  =item count  =item count
34    
35  Count the number of IDs needed to process the ADD and CHANGE transactions. This  Count the number of IDs needed to process the ADD and CHANGE transactions. This
36  will produce an listing of the number of feature IDs needed for each  will produce a listing of the number of feature IDs needed for each
37  organism and feature type. This command is mostly a sanity check: it provides  organism and feature type. This command is mostly a sanity check: it provides
38  useful statistics without changing anything.  useful statistics without changing anything.
39    
# Line 28  Line 45 
45    
46  =item process  =item process
47    
48  Process the transactions and update the FIG data store. This will also create  Process the transactions and update the FIG data store. This will also update
49  a copy of each transaction file in which the pseudo-IDs have been replaced by  the NR file and queue features for similarity generation.
50  real IDs.  
51    =item fudge
52    
53    Convert transactions that have already been applied to new transactions that can
54    be used to test the transaction processor.
55    
56  =back  =back
57    
# Line 140  Line 161 
161  Wrap each organism's processing in a database transaction. This makes the process  Wrap each organism's processing in a database transaction. This makes the process
162  slightly more restartable than it would be otherwise.  slightly more restartable than it would be otherwise.
163    
164    =item noAlias
165    
166    Assume that the transaction files do not contain aliases. This means that in CHANGE
167    records the translation will immediately follow the location.
168    
169    =item sql
170    
171    Trace SQL commands.
172    
173    =item tblFiles
174    
175    Output TBL files containing the corrected IDs. (B<process> command only)
176    
177    =item start
178    
179    ID of the first genome to process. This allows restarting a transaction run that failed
180    in the middle. The default is to run all transaction files.
181    
182    =back
183    
184  =cut  =cut
185    
186  use strict;  use strict;
187  use Tracer;  use Tracer;
188  use DocUtils;  use DocUtils;
 use TestUtils;  
189  use Cwd;  use Cwd;
190  use File::Copy;  use File::Copy;
191  use File::Path;  use File::Path;
192  use FIG;  use FIG;
193  use Stats;  use Stats;
194    use TransactionProcessor;
195    use ApplyTransactions;
196    use CountTransactions;
197    use FudgeTransactions;
198    
199  # Get the command-line options.  # Get the command-line options.
200  my ($options, @parameters) = Tracer::ParseCommand({ trace => 3, safe => 0 }, @ARGV);  my ($options, @parameters) = Tracer::ParseCommand({ trace => 3, sql => 0, safe => 0, noAlias => 0,
201                                                        start => ' ', tblFiles => 0},
202                                                      @ARGV);
203    # Get the command.
204    my $mainCommand = lc shift @parameters;
205  # Set up tracing.  # Set up tracing.
206  my $traceLevel = $options->{trace};  my $traceLevel = $options->{trace};
207  TSetup("$traceLevel Tracer DocUtils FIG", "TEXT");  my $tracing = "$traceLevel Tracer DocUtils FIG";
208    if ($options->{sql}) {
209        $tracing .= " SQL";
210    }
211    TSetup($tracing, "TEXT");
212  # Get the FIG object.  # Get the FIG object.
213  my $fig = FIG->new();  my $fig = FIG->new();
214  # Get its database handle.  # Create the transaction object.
215  my $dbh = $fig->db_handle;  my $controlBlock;
216  # Get the command.  if ($mainCommand eq 'count' || $mainCommand eq 'register') {
217  my $mainCommand = lc shift @parameters;      $controlBlock = CountTransactions->new($options, $mainCommand, @parameters);
218  Trace("$mainCommand command specified.") if T(2);  } elsif ($mainCommand eq 'process') {
219        $controlBlock = ApplyTransactions->new($options, $mainCommand, @parameters);
220  # Create the ID table. This maps each organism/ftype pair to the currently-  } elsif ($mainCommand eq 'fudge') {
221  # available ID number. If we're counting, we leave it empty. If we're not      $controlBlock = FudgeTransactions->new($options, $mainCommand, @parameters);
222  # counting, we need to read it in.  } else {
223  my %idHash = ();      Confess("Invalid command \"$mainCommand\" specified on command line.");
 if ($mainCommand eq 'process') {  
     my $inCount = 0;  
     Open(\*IDFILE, "<$parameters[1]");  
     while (my $idRecord = <IDFILE>) {  
         chomp $idRecord;  
         my ($orgID, $ftype, $firstNumber) = split /\t/, $idRecord;  
         $idHash{"$orgID.$ftype"} = $firstNumber;  
         $inCount++;  
     }  
     Trace("$inCount ID ranges read in from $parameters[1].") if T(2);  
224  }  }
225    # Setup the process.
226  # Create some counters we can use for statistical purposes.  $controlBlock->Setup();
 my $stats = Stats->new("genomes", "add", "change", "delete");  
227  # Verify that the organism directory exists.  # Verify that the organism directory exists.
228  if (! -d $parameters[0]) {  if (! -d $parameters[0]) {
229      Confess("Directory of genome files \"$parameters[0]\" not found.");      Confess("Directory of genome files \"$parameters[0]\" not found.");
# Line 192  Line 233 
233      my $orgsFound = 0;      my $orgsFound = 0;
234      my %transFiles = ();      my %transFiles = ();
235      my @transDirectory = OpenDir($parameters[0], 1);      my @transDirectory = OpenDir($parameters[0], 1);
236        # Pull out the "start" option value. This will be a space if all genomes should
237        # be processed, in which case it will always compare less than the genome ID.
238        my $startGenome = $options->{start};
239      # The next step is to create a hash of organism IDs to file names. This      # The next step is to create a hash of organism IDs to file names. This
240      # saves us some painful parsing later.      # saves us some painful parsing later.
241      for my $transFileName (@transDirectory) {      for my $transFileName (@transDirectory) {
242            # Parse the file name. This will only match if it's a real transaction file.
243          if ($transFileName =~ /^tbl_diff_(\d+\.\d+)$/) {          if ($transFileName =~ /^tbl_diff_(\d+\.\d+)$/) {
244                # Get the genome ID;
245                my $genomeID = $1;
246                # If we're skipping, only include this genome ID if it's equal to
247                # or greater than the start value.
248                if ($genomeID ge $startGenome) {
249              $transFiles{$1} = "$parameters[0]/$transFileName";              $transFiles{$1} = "$parameters[0]/$transFileName";
250              $orgsFound++;              $orgsFound++;
251          }          }
252      }      }
253        }
254      Trace("$orgsFound genome transaction files found in directory $parameters[0].") if T(2);      Trace("$orgsFound genome transaction files found in directory $parameters[0].") if T(2);
255      if (! $orgsFound) {      if (! $orgsFound) {
256          Confess("No \"tbl_diff\" files found in directory $parameters[1].");          Confess("No \"tbl_diff\" files found in directory $parameters[1].");
257      } else {      } else {
258          # Loop through the organisms.          # Loop through the organisms.
259          for my $genomeID (sort keys %transFiles) {          for my $genomeID (sort keys %transFiles) {
260                # Start this organism.
261              Trace("Processing changes for $genomeID.") if T(3);              Trace("Processing changes for $genomeID.") if T(3);
             # Create a statistics object for this organism.  
             my $orgStats = Stats->new("add", "change", "delete");  
             # Create a control block for passing around our key data.  
             my $controlBlock = { stats => $orgStats, genomeID => $genomeID,  
                                  idHash => \%idHash, options => $options,  
                                  fig => $fig, command => $mainCommand };  
             # Open the organism file.  
262              my $orgFileName = $transFiles{$genomeID};              my $orgFileName = $transFiles{$genomeID};
263                $controlBlock->StartGenome($genomeID, $orgFileName);
264                # Open the organism file.
265              Open(\*TRANS, "<$orgFileName");              Open(\*TRANS, "<$orgFileName");
266                # Clear the transaction counter.
267              my $tranCount = 0;              my $tranCount = 0;
             # If we're processing rather than counting, open a file for  
             # writing out corrected transactions and optionally start a  
             # database transaction.  
             if ($mainCommand eq 'process') {  
                 Open(\*TRANSOUT, ">$orgFileName.tbl");  
                 if ($options->{safe}) {  
                     $dbh->begin_tran();  
                 }  
             }  
268              # Loop through the organism's data.              # Loop through the organism's data.
269              while (my $transaction = <TRANS>) {              while (my $transaction = <TRANS>) {
270                  # Parse the record.                  # Parse the record.
# Line 237  Line 276 
276                  # Process according to the transaction type.                  # Process according to the transaction type.
277                  my $command = lc shift @fields;                  my $command = lc shift @fields;
278                  if ($command eq 'add') {                  if ($command eq 'add') {
279                      Add($controlBlock, @fields);                      $controlBlock->Add(@fields);
280                  } elsif ($command eq 'delete') {                  } elsif ($command eq 'delete') {
281                      Delete($controlBlock, @fields);                      $controlBlock->Delete(@fields);
282                  } elsif ($command eq 'change') {                  } elsif ($command eq 'change') {
283                      Change($controlBlock, @fields);                      # Here we have a special case. If "noalias" is in effect, we need
284                        # to splice an empty field in before the translation.
285                        if ($controlBlock->Option("noAlias")) {
286                            splice @fields, 3, 0, "";
287                        }
288                        $controlBlock->Change(@fields);
289                  } else {                  } else {
290                      $orgStats->AddMessage("Invalid command $command in line $tranCount for genome $genomeID");                      $controlBlock->AddMessage("Invalid command $command in line $tranCount for genome $genomeID");
291                  }                  }
292                  $orgStats->Add($command, 1);                  $controlBlock->IncrementStat($command);
293              }              }
             Trace("Statistics for $genomeID\n\n" . $orgStats->Show()) if T(3);  
             # Merge the statistics for this run into the globals statistics object.  
             $stats->Accumulate($orgStats);  
             $stats->Add("genomes", 1);  
294              # Close the transaction input file.              # Close the transaction input file.
295              close TRANS;              close TRANS;
296              # If we're processing, close the transaction output file              # Terminate processing for this genome.
297              # and optionally end the database transaction.              my $orgStats = $controlBlock->EndGenome();
298              if ($mainCommand eq 'process') {              Trace("Statistics for $genomeID\n\n" . $orgStats->Show() . "\n") if T(3);
                 close TRANSOUT;  
                 if ($options->{safe}) {  
                     $dbh->commit_tran();  
                 }  
             }  
         }  
     }  
     Trace("Statistics for this run\n\n" . $stats->Show()) if T(1);  
     # If we're counting, we need to write out the counts file or allocate IDs  
     # from the clearinghouse.  
     if ($mainCommand ne "process") {  
         # Loop through the ID hash, printing the counts. We will also write them  
         # to a file called "counts.tbl".  
         my $countfile = "$parameters[0]/counts.tbl";  
         Open(\*COUNTFILE, ">$countfile");  
         print "\nTable of Counts\n";  
         for my $idKey (keys %idHash) {  
             $idKey =~ /^(\d+\.\d+)\.([a-z]+)$/;  
             my ($org, $ftype) = ($1, $2);  
             my $count = $idHash{$idKey};  
             print "$idKey\t$count\n";  
             print COUNTFILE "$org\t$ftype\t$count\n";  
         }  
         close COUNTFILE;  
         if ($mainCommand eq "register") {  
             # Here we are registering as well as counting. This process also produces  
             # the ID file.  
             Trace("Submitting ID file to clearing house.") if T(2);  
             system("register_features_batch <$countfile >$parameters[1]");  
             Trace("Clearing house request complete.") if T(2);  
299          }          }
300      }      }
301        # Terminate processing.
302        $controlBlock->Teardown();
303        Trace("Statistics for this run\n\n" . $controlBlock->Show() . "\n") if T(1);
304      Trace("Processing complete.") if T(1);      Trace("Processing complete.") if T(1);
305  }  }
306    
 =head2 Utility Methods  
   
 =head3 Add  
   
 C<< Add($controlBlock, $newID, $locations, $translation); >>  
   
 Add a new feature to the data store.  
   
 =over 4  
   
 =item controlBlock  
   
 Reference to a hash containing the data structures required to manage feature  
 transactions.  
   
 =item newID  
   
 ID to give to the new feature.  
   
 =item locations  
   
 Location of the new feature, in the form of a comma-separated list of location  
 strings in SEED format.  
   
 =item translation (optional)  
   
 Protein translation string for the new feature. If this field is omitted and  
 the feature is a peg, the translation will be generated by normal means.  
   
 =back  
   
 =cut  
   
 sub Add {  
     my ($controlBlock, $newID, $locations, $translation) = @_;  
     my $fig = $controlBlock->{fig};  
     # Extract the feature type and ordinal number from the new ID.  
     my ($ftype, $ordinal, $key) = ParseNewID($controlBlock, $newID);  
     # If we're counting, we need to count the ID. Otherwise, we need to  
     # add the new feature.  
     if ($controlBlock->{command} ne 'process') {  
         $controlBlock->{idHash}->{$key}++;  
     } else {  
         # Here we need to add the new feature.  
         my $realID = AddFeature($controlBlock, $ordinal, $key, $ftype,  
                                 "", $locations, $translation);  
         Trace("Feature $realID added for pseudo-ID $newID.") if T(4);  
         # Write a corrected transaction to the transaction output file.  
         print TRANSOUT "add\t$realID\t$locations\t$translation\n";  
     }  
 }  
   
 =head3 Change  
   
 C<< Change($controlBlock, $fid, $newID, $locations, $aliases, $translation); >>  
   
 Replace a feature to the data store. The feature will be marked for deletion and  
 a new feature will be put in its place.  
   
 This is a much more complicated process than adding a feature. In addition to  
 the add, we have to create new aliases and transfer across the assignment and  
 the annotations.  
   
 =over 4  
   
 =item controlBlock  
   
 Reference to a hash containing the data structures required to manage feature  
 transactions.  
   
 =item fid  
   
 ID of the feature being changed.  
   
 =item newID  
   
 New ID to give to the feature.  
   
 =item locations  
   
 New location to give to the feature, in the form of a comma-separated list of location  
 strings in SEED format.  
   
 =item aliases (optional)  
   
 A new list of alias names for the feature.  
   
 =item translation (optional)  
   
 New protein translation string for the feature. If this field is omitted and  
 the feature is a peg, the translation will be generated by normal means.  
   
 =back  
   
 =cut  
   
 sub Change {  
     my ($controlBlock, $fid, $newID, $locations, $aliases, $translation) = @_;  
     my $fig = $controlBlock->{fig};  
     # Extract the feature type and ordinal number from the new ID.  
     my ($ftype, $ordinal, $key) = ParseNewID($controlBlock, $newID);  
     # If we're counting, we need to count the ID. Otherwise, we need to  
     # replace the feature.  
     if ($controlBlock->{command} ne 'process') {  
         $controlBlock->{idHash}->{$key}++;  
     } else {  
         # Here we can go ahead and change the feature. First, we must  
         # get the old feature's assignment and annotations. Note that  
         # for the annotations we ask for the time in its raw format.  
         my @functions = $fig->function_of($fid);  
         my @annotations = $fig->feature_annotations($fid, 1);  
         # Create some counters.  
         my ($assignCount, $annotateCount) = (0, 0);  
         # Add the new version of the feature and get its ID.  
         my $realID = AddFeature($controlBlock, $ordinal, $key, $ftype, $locations,  
                                 $aliases, $translation);  
         # Copy over the assignments.  
         for my $assignment (@functions) {  
             my ($user, $function) = @{$assignment};  
             $fig->assign_function($realID, $user, $function);  
             $assignCount++;  
         }  
         # Copy over the annotations.  
         for my $annotation (@annotations) {  
             my ($oldID, $timestamp, $user, $annotation) = @{$annotation};  
             $fig->add_annotation($realID, $user, $annotation, $timestamp);  
             $annotateCount++;  
         }  
         # Mark the old feature for deletion.  
         $fig->delete_feature($fid);  
         # Tell the user what we did.  
         $controlBlock->{stats}->Add("assignments", $assignCount);  
         $controlBlock->{stats}->Add("annotations", $annotateCount);  
         Trace("Feature $realID created from $fid. $assignCount assignments and $annotateCount annotations copied.") if T(4);  
         # Write a corrected transaction to the transaction output file.  
         print TRANSOUT "change\t$fid\t$realID\t$locations\t$aliases\t$translation\n";  
     }  
 }  
   
 =head3 Delete  
   
 C<< Delete($controlBlock, $fid); >>  
   
 Delete a feature from the data store. The feature will be marked as deleted,  
 which will remove it from consideration by most FIG methods. A garbage  
 collection job will be run later to permanently delete the feature.  
   
 =over 4  
   
 =item controlBlock  
   
 Reference to a hash containing the data structures required to manage feature  
 transactions.  
   
 =item fid  
   
 ID of the feature to delete.  
   
 =back  
   
 =cut  
   
 sub Delete {  
     my ($controlBlock, $fid) = @_;  
     my $fig = $controlBlock->{fig};  
     # Extract the feature type and count it.  
     my $ftype = FIG::ftype($fid);  
     $controlBlock->{stats}->Add($ftype, 1);  
     # If we're not counting, delete the feature.  
     if ($controlBlock->{command} eq 'process') {  
         # Mark the feature for deletion.  
         $fig->delete_feature($fid);  
         # Echo the transaction to the transaction output file.  
         print TRANSOUT "del\t$fid\n";  
     }  
 }  
   
 =head3 ParseNewID  
   
 C<< my ($ftype, $ordinal, $key) = ParseNewID($controlBlock, $newID); >>  
   
 Extract the feature type and ordinal number from an incoming new ID.  
   
 =over 4  
   
 =item controlBlock  
   
 Reference to a hash containing the data structures needed to manage transactions.  
   
 =item newID  
   
 New ID specification taken from a transaction input record. This contains the  
 feature type followed by a period and then the ordinal number of the ID.  
   
 =item RETURN  
   
 Returna a three-element list. If successful, the list will contain the feature  
 type followed by the ordinal number and the key to use in the ID hash to find  
 the feature's true ID number. If the incoming ID is invalid, the list  
 will contain three C<undef>s.  
   
 =back  
   
 =cut  
   
 sub ParseNewID {  
     # Get the parameters.  
     my ($controlBlock, $newID) = @_;  
     my ($ftype, $ordinal, $key);  
     # Parse the ID.  
     if ($newID =~ /^([a-z]+)\.(\d+)$/) {  
         # Here we have a valid ID.  
         ($ftype, $ordinal) = ($1, $2);  
         $key = $controlBlock->{genomeID} . ".$ftype";  
         # Update the feature type count in the statistics.  
         $controlBlock->{stats}->Add($ftype, 1);  
     } else {  
         # Here we have an invalid ID.  
         $controlBlock->{stats}->AddMessage("Invalid ID $newID found in line " .  
                                            $controlBlock->{line} . " for genome " .  
                                            $controlBlock->{genomeID} . ".");  
     }  
     # Return the result.  
     return ($ftype, $ordinal, $key);  
 }  
   
 =head3 GetRealID  
   
 C<< my $realID = GetRealID($controlBlock, $ftype, $ordinal, $key); >>  
   
 Compute the real ID of a new feature. This involves interrogating the ID hash and  
 formatting a full-blown ID out of little bits of information.  
   
 =over 4  
   
 =item controlBlock  
   
 Reference to a hash containing data used to manage the transaction process.  
   
 =item ordinal  
   
 Zero-based ordinal number of this feature. The ordinal number is added to the value  
 stored in the control block's ID hash to compute the real feature number.  
   
 =item key  
   
 Key in the ID hash relevant to this feature.  
   
 =item RETURN  
   
 Returns a fully-formatted FIG ID for the new feature.  
   
 =back  
   
 =cut  
   
 sub GetRealID {  
     # Get the parameters.  
     my ($controlBlock, $ordinal, $key) = @_;  
     #Declare the return value.  
     my $retVal;  
     # Get the base value for the feature ID number.  
     my $base = $controlBlock->{idHash}->{$key};  
     # If it didn't exist, we have an error.  
     if (! defined $base) {  
         Confess("No ID range found for genome ID and feature type $key.");  
     } else {  
         # Now we have enough data to format the ID.  
         my $num = $base + $ordinal;  
         $retVal = "fig|$key.$num";  
     }  
     # Return the result.  
     return $retVal;  
 }  
   
 =head3 CheckTranslation  
   
 C<< my $actualTranslation = CheckTranslation($controlBlock, $ftype, $locations, $translation); >>  
   
 If we are processing a PEG, insure we have a translation for the peg's locations.  
   
 This method checks the feature type and the incoming translation string. If the  
 translation string is empty and the feature type is C<peg>, it will generate  
 a translation string using the specified locations for the genome currently  
 being processed.  
   
 =over 4  
   
 =item controlBlock  
   
 Reference to a hash containing data used to manage the transaction process.  
   
 =item ftype  
   
 Feature type (C<peg>, C<rna>, etc.)  
   
 =item locations  
   
 Comma-delimited list of location strings for the feature in question.  
   
 =item translation (optional)  
   
 If specified, will be returned to the caller as the result.  
   
 =item RETURN  
   
 Returns the protein translation string for the specified locations, or C<undef>  
 if no translation is warranted.  
   
 =back  
   
 =cut  
   
 sub CheckTranslation {  
     # Get the parameters.  
     my ($controlBlock, $ftype, $locations, $translation) = @_;  
     my $fig = $controlBlock->{fig};  
     # Declare the return variable.  
     my $retVal;  
     if ($ftype eq 'peg') {  
         # Here we have a protein encoding gene. Check to see if we already have  
         # a translation.  
         if (defined $translation) {  
             # Pass it back unmodified.  
             $retVal = $translation;  
         } else {  
             # Here we need to compute the translation.  
             my $dna = $fig->dna_seq($controlBlock->{genomeID}, $locations);  
             $retVal = FIG::translate($dna);  
         }  
     }  
     # Return the result.  
     return $retVal;  
 }  
   
 =head3 AddFeature  
   
 C<< my $realID = AddFeature($controlBlock, $ordinal, $key, $ftype, $locations, $translation); >>  
   
 Add the specified feature to the FIG data store. This involves generating the new feature's  
 ID, creating the translation (if needed), adding the feature to the data store, and  
 queueing a request to update the similarities. The generated ID will be returned to the  
 caller.  
   
 =over 4  
   
 =item controlBlock  
   
 Reference to a hash containing the data structures required to manage feature  
 transactions.  
   
 =item ordinal  
   
 Zero-based ordinal number of the proposed feature in the ID space. This is added to the  
 base ID number to get the real ID number.  
   
 =item key  
   
 Key to use for getting the base ID number from the ID hash.  
   
 =item ftype  
   
 Proposed feature type (C<peg>, C<rna>, etc.)  
   
 =item locations  
   
 Location of the new feature, in the form of a comma-separated list of location  
 strings in SEED format.  
   
 =item aliases (optional)  
   
 A new list of alias names for the feature.  
   
 =item translation (optional)  
   
 Protein translation string for the new feature. If this field is omitted and  
 the feature is a peg, the translation will be generated by normal means.  
   
 =back  
   
 =cut  
   
 sub AddFeature {  
     # Get the parameters.  
     my ($controlBlock, $ordinal, $key, $ftype, $locations, $aliases, $translation) = @_;  
     my $fig = $controlBlock->{fig};  
     # We want to add a new feature using the information provided. First, we  
     # generate its ID.  
     my $retVal = GetRealID($controlBlock, $ordinal, $key);  
     # Next, we insure that we have a translation.  
     my $actualTranslation = CheckTranslation($controlBlock, $ftype,  
                                              $locations, $translation);  
     # Now we add it to FIG.  
     $fig->add_feature($controlBlock->{genomeID}, $ftype, $locations, "",  
                       $actualTranslation, $retVal);  
     # Tell FIG to recompute the similarities.  
     $fig->enqueue_similarities([$retVal]);  
     # Return the ID we generated.  
     return $retVal;  
 }  
307    
308  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