[Bio] / Sprout / SimLoad.pl Repository:
ViewVC logotype

Diff of /Sprout/SimLoad.pl

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

revision 1.2, Wed Jul 27 20:05:58 2005 UTC revision 1.8, Wed Feb 1 03:28:11 2006 UTC
# Line 4  Line 4 
4  use CGI;  use CGI;
5  use Tracer;  use Tracer;
6  use Genome;  use Genome;
7    use DBKernel;
8  use SimBlocks;  use SimBlocks;
9  use File::Path;  use File::Path;
10  use BasicLocation;  use BasicLocation;
11    use Cwd;
12    
13  =head1 Similarity Block Loader  =head1 Similarity Block Loader
14    
15  This script loads the similarity block database from  This script loads the similarity block database from
16  the input files.  the input files. The load process involves two steps:
17    converting the input files into C<dtx> load files
18  The script takes a single parameter-- the directory name.  (B<generate>), and loading the C<dtx> files into the
19  The default directory name is taken from the config file  database (B<load>).
20  parameter C<$fig_config::SimBlastData>. The output files  
21  will be produced in the similarity block data directory  The script takes a single parameter-- a directory name.
22  C<$fig_config::SimBlockData>, which will be created if  The default directory name is C<"$FIG_Config::data/CloseStrainSets">.
23  it does not exist.  The input files should be in subdirectories called
24    C<Block> under the subdirectories of the input directory.
25    The subdirectory names themselves are considered the name
26    of the close-strain set. So, for example
27    
28        Data/CloseStrainSets/Vibrio/Block
29    
30    would be presumed to contain the Vibrio strains.
31    
32    The output files will be produced in the similarity block
33    data directory C<$fig_config::SimBlockData>, which will be
34    created if it does not exist. The input directory and all its
35    subdirectories will be processed for input files.
36    
37  In addition to the directory name, the following  In addition to the directory name, the following
38  option parameters are supported.  option parameters are supported.
# Line 28  Line 42 
42  =item trace  =item trace
43    
44  Trace level for output messages. A higher number means more  Trace level for output messages. A higher number means more
45  messages. The default is C<1>.  messages. The default is C<3>. Trace messages are sent to
46    the file C<trace.log> in the B<$FIG_Config::tmp>
47    directory.
48    
49  =item logFile  =item sql
50    
51  Name of a file to be used for trace messages, or  If specified, SQL activity will be traced at the specified
52  C<*> to send them to the standard output. If a  trace level.
 file is specified, the output directory must  
 already exist. The default is C<*>.  
53    
54  =item load  =item load
55    
# Line 47  Line 61 
61  C<yes> to generate output files from input files, else  C<yes> to generate output files from input files, else
62  C<no>. The default is C<yes>.  C<no>. The default is C<yes>.
63    
64    =item createDB
65    
66    If specified, the database will be dropped and
67    re-created before loading.
68    
69  =back  =back
70    
71  For example, the following command line will process the  For example, the following command line will process the
72  C<Fragment.sort> file in the C</Users/fig/BlastData> directory and  input files in the C</Users/fig/BlastData> directory tree
73  run at a trace level of 3.  and run at a trace level of 3.
74    
75  C<< SimLoad /Users/fig/BlastData -trace=3 >>  C<< SimLoad -trace=3 /Users/fig/BlastData >>
76    
77  Please note that spaces in the file and directory names must  The following command line converts the input files in
78  be escaped as C<\b> to prevent them from being parsed as  the default directory into load files but does not load
79  argument delimiters.  the database and runs at a trace level of 2.
80    
81    C<< SimLoad -load=no >>
82    
83  =head2 Input Directory  =head2 Input Directory
84    
85  The following files must exist in the input directory.  The following files must exist in each C<Block> directory
86    under the input directory.
87    
88  =over 4  =over 4
89    
90  =item Genome.tbl  =item genome.tbl
91    
92  This is a tab-delimited file that contains the ID of each  This is a tab-delimited file that contains the ID of each
93  genome followed by a description string.  genome followed by a description string.
94    
95  =item Block.tbl, InterGenic_Block.tbl  =item block.tbl, intergenic_block.tbl
96    
97  These are tab-delimited files that associate a gene name  These are tab-delimited files that associate a gene name
98  with each block. The InterGenic file is optional.  with each block. The InterGenic file is optional.
99    
100  =item Region.tbl, InterGenic_Region.tbl  =item region.tbl, intergenic_region.tbl
101    
102  These are tab-delimited files that describe each region  These are tab-delimited files that describe each region
103  of a block. The InterGenic file is optional.  of a block. The InterGenic file is optional.
# Line 84  Line 106 
106    
107  The format of each file is given below.  The format of each file is given below.
108    
109  =head3 Genome.tbl  =head3 genome.tbl
110    
111  The Genome file is copied almost unmodified to the  The Genome file is copied almost unmodified to the
112  load file for the B<Genome> entity. Each record  load file for the B<Genome> entity. Each record
# Line 102  Line 124 
124  A text description of the genome (usually the species name with  A text description of the genome (usually the species name with
125  a strain ID).  a strain ID).
126    
127    =teim groupName
128    
129    The name of the group to which the genome belongs.
130    
131  =back  =back
132    
133  =head3 Block.tbl, InterGenic_Block.tbl  =head3 block.tbl, intergenic_block.tbl
134    
135  These files produce most of the data found in the B<GroupBlock>  These files produce most of the data found in the B<GroupBlock>
136  entity. Each record represents a single block. Blocks either  entity. Each record represents a single block. Blocks either
# Line 127  Line 153 
153    
154  =back  =back
155    
156  =head3 Region.tbl, InterGenic_Region.tbl  =head3 region.tbl, intergenic_region.tbl
157    
158  These files describe the regions in each block. They are  These files describe the regions in each block. They are
159  used to derive the relationships between genomes and  used to derive the relationships between genomes and
# Line 278  Line 304 
304  my $TRAILER = 999999999;  my $TRAILER = 999999999;
305    
306  # Parse the command line.  # Parse the command line.
307  my ($options, @arguments) = Tracer::ParseCommand({ trace => 1,  my ($options, @arguments) = StandardSetup(['SimBlocks'],
308                                                    logFile => "*",                                                  { load => ['yes', "'no' to suppress loading the database"],
309                                                    load => 'yes',                                                    generate => ['yes', "'no' to suppress generating the load files"],
310                                                    generate => 'yes'},                                                    createDB => [0, 'drop and create the database before loading']
311                                                    },
312                                                    "directoryName",
313                                                   @ARGV);                                                   @ARGV);
314  # Extract the directory name from the argument array.  # Extract the directory name from the argument array.
315  my $inDirectory = $FIG_Config::simBlastData;  my $inDirectoryTree = ($arguments[0] ? Cwd::abs_path($arguments[0]) : "$FIG_Config::data/CloseStrainSets");
316  if ($arguments[0]) {  # Check to see if we need to create the database.
317      $inDirectory = Cwd::abs_path($arguments[0]);  if ($options->{createDB}) {
318  }      Trace("Creating database.") if T(2);
319  # Set up tracing.      DBKernel::CreateDB($FIG_Config::simBlocksDB);
320  my $traceLevel = $options->{trace};  }
 my $traceOption = $options->{logFile};  
 my $TracingToFile = ($traceOption ne "*");  
 my $traceDestination = ($TracingToFile ? ">$traceOption" : "TEXT");  
 TSetup("$traceLevel Tracer", $traceDestination);  
321  # Get the output directory.  # Get the output directory.
322  my $outDirectory = $FIG_Config::simBlocksData;  my $outDirectory = $FIG_Config::simBlocksData;
323  # Insure that it exists.  # Insure that it exists.
324  if (! -d $outDirectory) {  if (! -d $outDirectory) {
325      Output("Creating output directory $outDirectory.");      Trace("Creating output directory $outDirectory.") if T(2);
326      mkpath($outDirectory);      mkpath($outDirectory);
327    } elsif ($options->{generate} eq 'yes') {
328        # Here we have an output directory already and are going to generate new
329        # load files. Clear any leftover data from previous runs.
330        my @files = grep { $_ =~ /.dtx$/ } Tracer::OpenDir($outDirectory);
331        my $numFiles = @files;
332        if ($numFiles > 0) {
333            Trace("Deleting $numFiles old dtx files from $outDirectory.") if T(2);
334            unlink map { "$outDirectory/$_" } @files;
335        }
336  }  }
337  # Create an error counter.  # Create an error counter and a directory counter.
338  my $errorCount = 0;  my $errorCount = 0;
339    my $dirCount = 0;
340  # Check to see if we should generate the output files.  # Check to see if we should generate the output files.
341  if ($options->{generate} eq 'no') {  if ($options->{generate} eq 'no') {
342      # Here we are to use existing output files.      # Here we are to use existing output files.
343      Output("Existing database load files will be used.");      Trace("Existing database load files will be used.") if T(2);
344  } else {  } else {
345      # Here we need to produce new output files.      # Here we need to produce new output files.
346      # Verify that the input directory exists.      # Verify that the input directory exists.
347      if (! -d $inDirectory) {      if (! -d $inDirectoryTree) {
348          Confess("Input directory \"$inDirectory\" not found.");          Confess("Input directory \"$inDirectoryTree\" not found.");
349        }
350        # Loop through the subdirectories.
351        for my $inputDirectory (Tracer::OpenDir($inDirectoryTree, 1)) {
352            # Verify that this is a directory.
353            my $inDirectory = "$inDirectoryTree/$inputDirectory/Blocks";
354            if (-d $inDirectory) {
355                # Here we have a directory to process. Check for a genome
356                # file.
357                my $genomeFileName = "$inDirectory/genome.tbl";
358                if (! -e $genomeFileName) {
359                    Trace("$genomeFileName not found. Directory skipped.") if T(1);
360                } else {
361                    # Now we can process the directory and accumulate the error
362                    # count.
363                    $errorCount += ProcessDirectory($inDirectory, $outDirectory, $inputDirectory);
364                    $dirCount++;
365                }
366            }
367        }
368        Trace("Load files generated from $dirCount directories.") if T(2);
369    }
370    # Check for errors.
371    if ($errorCount > 0) {
372        Trace("$errorCount errors found in input files.") if T(0);
373    } else {
374        # No errors, so it's okay to load the database.
375        if ($options->{load} eq 'yes') {
376            # Here we have no outstanding errors and the user wants us to load
377            # the database. First, we create a similarity block object.
378            my $simBlocks = SimBlocks->new();
379            # Use it to load the database. Note we specify that the tables are to be
380            # dropped and rebuilt.
381            $simBlocks->LoadTables($outDirectory, 1);
382            Trace("Database loaded.") if T(2);
383        }
384      }      }
385    
386    # Process a single input directory.
387    sub ProcessDirectory {
388        my ($inDirectory, $outDirectory, $groupName) = @_;
389        Trace("Processing directory $inDirectory.") if T(2);
390      # Our first task is to copy the genome data to the output directory      # Our first task is to copy the genome data to the output directory
391      # and build the genome list.      # and add the genomes to the genome list.
392      my %genomes = ();      my %genomes = ();
393      (open GENOMESIN, "<$inDirectory/Genome.tbl") ||      Open(\*GENOMESIN, "<$inDirectory/genome.tbl");
394          Confess("Could not open Genome input file in $inDirectory.");      Open(\*GENOMESOUT, ">>$outDirectory/Genome.dtx");
395      (open GENOMESOUT, ">$outDirectory/Genome.dtx") ||      # Count the genomes read and errors found.
         Confess("Could not open Genome output file in $outDirectory.");  
     # Count the genomes read.  
396      my $genomeCount = 0;      my $genomeCount = 0;
397        my $errorCount = 0;
398      # Loop through the input.      # Loop through the input.
399      while (my $genomeData = <GENOMESIN>) {      while (my $genomeData = <GENOMESIN>) {
400          # Echo the genome record to the output.          # Echo the genome record to the output.
401          print GENOMESOUT $genomeData;          my @fields = Tracer::ParseRecord($genomeData);
402            print GENOMESOUT join("\t", @fields, $groupName). "\n";
403          # Extract the genome ID.          # Extract the genome ID.
404          my ($genomeID) = Tracer::ParseRecord($genomeData);          my $genomeID = $fields[0];
405          # Store it in the genomes hash. We start with a value of 0. If          # Store it in the genomes hash. We start with a value of 0. If
406          # contig information for the genome is found, we change the value          # contig information for the genome is found, we change the value
407          # to 1. When we're all done with the regions, we can check the          # to 1. When we're all done with the regions, we can check the
# Line 336  Line 410 
410          # Count this genome.          # Count this genome.
411          $genomeCount++;          $genomeCount++;
412      }      }
413      Output("$genomeCount genomes found.");      Trace("$genomeCount genomes found.") if T(2);
414      # Close the files.      # Close the files.
415      close GENOMESIN;      close GENOMESIN;
416      close GENOMESOUT;      close GENOMESOUT;
# Line 347  Line 421 
421      # are sorted by block ID, so all processing for this section of the      # are sorted by block ID, so all processing for this section of the
422      # script is done a block at a time. The first task is to      # script is done a block at a time. The first task is to
423      # open the output files.      # open the output files.
424      (open BLOCKSOUT, ">$outDirectory/GroupBlock.dtx") ||      Open(\*BLOCKSOUT, ">>$outDirectory/GroupBlock.dtx");
425          Confess("Could not open block output file in $outDirectory.");      Open(\*REGIONSOUT, ">>$outDirectory/Region.dtx");
426      (open REGIONSOUT, ">$outDirectory/Region.dtx") ||      Open(\*INSTANCESOUT, ">>$outDirectory/HasInstanceOf.dtx");
427          Confess("Could not open region output file in $outDirectory.");      Open(\*CONTAINSOUT, ">>$outDirectory/ContainsRegion.dtx");
428      (open INSTANCESOUT, ">$outDirectory/HasInstanceOf.dtx") ||      Open(\*INCLUDESOUT, ">>$outDirectory/IncludesRegion.dtx");
         Confess("Could not open instance output file in $outDirectory.");  
     (open CONTAINSOUT, ">$outDirectory/ContainsRegion.dtx") ||  
         Confess("Could not open contig-region output file in $outDirectory.");  
     (open INCLUDESOUT, ">$outDirectory/IncludesRegion.dtx") ||  
         Confess("Could not open block-region output file in $outDirectory.");  
429      # Determine which file sets we'll be processing.      # Determine which file sets we'll be processing.
430      my @fileSets = ();      my @fileSets = ();
431      my @prefixes = ("", "InterGenic_");      my @prefixes = ("", "intergenic_");
432      for my $prefix (@prefixes) {      for my $prefix (@prefixes) {
433          if (-e "$inDirectory/${prefix}Block.tbl") {          if (-e "$inDirectory/${prefix}block.tbl") {
434              push @fileSets, $prefix;              push @fileSets, $prefix;
435          }          }
436      }      }
437        # Set up the duplicate-region check.
438        my %allRegions = ();
439      # Set up some counters.      # Set up some counters.
440      my ($blocksCount, $regionsCount) = (0, 0);      my ($blocksCount, $regionsCount) = (0, 0);
441      # Loop through the useful file sets.      # Loop through the useful file sets.
442      for my $fileSet (@fileSets) {      for my $fileSet (@fileSets) {
443          (open BLOCKSIN, "<$inDirectory/${fileSet}Block.tbl") ||          Open(\*BLOCKSIN, "<$inDirectory/${fileSet}block.tbl");
444              Confess("Could not open block input file in $inDirectory.");          Open(\*REGIONSIN, "<$inDirectory/${fileSet}region.tbl");
445          (open REGIONSIN, "<$inDirectory/${fileSet}Region.tbl") ||          Trace("Processing ${fileSet}Blocks.") if T(2);
             Confess("Could not open region input file in $inDirectory.");  
         Output("Processing ${fileSet}Blocks.");  
446          # The outer loop processes blocks. This is accomplished by reading          # The outer loop processes blocks. This is accomplished by reading
447          # through the block file. We prime the loop by reading the first          # through the block file. We prime the loop by reading the first
448          # region record. This is because we finish processing a block when          # region record. This is because we finish processing a block when
# Line 403  Line 472 
472                  # If this region's block ID is invalid, complain                  # If this region's block ID is invalid, complain
473                  # and skip it.                  # and skip it.
474                  if ($regionRecord{blockID} != $blockID) {                  if ($regionRecord{blockID} != $blockID) {
475                      Output("Block $regionRecord{blockID} in region record $regionsCount not found in block input file at record $blocksCount.");                      Trace("Block $regionRecord{blockID} in region record $regionsCount not found in block input file at record $blocksCount.") if T(0);
476                      $errorCount++;                      $errorCount++;
477                  } else {                  } else {
478                      # Here both files are in sync, which is good. The next step is                      # Here both files are in sync, which is good. The next step is
# Line 411  Line 480 
480                      my $genomeID = $regionRecord{genomeID};                      my $genomeID = $regionRecord{genomeID};
481                      my $contigID = "$genomeID:$regionRecord{contigID}";                      my $contigID = "$genomeID:$regionRecord{contigID}";
482                      if (! exists $genomes{$genomeID}) {                      if (! exists $genomes{$genomeID}) {
483                          Output("Genome $genomeID in region record $regionsCount not found in genome input file.");                          Trace("Genome $genomeID in region record $regionsCount not found in genome input file.") if T(0);
484                          $errorCount++;                          $errorCount++;
485                      } else {                      } else {
486                          # Denote this genome has an instance of this block.                          # Denote this genome has an instance of this block.
# Line 435  Line 504 
504                              $blockData{len} = length $snippet;                              $blockData{len} = length $snippet;
505                          } elsif ($blockData{len} != length $snippet) {                          } elsif ($blockData{len} != length $snippet) {
506                              # Here it is not the first, but the lengths do not match.                              # Here it is not the first, but the lengths do not match.
507                              Output("Snippet for region record $regionsCount does not match block length $blockData{len}.");                              Trace("Snippet for region record $regionsCount does not match block length $blockData{len}.") if T(0);
508                              $errorCount++;                              $errorCount++;
509                          } else {                          } else {
510                              # Here everything is legitimate, so we merge the new                              # Here everything is legitimate, so we merge the new
# Line 453  Line 522 
522              # We have now processed all the regions in the block. Insure we found at least              # We have now processed all the regions in the block. Insure we found at least
523              # one.              # one.
524              if (! $regionCounter) {              if (! $regionCounter) {
525                  Output("No regions found for block $blockID at $blocksCount in block input file.");                  Trace("No regions found for block $blockID at $blocksCount in block input file.") if T(0);
526                  $errorCount++;                  $errorCount++;
527              } else {              } else {
528                  Trace("$regionCounter regions found in block $blockID.") if T(2);                  Trace("$regionCounter regions found in block $blockID.") if T(4);
529                  # Write the block record.                  # Write the block record. Note that the block ID is prefixed by the group name to
530                    # make it unique.
531                  my $variance = $blockData{"snip-count"} / $blockData{len};                  my $variance = $blockData{"snip-count"} / $blockData{len};
532                  print BLOCKSOUT join("\t", $blockID, $blockData{description}, $blockData{len},                  print BLOCKSOUT join("\t", "$groupName:$blockID", $blockData{description}, $blockData{len},
533                                       $blockData{"snip-count"}, $variance, $blockData{pattern}) . "\n";                                       $blockData{"snip-count"}, $variance, $blockData{pattern}) . "\n";
534                  # Find all the variance points in the block pattern. We'll use them to create                  # Find all the variance points in the block pattern. We'll use them to create
535                  # the content strings for each region.                  # the content strings for each region.
536                  my @positions = SimBlocks::ParsePattern($blockData{pattern});                  my @positions = SimBlocks::ParsePattern($blockData{pattern});
537                  # Loop through the regions, writing them out to the region output file.                  # Loop through the regions, writing them out to the region output file.
538                  for my $region (keys %regionMap) {                  for my $region (keys %regionMap) {
539                        if (length($region) > 80) {
540                            Trace("Invalid region key \"$region\".") if T(1);
541                        }
542                      # Get the region's snips.                      # Get the region's snips.
543                      my $source = $regionMap{$region};                      my $source = $regionMap{$region};
544                      my $content = "";                      my $content = "";
# Line 476  Line 549 
549                      my $location = BasicLocation->new($region);                      my $location = BasicLocation->new($region);
550                      # Write this region to the output files.                      # Write this region to the output files.
551                      print REGIONSOUT join("\t", $region, $location->Contig, $location->Dir,                      print REGIONSOUT join("\t", $region, $location->Contig, $location->Dir,
552                                            $location->Length, $regionPeg{$region},                                            $location->Right, $location->Length,
553                                            $location->Left, $content) . "\n";                                            $regionPeg{$region}, $location->Left, $content) . "\n";
554                      print CONTAINSOUT join("\t", $location->Contig, $region,                      print CONTAINSOUT join("\t", $location->Contig, $region,
555                                             $location->Length, $location->Left) . "\n";                                             $location->Length, $location->Left) . "\n";
556                      print INCLUDESOUT join("\t", $blockID, $region);                      print INCLUDESOUT join("\t", "$groupName:$blockID", $region) . "\n";
557                  }                  }
558                  # Finally, we need to connect this block to the genomes in which it occurs.                  # Finally, we need to connect this block to the genomes in which it occurs.
559                  for my $genomeID (keys %genomesFound) {                  for my $genomeID (keys %genomesFound) {
560                      print INSTANCESOUT join("\t", $genomeID, $blockID) . "\n";                      print INSTANCESOUT join("\t", $genomeID, "$groupName:$blockID") . "\n";
561                  }                  }
562                  # Count this block's regions.                  # Count this block's regions.
563                  $regionsCount += $regionCounter;                  $regionsCount += $regionCounter;
# Line 499  Line 572 
572      close BLOCKSOUT;      close BLOCKSOUT;
573      close INSTANCESOUT;      close INSTANCESOUT;
574      # All the block data has been written. Tell the user what we found.      # All the block data has been written. Tell the user what we found.
575      Output("$blocksCount blocks processed, $regionsCount regions processed.");      Trace("$blocksCount blocks processed, $regionsCount regions processed.") if T(2);
576      # The next task is to write the genome/contig data. This is provided by the      # The next task is to write the genome/contig data. This is provided by the
577      # "%contigs" hash. First, we need to open the files.      # "%contigs" hash. First, we need to open the files.
578      my $contigsCount = 0;      my $contigsCount = 0;
579      (open CONTIGSOUT, ">$outDirectory/Contig.dtx") ||      Open(\*CONTIGSOUT, ">>$outDirectory/Contig.dtx");
580          Confess("Could not open contig output file in $outDirectory.");      Open(\*CONSISTSOUT, ">>$outDirectory/ConsistsOf.dtx");
     (open CONSISTSOUT, ">$outDirectory/ConsistsOf.dtx") ||  
         Confess("Could not open consists output file in $outDirectory.");  
581      for my $contigID (keys %contigs) {      for my $contigID (keys %contigs) {
582          print CONTIGSOUT "$contigID\n";          print CONTIGSOUT "$contigID\n";
583          print CONSISTSOUT join("\t", $contigs{$contigID}, $contigID) . "\n";          print CONSISTSOUT join("\t", $contigs{$contigID}, $contigID) . "\n";
584          $contigsCount++;          $contigsCount++;
585      }      }
586      Output("$contigsCount contigs found.");      Trace("$contigsCount contigs found.") if T(2);
587        # Close the output files.
588        close CONTIGSOUT;
589        close CONSISTSOUT;
590      # Now warn the user about all the genomes that didn't have blocks.      # Now warn the user about all the genomes that didn't have blocks.
591      for my $genomeID (keys %genomes) {      for my $genomeID (keys %genomes) {
592          if (! $genomes{$genomeID}) {          if (! $genomes{$genomeID}) {
593              Output("Genome $genomeID did not have any regions.");              Trace("Genome $genomeID did not have any regions.") if T(1);
594              $errorCount++;              $errorCount++;
595          }          }
596      }      }
597  }      return $errorCount;
 # Check for errors.  
 if ($errorCount > 0) {  
     Output("$errorCount errors found in input files.");  
 } else {  
     # No errors, so it's okay to load the database.  
     if ($options->{load} eq 'yes') {  
         # Here we have no outstanding errors and the user wants us to load  
         # the database. First, we create a similarity block object.  
         my $simBlocks = SimBlocks->new();  
         # Use it to load the database. Note we specify that the tables are to be  
         # dropped and rebuilt.  
         $simBlocks->LoadTables($outDirectory, 1);  
         Output("Database loaded.");  
     }  
598  }  }
599  # Tell the user we're done.  # Tell the user we're done.
600  Output("Processing complete.");  Trace("Processing complete.") if T(0);
601    
602  # Read a region record from the file and parse it into a hash  # Read a region record from the file and parse it into a hash
603  # for return to the caller. If we reach end-of-file, the  # for return to the caller. If we reach end-of-file, the
# Line 562  Line 622 
622      return %retVal;      return %retVal;
623  }  }
624    
 # Write an output line. The output line will be traced at level 0. If  
 # $TracingToFile is set, it will be echoed to the standard output.  
 sub Output {  
     my ($message) = @_;  
     Trace($message) if T(0);  
     if ($TracingToFile) {  
         print "$message\n";  
     }  
 }  
   
625  1;  1;

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

MCS Webmaster
ViewVC Help
Powered by ViewVC 1.0.3