PageRenderTime 35ms CodeModel.GetById 0ms RepoModel.GetById 0ms app.codeStats 1ms

/scripts/batch_hmmer.pl

http://dawg-paws.googlecode.com/
Perl | 763 lines | 657 code | 28 blank | 78 comment | 23 complexity | ac66e6714dd82e1fb0d7e352644720d9 MD5 | raw file
  1. #!/usr/bin/perl -w
  2. #-----------------------------------------------------------+
  3. # |
  4. # batch_hmmer.pl - Run hmmer searches in batch mode. |
  5. # |
  6. #-----------------------------------------------------------+
  7. # |
  8. # AUTHOR: James C. Estill |
  9. # CONTACT: JamesEstill_@_gmail.com |
  10. # STARTED: 09/17/2007 |
  11. # UPDATED: 09/19/2007 |
  12. # |
  13. # DESCRIPTION: |
  14. # Run hmmer against repeat hmmer models in batch mode, |
  15. # produce results in gff format if requested. |
  16. # |
  17. # VERSION: $Rev: 276 $ |
  18. # |
  19. # LICENSE: |
  20. # GNU General Public License, Version 3 |
  21. # http://www.gnu.org/licenses/gpl.html |
  22. # |
  23. #-----------------------------------------------------------+
  24. #
  25. # TO DO:
  26. # CONFIG FILE CAN INCLUDE
  27. # Name for the paramter set
  28. # Folder containing the models for this set
  29. # ie Mites, Mules, LTRS, etc.
  30. # -A Limit to n best domains
  31. # -E Evalue cutoff
  32. # -T T bit threshold
  33. # -Z # seqs for E-Value calc
  34. package DAWGPAWS;
  35. #-----------------------------+
  36. # INCLUDES |
  37. #-----------------------------+
  38. use strict;
  39. use Getopt::Long;
  40. use Bio::Tools::HMMER::Results;# Bioperl HMMER results parser
  41. use Text::Wrap; # Allows word wrapping and hanging indents
  42. # for more readable output for long strings.
  43. #-----------------------------+
  44. # PROGRAM VARIABLES |
  45. #-----------------------------+
  46. my ($VERSION) = q$Rev: 276 $ =~ /(\d+)/;
  47. #-----------------------------+
  48. # VARIABLE SCOPE |
  49. #-----------------------------+
  50. my $indir;
  51. my $outdir;
  52. my $config_file;
  53. my $name_root; # Root name of the sequence file
  54. my $i;
  55. # Array of rephmmer parameters
  56. my @bh_params = (); # Batch hmmer parameters
  57. # Booleans
  58. my $quiet = 0;
  59. my $do_gff = 0;
  60. my $test = 0;
  61. my $verbose = 0;
  62. my $show_help = 0;
  63. my $show_usage = 0;
  64. my $show_man = 0;
  65. my $show_version = 0;
  66. # Counters
  67. my $file_num = 0;
  68. #-----------------------------+
  69. # COMMAND LINE OPTIONS |
  70. #-----------------------------+
  71. my $ok = GetOptions(# REQUIRED OPTIONS
  72. "i|indir=s" => \$indir,
  73. "o|outdir=s" => \$outdir,
  74. "c|config=s" => \$config_file,
  75. # ADDITIONAL OPTIONS
  76. "gff" => \$do_gff,
  77. "q|quiet" => \$quiet,
  78. "verbose" => \$verbose,
  79. "test" => \$test,
  80. # ADDITIONAL INFORMATION
  81. "usage" => \$show_usage,
  82. "version" => \$show_version,
  83. "man" => \$show_man,
  84. "h|help" => \$show_help,);
  85. #-----------------------------+
  86. # SHOW REQUESTED HELP |
  87. #-----------------------------+
  88. if ($show_usage) {
  89. print_help("");
  90. }
  91. if ($show_help || (!$ok) ) {
  92. print_help("full");
  93. }
  94. if ($show_version) {
  95. print "\n$0:\nVersion: $VERSION\n\n";
  96. exit;
  97. }
  98. if ($show_man) {
  99. # User perldoc to generate the man documentation.
  100. system("perldoc $0");
  101. exit($ok ? 0 : 2);
  102. }
  103. # Throw error if required arguments not present
  104. if ( (!$indir) || (!$outdir) || (!$config_file) ) {
  105. print "\a";
  106. print STDERR "ERROR: An input directory must be specified" if !$indir;
  107. print STDERR "ERROR: An output directory must be specified" if !$outdir;
  108. print STDERR "ERROR: A config file must be specified" if !$config_file;
  109. print_help("full");
  110. exit;
  111. }
  112. #-----------------------------------------------------------+
  113. # MAIN PROGRAM BODY |
  114. #-----------------------------------------------------------+
  115. #-----------------------------+
  116. # CHECK FOR SLASH IN DIR |
  117. # VARIABLES |
  118. #-----------------------------+
  119. # If the indir does not end in a slash then append one
  120. # TO DO: Allow for backslash
  121. unless ($indir =~ /\/$/ ) {
  122. $indir = $indir."/";
  123. }
  124. unless ($outdir =~ /\/$/ ) {
  125. $outdir = $outdir."/";
  126. }
  127. #-----------------------------+
  128. # CREATE THE OUT DIR |
  129. # IF IT DOES NOT EXIST |
  130. #-----------------------------+
  131. unless (-e $outdir) {
  132. print "Creating output dir ...\n" if $verbose;
  133. mkdir $outdir ||
  134. die "Could not create the output directory:\n$outdir";
  135. }
  136. #-----------------------------+
  137. # LOAD THE CONFIG FILE |
  138. #-----------------------------+
  139. $i=0;
  140. my $config_line_num=0;
  141. open (CONFIG, "<$config_file") ||
  142. die "ERROR Can not open the config file:\n $config_file";
  143. while (<CONFIG>) {
  144. chomp;
  145. $config_line_num++;
  146. unless (m/^\#/) {
  147. my @in_line = split (/\t/); # Implicit split of $_ by tab
  148. my $num_in_line = @in_line;
  149. if ($num_in_line == 3) {
  150. $bh_params[$i][0] = $in_line[0] || "NULL"; # Name
  151. $bh_params[$i][1] = $in_line[1] || "NULL"; # HMMER model dir
  152. $bh_params[$i][2] = $in_line[2] || "NULL"; # HMMER suffix
  153. $i++;
  154. if ($verbose) {
  155. print STDERR "NAME:\t".$bh_params[$i][0]."\n";
  156. print STDERR "DIR:\t".$bh_params[$i][1]."\n";
  157. print STDERR "".$bh_params[$i][2]."\n";
  158. } # End of if verbose
  159. }
  160. else {
  161. print "\a";
  162. print STDERR "WARNING: Unexpected number of lines in config".
  163. " file line $config_line_num\n$config_file\n";
  164. }
  165. } # End of unless comment line
  166. } # End of while CONFIG file
  167. close CONFIG;
  168. # Number of parameter sets specified in the config file
  169. my $num_par_sets = $i;
  170. if ($num_par_sets == 0) {
  171. print "\a";
  172. print "No parameter sets were found in the config file:\n";
  173. print "$config_file\n\n";
  174. print "batch_hmmer.pl --man \n";
  175. print "to see how to format configuration files\n";
  176. exit;
  177. }
  178. #-----------------------------+
  179. # Get the FASTA files from the|
  180. # directory provided by the |
  181. # var $indir |
  182. #-----------------------------+
  183. opendir( DIR, $indir ) ||
  184. die "Can't open directory:\n$indir";
  185. my @fasta_files = grep /\.fasta$|\.fa$/, readdir DIR ;
  186. closedir( DIR );
  187. my $num_files = @fasta_files;
  188. if ($num_files == 0) {
  189. print "\a";
  190. print "No fasta files were found in the input direcotry:\n";
  191. print "$indir\n";
  192. print "Fasta file MUST have the fasta or fa extension to be".
  193. " recognized as fasta files\n";
  194. exit;
  195. }
  196. my $num_proc_total = $num_files * $num_par_sets;
  197. #-----------------------------+
  198. # RUN hmmsearch FOR EACH OF |
  199. # THE FASTA FILES IN THE |
  200. # INPUT DIRECTORY |
  201. #-----------------------------+
  202. for my $ind_file (@fasta_files)
  203. {
  204. $file_num++;
  205. # Get root name
  206. if ($ind_file =~ m/(.*)\.fasta$/ ) {
  207. $name_root = "$1";
  208. }
  209. elsif ($ind_file =~ m/(.*)\.fasta$/ ) {
  210. $name_root = "$1";
  211. }
  212. else {
  213. $name_root = "UNDEFINED";
  214. }
  215. #-----------------------------+
  216. # MAKE OUTPUT DIR |
  217. #-----------------------------+
  218. # The base output dir for the BAC
  219. my $bac_out_dir = $outdir.$name_root."/";
  220. mkdir $bac_out_dir, 0777 unless (-e $bac_out_dir);
  221. #-----------------------------+
  222. # MAKE HMMER OUTPUT DIR |
  223. #-----------------------------+
  224. # dir for the repeat maske output
  225. my $hmmer_out_dir = "$bac_out_dir"."hmmer/";
  226. mkdir $hmmer_out_dir, 0777 unless (-e $hmmer_out_dir);
  227. #-----------------------------+
  228. # MAKE GFF OUTPUT DIR |
  229. #-----------------------------+
  230. my $gff_out_dir = "$bac_out_dir"."gff/";
  231. mkdir $gff_out_dir, 0777 unless (-e $gff_out_dir);
  232. my $file_to_search = $indir.$ind_file;
  233. #-----------------------------+
  234. # FOR EACH PARAM SET IN THE |
  235. # bh_params ARRAY |
  236. #-----------------------------+
  237. for ($i=0; $i<$num_par_sets; $i++) {
  238. my $hmm_par_name = $bh_params[$i][0];
  239. my $hmm_par_model_dir = $bh_params[$i][1];
  240. my $hmm_par_suffix = $bh_params[$i][2];
  241. #my $hmm_out_path = $hmmer_out_dir.$name_root."_hmm_".
  242. # $hmm_par_name.".hmmout";
  243. my $hmm_in_path = $indir.$ind_file;
  244. #-----------------------------+
  245. # CREATE DIR TO HOLD PARAMETER|
  246. # SET HMMSEARCH OUTPUT |
  247. #-----------------------------+
  248. my $hmmer_par_out_dir = $hmmer_out_dir.$hmm_par_name."/";
  249. mkdir $hmmer_par_out_dir, 0777 unless (-e $hmmer_par_out_dir);
  250. run_hmmer( $name_root, $file_to_search, $hmm_par_model_dir,
  251. # $hmm_par_suffix, $hmmer_out_dir, $hmm_par_name);
  252. $hmm_par_suffix, $hmmer_par_out_dir, $hmm_par_name);
  253. if ($do_gff) {
  254. my $gff_out_path = $gff_out_dir.$name_root."_hmm_".
  255. $hmm_par_name.".gff";
  256. # 0 at end indicates to not append to an existing gff
  257. hmmer2gff ($hmmer_par_out_dir, $gff_out_path, 0,
  258. $name_root, $hmm_par_name);
  259. } # End of if $do_gff
  260. } # End for each i in the bh_params array
  261. } # End of for each ind_file in the fasta_files array
  262. exit;
  263. #-----------------------------------------------------------+
  264. # SUBFUNCTIONS |
  265. #-----------------------------------------------------------+
  266. sub print_help {
  267. # Print requested help or exit.
  268. # Options are to just print the full
  269. my ($opt) = @_;
  270. my $usage = "USAGE:\n".
  271. "MyProg.pl -i InFile -o OutFile";
  272. my $args = "REQUIRED ARGUMENTS:\n".
  273. " --infile # Path to the input file\n".
  274. " --outfile # Path to the output file\n".
  275. "\n".
  276. "OPTIONS::\n".
  277. " --version # Show the program version\n".
  278. " --usage # Show program usage\n".
  279. " --help # Show this help message\n".
  280. " --man # Open full program manual\n".
  281. " --quiet # Run program with minimal output\n";
  282. if ($opt =~ "full") {
  283. print "\n$usage\n\n";
  284. print "$args\n\n";
  285. }
  286. else {
  287. print "\n$usage\n\n";
  288. }
  289. exit;
  290. }
  291. sub run_hmmer {
  292. # Run the HMMER program for a set of models
  293. #-----------------------------+
  294. # VARS PASSED TO THE SUBFUN |
  295. #-----------------------------+
  296. my ($seq_name, $seq_path, $model_dir, $hmm_suffix,
  297. $out_dir, $par_name) = @_;
  298. # $seq_name # name of the seq record id HEX0014K09
  299. # $seq_path # Path to the seq
  300. # $model_dir # Path to the dir containing the seq models
  301. # $hmm_suffix # Options to add to the hmmsearch command line
  302. # # May need to chomp the suffix
  303. # $out_dir # Out dir for the location of the hmm out files
  304. # $par_name # Name given to the hmm parameter set
  305. # Append slash to end of model_dir if needed
  306. unless ($model_dir =~ /\/$/ ) {
  307. $model_dir = $model_dir."/";
  308. }
  309. unless ($out_dir =~ /\/$/ ) {
  310. $out_dir = $out_dir."/";
  311. }
  312. #-----------------------------+
  313. # VAR SCOPE AND INITIALIZE |
  314. #-----------------------------+
  315. my $sub_proc_num = 0; # Process number starts at zero
  316. my $hmm_cmd; # hmmsearch command line
  317. # my $out_path = $out_dir.$seq_name."_hmm_".$par_name.".hmmout";
  318. # Will need to delete an already existing outdir
  319. #-----------------------------+
  320. # OPEN MODEL DIR |
  321. #-----------------------------+
  322. opendir( MODDIR, $model_dir ) ||
  323. die "Can not open the hmm model directory:\n $model_dir\n";
  324. # The following does not search for the hmm extension
  325. # and assumes that all files in this directory are hmm models
  326. my @models = grep !/^\.\.?$/, readdir MODDIR ;
  327. closedir( MODDIR );
  328. my $num_models = @models; # Number of models
  329. for my $ind_model (@models)
  330. {
  331. $sub_proc_num++; # Increment the process number
  332. # Model root name will be used in the naming of files
  333. # default is just the name of the individual model file
  334. # will try to trim off the hmm when it is present
  335. my $model_root_name = $ind_model;
  336. if ($ind_model =~ m/(.*)\.hmm$/) {
  337. $model_root_name = $1;
  338. }
  339. # HMMER MODEL PATH
  340. my $model_path = $model_dir.$ind_model;
  341. my $out_path = $out_dir.$seq_name."_hmm_".$par_name."_".
  342. $model_root_name.".hmmout";
  343. #-----------------------------+
  344. # DOES THE HMM MODEL EXIST |
  345. #-----------------------------+
  346. if ( (-e $model_path) && (-e $seq_path) ) {
  347. print "\nMOD PATH: $model_path\n" if $verbose;
  348. print "SEQ PATH: $seq_path\n" if $verbose;
  349. print "OUT PATH: $out_path\n" if $verbose;
  350. # $hmm_cmd = "hmmsearch " .
  351. # "--domT 2 $model_path $seq_path >$out_path";
  352. # Alternative may be to set a single $out_path
  353. # However, the hmmer parser may have a problem with this
  354. $hmm_cmd = "hmmsearch " .
  355. "--domT 2 $model_path $seq_path >>$out_path";
  356. #-----------------------------+
  357. # PRINT STATUS OF EACH HMM |
  358. # PROCESS |
  359. #-----------------------------+
  360. if ($verbose) {
  361. print "HMM model ".$sub_proc_num." of ".$num_models."\n";
  362. print wrap("\t", "\t", $hmm_cmd );
  363. print "\n";
  364. }
  365. system ($hmm_cmd) if (!$test);
  366. }
  367. else {
  368. # Show error if the model_path or input sequence
  369. # could not be located
  370. unless (-e $model_path) {
  371. print STDERR "ERROR: Can not find model:\n$ind_model\n";
  372. }
  373. unless (-e $seq_path) {
  374. print STDERR "ERROR: Can not find sequense:\n$seq_path\n";
  375. }
  376. } # End of test for existence of model_path and seq_path
  377. } # End of for each database loop
  378. } # End of run hmmer subfunction
  379. sub hmmer2gff {
  380. #-----------------------------+
  381. # PARSE THE OUTPUT FROM A |
  382. # HMMER RUN AGAINST A SET OF |
  383. # HMM PROFILES |
  384. #-----------------------------+
  385. #-----------------------------+
  386. # VARIABLES |
  387. #-----------------------------+
  388. # THE FOLLOWING SHOULD BE PASSED TO THE SUBFUNCTION
  389. my ($hmm_in_dir, $gff_out_path, $append_gff,
  390. $seq_name, $gff_suffix) = @_;
  391. # hmm_in_dir # The directory containing the hmm files
  392. # This will need to be all output for the parameter set
  393. # gff_out_path # Out file for the gff file
  394. # append_gff # Boolean, should the gff file be appended
  395. # By default this will append.
  396. # seq_name # Name of the seq file ie HEX0014K09
  397. # gff_suffix # Suffix to add to the hmmsearch:suffix
  398. # This will be the parameter set name
  399. # Old variables
  400. # my $seq_name = $_[0];
  401. # my $WorkDir = $_[1];
  402. # my $HmmDir = $_[2];
  403. # my $class = $_[3];
  404. # Set to subfun scope
  405. # Added 09/18/2007
  406. my $domain;
  407. my $dataset;
  408. my $tot_res; # Total results
  409. my $BestName = ""; # Name of the best hit
  410. my $FilePath; # The file path for the inidividual HMM output
  411. my $TotRes = '0'; # Total number of results for the sequence
  412. my $BestBit = '0'; # Best BIT Score
  413. my $BestHit; # The name of the Best Hit
  414. my $BestEval = 'null'; # Set scope of this variable
  415. #-----------------------------+
  416. # LOAD FILES TO PARSE INTO |
  417. # THE @hmm_files ARRAAY |
  418. #-----------------------------+
  419. # Currently gets all files in the directory
  420. # May need to create a subdir for each basic model
  421. # parameter set.
  422. unless ($hmm_in_dir =~ /\/$/ ) {
  423. $hmm_in_dir = $hmm_in_dir."/";
  424. }
  425. # THIS CURRENTLY ASSUMES THAT ALL FILES IN hmm_in_dir ARE
  426. # HMMSEARCH OUTPUT FILES
  427. opendir( HMMDIR, $hmm_in_dir ) ||
  428. die "ERROR: Can not open hmm input dir:\n$hmm_in_dir\n";
  429. my @hmm_files = grep !/^\.\.?$/, readdir HMMDIR ;
  430. closedir( HMMDIR );
  431. # Open up an Output file
  432. if ($append_gff) {
  433. open ( GFFOUT, ">>$gff_out_path") ||
  434. die "ERROR: Can not open gff output file:\n$gff_out_path\n";
  435. }
  436. else {
  437. open ( GFFOUT, ">$gff_out_path") ||
  438. die "ERROR: Can not open gff output file:\n$gff_out_path\n";;
  439. }
  440. $tot_res = 0;
  441. #-----------------------------------------------------------+
  442. # FOR EACH FILE IN THE ARRAY OF FILES |
  443. #-----------------------------------------------------------+
  444. for my $ind_file (@hmm_files)
  445. {
  446. my $hmm_in_path = $hmm_in_dir.$ind_file;
  447. # OPEN THE HMM RESULT AS HMMER RESULTS OBJECT
  448. my $hmm_res = new Bio::Tools::HMMER::Results ( -file => $hmm_in_path ,
  449. -type => 'hmmsearch')
  450. || die "Could not open file\n$hmm_in_path\n";
  451. my $num_res = $hmm_res->number;
  452. $tot_res = $tot_res + $num_res;
  453. # ONLY PRINT OUTPUT FOR QUERIES WITH MATCHES
  454. if ($num_res >> 0) #08/07/2006
  455. { #08/07/2006
  456. foreach my $seq ( $hmm_res->each_Set )
  457. {
  458. foreach $domain ( $seq->each_Domain )
  459. {
  460. #my $CurBit = $domain->bits;
  461. my $cur_name = $domain->hmmname;
  462. $cur_name =~ m/.*\/(.*)\.hmm/; # Returns what I want
  463. $cur_name = $1;
  464. # RECORD THE NAME AND SCORE OF THE
  465. # BEST HIT
  466. if ($domain->bits > $BestBit)
  467. {
  468. # ASSUMES BIT SCORE AND E VALUE
  469. # HAVE THE SAME RANK
  470. $BestBit = $domain->bits;
  471. $BestName = $cur_name;
  472. $BestEval = $domain->evalue || "NULL";
  473. }
  474. # Determine the length of the match of the
  475. # element length
  476. #my $dom_len = $domain->end - $domain->start;
  477. my $gff_source = "hmmer:".$gff_suffix;
  478. #-----------------------------+
  479. # PRINT RESULTS TO GFF OUT |
  480. #-----------------------------+
  481. print GFFOUT "$seq_name\t". # Name of sequence
  482. "$gff_source\t". # Source
  483. "transposable element\t". # Feature name
  484. $domain->start."\t". # Feature start
  485. $domain->end."\t". # Feature end
  486. $domain->evalue."\t". # Feature score
  487. ".\t". # Feature strand
  488. ".\t". # Feature frame
  489. "$cur_name\n"; # Feature name
  490. } # End of for each domain in the HMM output file
  491. } # End of if greater then zero hits 08/07/2006
  492. } # End of for each seq in the HMM output file
  493. }
  494. # if ($verbose) {
  495. # print "\n\t===================================\n";
  496. # print "\t$class HMMER RESULT\n";
  497. # print "\t===================================\n";
  498. # print "\tSEQ: \t".$seq_name."\n";
  499. # print "\tDATASET: \t".$dataset."\n";
  500. # print "\tCLASS: \t".$class."\n";
  501. # print "\tTOTAL: \t".$tot_res."\n";
  502. # print "\tBEST HIT: \t".$BestName."\n";
  503. # print "\tBEST BIT: \t".$BestBit."\n";
  504. # print "\tBEST EVAL: \t".$BestEval."\n";
  505. # print "\t===================================\n";
  506. # }
  507. close (GFFOUT);
  508. } # END OF THE CONVERT TO GFF SUBFUNCTION
  509. =head1 NAME
  510. batch_hmmer.pl - Short program description.
  511. =head1 VERSION
  512. This documentation refers to program version $Rev: 276 $
  513. =head1 SYNOPSIS
  514. USAGE:
  515. batch_rephmmer.pl -i InDir -o OutDir
  516. --indir # Path to the input dir containing fasta files
  517. --outdir # Path to the base output directory
  518. =head1 DESCRIPTION
  519. Given a config file describing sets of
  520. =head1 COMMAND LINE ARGUMENTS
  521. =head 2 Required Arguments
  522. =over 2
  523. =item -i,--indir
  524. Path of the input directory. This is the directory that contains
  525. the
  526. =item -o,--outdir
  527. Path of the base output directory.
  528. =back
  529. =head2 Additional Options
  530. =over
  531. =item -q,--quiet
  532. Run the program with minimal output.
  533. =back
  534. =head2 Additional Information
  535. =over 2
  536. =item --version
  537. Show program version.
  538. =item --usage
  539. Short overview of how to use program from command line.
  540. =item --help
  541. Show program usage with summary of options.
  542. =item --man
  543. Show the full program manual. This uses the perldoc command to print the
  544. POD documentation for the program.
  545. =back
  546. =head1 DIAGNOSTICS
  547. The list of error messages that can be generated,
  548. explanation of the problem
  549. one or more causes
  550. suggested remedies
  551. list exit status associated with each error
  552. =head1 CONFIGURATION AND ENVIRONMENT
  553. Names and locations of config files
  554. environmental variables
  555. or properties that can be set.
  556. =head1 DEPENDENCIES
  557. The following software are Perl modules are required for the
  558. batch_hmmer.pl program to work properly.
  559. =head2 Required Software
  560. B<HMMER>
  561. The hmmer program is required: http://hmmer.janelia.org/.
  562. =head2 Required Perl Modules
  563. The following Perl modules are required for this program to function
  564. properly.
  565. =head1 BUGS AND LIMITATIONS
  566. Any known bugs and limitations will be listed here.
  567. =head1 LICENSE
  568. GNU GENERAL PUBLIC LICENSE, Version 3
  569. http://www.gnu.org/licenses/gpl.html
  570. =head1 AUTHOR
  571. James C. Estill E<lt>JamesEstill at gmail.comE<gt>
  572. =head1 HISTORY
  573. STARTED: 09/17/2007
  574. UPDATED: 09/18/2007
  575. VERSION: $Rev: 276 $
  576. =cut
  577. #-----------------------------------------------------------+
  578. # HISTORY |
  579. #-----------------------------------------------------------+
  580. #
  581. # 09/17/2007
  582. # - Program started
  583. # - Basic boilerplate stuff laid out
  584. #
  585. # 10/03/2007
  586. # -