]> git.donarmstrong.com Git - biopieces.git/blob - code_perl/Maasha/BioRun.pm
c54c9ef8c664ce134c6354b5d3a459c3805e0353
[biopieces.git] / code_perl / Maasha / BioRun.pm
1 package Maasha::BioRun;
2
3
4 # Copyright (C) 2007-2009 Martin A. Hansen.
5
6 # This program is free software; you can redistribute it and/or
7 # modify it under the terms of the GNU General Public License
8 # as published by the Free Software Foundation; either version 2
9 # of the License, or (at your option) any later version.
10
11 # This program is distributed in the hope that it will be useful,
12 # but WITHOUT ANY WARRANTY; without even the implied warranty of
13 # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
14 # GNU General Public License for more details.
15
16 # You should have received a copy of the GNU General Public License
17 # along with this program; if not, write to the Free Software
18 # Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
19
20 # http://www.gnu.org/copyleft/gpl.html
21
22
23 # >>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> DESCRIPTION <<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<
24
25
26 # Routines that contains Biopieces which are run.
27
28
29 # >>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>><<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<
30
31
32 use strict;
33 use Data::Dumper;
34 use Getopt::Long qw( :config bundling );
35 use Time::HiRes qw( gettimeofday );
36 use Storable qw( dclone );
37 use Maasha::Biopieces;
38 use Maasha::Config;
39 use Maasha::Common;
40 use Maasha::Filesys;
41 use Maasha::Fasta;
42 use Maasha::Align;
43 use Maasha::Matrix;
44 use Maasha::Match;
45 use Maasha::EMBL;
46 use Maasha::Stockholm;
47 use Maasha::Seq;
48 use Maasha::Patscan;
49 use Maasha::Plot;
50 use Maasha::Calc;
51 use Maasha::UCSC;
52 use Maasha::UCSC::BED;
53 use Maasha::UCSC::Wiggle;
54 use Maasha::NCBI;
55 use Maasha::GFF;
56 use Maasha::TwoBit;
57 use Maasha::Solid;
58 use Maasha::Solexa;
59 use Maasha::SQL;
60 use Maasha::Gwiki;
61
62 use vars qw( @ISA @EXPORT_OK );
63
64 require Exporter;
65
66 @ISA = qw( Exporter );
67
68 use constant {
69     SEQ_NAME => 0,
70     SEQ      => 1,
71 };
72
73
74 # >>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> GLOBALS <<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<
75
76
77 my ( $script, $BP_TMP );
78
79 $script = Maasha::Common::get_scriptname();
80 $BP_TMP = Maasha::Common::get_tmpdir();
81
82
83 # >>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> RUN SCRIPT <<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<
84
85
86 run_script( $script );
87
88
89 # >>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> SUBROUTINES <<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<
90
91
92 sub run_script
93 {
94     # Martin A. Hansen, August 2007.
95
96     # Run a specific script.
97
98     my ( $script,   # script name
99        ) = @_;
100
101     # Returns nothing.
102
103     my ( $t0, $t1, $options, $in, $out );
104
105     Maasha::Biopieces::log_biopiece();
106
107     $t0 = gettimeofday();
108
109     $options = get_options( $script );
110
111     $options->{ "SCRIPT" } = $script;
112
113     $script = "print_usage" if ( -t STDIN and keys %{ $options } <= 1 or $options->{ 'help' } );
114
115     $in  = Maasha::Biopieces::read_stream( $options->{ "stream_in" } );
116     $out = Maasha::Biopieces::write_stream( $options->{ "stream_out" } );
117
118     if    ( $script eq "print_usage" )              { script_print_usage(               $in, $out, $options ) }
119     elsif ( $script eq "read_psl" )                 { script_read_psl(                  $in, $out, $options ) }
120     elsif ( $script eq "read_bed" )                 { script_read_bed(                  $in, $out, $options ) }
121     elsif ( $script eq "read_fixedstep" )           { script_read_fixedstep(            $in, $out, $options ) }
122     elsif ( $script eq "read_blast_tab" )           { script_read_blast_tab(            $in, $out, $options ) }
123     elsif ( $script eq "read_embl" )                { script_read_embl(                 $in, $out, $options ) }
124     elsif ( $script eq "read_stockholm" )           { script_read_stockholm(            $in, $out, $options ) }
125     elsif ( $script eq "read_phastcons" )           { script_read_phastcons(            $in, $out, $options ) }
126     elsif ( $script eq "read_soft" )                { script_read_soft(                 $in, $out, $options ) }
127     elsif ( $script eq "read_gff" )                 { script_read_gff(                  $in, $out, $options ) }
128     elsif ( $script eq "read_2bit" )                { script_read_2bit(                 $in, $out, $options ) }
129     elsif ( $script eq "read_solexa" )              { script_read_solexa(               $in, $out, $options ) }
130     elsif ( $script eq "read_solid" )               { script_read_solid(                $in, $out, $options ) }
131     elsif ( $script eq "read_mysql" )               { script_read_mysql(                $in, $out, $options ) }
132     elsif ( $script eq "read_ucsc_config" )         { script_read_ucsc_config(          $in, $out, $options ) }
133     elsif ( $script eq "assemble_tag_contigs" )     { script_assemble_tag_contigs(      $in, $out, $options ) }
134     elsif ( $script eq "length_seq" )               { script_length_seq(                $in, $out, $options ) }
135     elsif ( $script eq "uppercase_seq" )            { script_uppercase_seq(             $in, $out, $options ) }
136     elsif ( $script eq "analyze_seq" )              { script_analyze_seq(               $in, $out, $options ) }
137     elsif ( $script eq "analyze_tags" )             { script_analyze_tags(              $in, $out, $options ) }
138     elsif ( $script eq "complexity_seq" )           { script_complexity_seq(            $in, $out, $options ) }
139     elsif ( $script eq "oligo_freq" )               { script_oligo_freq(                $in, $out, $options ) }
140     elsif ( $script eq "create_weight_matrix" )     { script_create_weight_matrix(      $in, $out, $options ) }
141     elsif ( $script eq "calc_bit_scores" )          { script_calc_bit_scores(           $in, $out, $options ) }
142     elsif ( $script eq "calc_fixedstep" )           { script_calc_fixedstep(            $in, $out, $options ) }
143     elsif ( $script eq "remove_indels" )            { script_remove_indels(             $in, $out, $options ) }
144     elsif ( $script eq "transliterate_seq" )        { script_transliterate_seq(         $in, $out, $options ) }
145     elsif ( $script eq "transliterate_vals" )       { script_transliterate_vals(        $in, $out, $options ) }
146     elsif ( $script eq "translate_seq" )            { script_translate_seq(             $in, $out, $options ) }
147     elsif ( $script eq "get_genome_align" )         { script_get_genome_align(          $in, $out, $options ) }
148     elsif ( $script eq "get_genome_phastcons" )     { script_get_genome_phastcons(      $in, $out, $options ) }
149     elsif ( $script eq "fold_seq" )                 { script_fold_seq(                  $in, $out, $options ) }
150     elsif ( $script eq "split_seq" )                { script_split_seq(                 $in, $out, $options ) }
151     elsif ( $script eq "split_bed" )                { script_split_bed(                 $in, $out, $options ) }
152     elsif ( $script eq "tile_seq" )                 { script_tile_seq(                  $in, $out, $options ) }
153     elsif ( $script eq "invert_align" )             { script_invert_align(              $in, $out, $options ) }
154     elsif ( $script eq "patscan_seq" )              { script_patscan_seq(               $in, $out, $options ) }
155     elsif ( $script eq "blat_seq" )                 { script_blat_seq(                  $in, $out, $options ) }
156     elsif ( $script eq "soap_seq" )                 { script_soap_seq(                  $in, $out, $options ) }
157     elsif ( $script eq "match_seq" )                { script_match_seq(                 $in, $out, $options ) }
158     elsif ( $script eq "create_vmatch_index" )      { script_create_vmatch_index(       $in, $out, $options ) }
159     elsif ( $script eq "write_align" )              { script_write_align(               $in, $out, $options ) }
160     elsif ( $script eq "write_bed" )                { script_write_bed(                 $in, $out, $options ) }
161     elsif ( $script eq "write_psl" )                { script_write_psl(                 $in, $out, $options ) }
162     elsif ( $script eq "write_fixedstep" )          { script_write_fixedstep(           $in, $out, $options ) }
163     elsif ( $script eq "write_2bit" )               { script_write_2bit(                $in, $out, $options ) }
164     elsif ( $script eq "write_solid" )              { script_write_solid(               $in, $out, $options ) }
165     elsif ( $script eq "write_ucsc_config" )        { script_write_ucsc_config(         $in, $out, $options ) }
166     elsif ( $script eq "head_records" )             { script_head_records(              $in, $out, $options ) }
167     elsif ( $script eq "remove_keys" )              { script_remove_keys(               $in, $out, $options ) }
168     elsif ( $script eq "remove_adaptor" )           { script_remove_adaptor(            $in, $out, $options ) }
169     elsif ( $script eq "remove_mysql_tables" )      { script_remove_mysql_tables(       $in, $out, $options ) }
170     elsif ( $script eq "remove_ucsc_tracks" )       { script_remove_ucsc_tracks(        $in, $out, $options ) }
171     elsif ( $script eq "rename_keys" )              { script_rename_keys(               $in, $out, $options ) }
172     elsif ( $script eq "uniq_vals" )                { script_uniq_vals(                 $in, $out, $options ) }
173     elsif ( $script eq "merge_vals" )               { script_merge_vals(                $in, $out, $options ) }
174     elsif ( $script eq "merge_records" )            { script_merge_records(             $in, $out, $options ) }
175     elsif ( $script eq "compute" )                  { script_compute(                   $in, $out, $options ) }
176     elsif ( $script eq "flip_tab" )                 { script_flip_tab(                  $in, $out, $options ) }
177     elsif ( $script eq "count_records" )            { script_count_records(             $in, $out, $options ) }
178     elsif ( $script eq "random_records" )           { script_random_records(            $in, $out, $options ) }
179     elsif ( $script eq "sort_records" )             { script_sort_records(              $in, $out, $options ) }
180     elsif ( $script eq "count_vals" )               { script_count_vals(                $in, $out, $options ) }
181     elsif ( $script eq "plot_histogram" )           { script_plot_histogram(            $in, $out, $options ) }
182     elsif ( $script eq "plot_lendist" )             { script_plot_lendist(              $in, $out, $options ) }
183     elsif ( $script eq "plot_chrdist" )             { script_plot_chrdist(              $in, $out, $options ) }
184     elsif ( $script eq "plot_karyogram" )           { script_plot_karyogram(            $in, $out, $options ) }
185     elsif ( $script eq "plot_matches" )             { script_plot_matches(              $in, $out, $options ) }
186     elsif ( $script eq "plot_seqlogo" )             { script_plot_seqlogo(              $in, $out, $options ) }
187     elsif ( $script eq "plot_phastcons_profiles" )  { script_plot_phastcons_profiles(   $in, $out, $options ) }
188     elsif ( $script eq "analyze_bed" )              { script_analyze_bed(               $in, $out, $options ) }
189     elsif ( $script eq "analyze_vals" )             { script_analyze_vals(              $in, $out, $options ) }
190     elsif ( $script eq "length_vals" )              { script_length_vals(               $in, $out, $options ) }
191     elsif ( $script eq "sum_vals" )                 { script_sum_vals(                  $in, $out, $options ) }
192     elsif ( $script eq "mean_vals" )                { script_mean_vals(                 $in, $out, $options ) }
193     elsif ( $script eq "median_vals" )              { script_median_vals(               $in, $out, $options ) }
194     elsif ( $script eq "max_vals" )                 { script_max_vals(                  $in, $out, $options ) }
195     elsif ( $script eq "min_vals" )                 { script_min_vals(                  $in, $out, $options ) }
196     elsif ( $script eq "upload_to_ucsc" )           { script_upload_to_ucsc(            $in, $out, $options ) }
197
198     close $in if defined $in;
199     close $out;
200
201     $t1 = gettimeofday();
202
203     print STDERR "Program: $script" . ( " " x ( 25 - length( $script ) ) ) . sprintf( "Run time: %.4f\n", ( $t1 - $t0 ) ) if $options->{ 'verbose' };
204 }
205
206
207 sub get_options
208 {
209     # Martin A. Hansen, February 2008.
210
211     # Gets options from commandline and checks these vigerously.
212
213     my ( $script,     # name of script
214        ) = @_;
215
216     # Returns hash
217
218     my ( %options, @options, $opt, @genomes, $real );
219
220     if ( $script eq "print_usage" )
221     {
222         @options = qw(
223             data_in|i=s
224         );
225     }
226     elsif ( $script eq "read_psl" )
227     {
228         @options = qw(
229             data_in|i=s
230             num|n=s
231         );
232     }
233     elsif ( $script eq "read_bed" )
234     {
235         @options = qw(
236             data_in|i=s
237             cols|c=s
238             num|n=s
239             check|C
240         );
241     }
242     elsif ( $script eq "read_fixedstep" )
243     {
244         @options = qw(
245             data_in|i=s
246             num|n=s
247         );
248     }
249     elsif ( $script eq "read_blast_tab" )
250     {
251         @options = qw(
252             data_in|i=s
253             num|n=s
254         );
255     }
256     elsif ( $script eq "read_embl" )
257     {
258         @options = qw(
259             data_in|i=s
260             num|n=s
261             keys|k=s
262             feats|f=s
263             quals|q=s
264         );
265     }
266     elsif ( $script eq "read_stockholm" )
267     {
268         @options = qw(
269             data_in|i=s
270             num|n=s
271         );
272     }
273     elsif ( $script eq "read_phastcons" )
274     {
275         @options = qw(
276             data_in|i=s
277             num|n=s
278             min|m=s
279             dist|d=s
280             threshold|t=f
281             gap|g=s
282         );
283     }
284     elsif ( $script eq "read_soft" )
285     {
286         @options = qw(
287             data_in|i=s
288             samples|s=s
289             num|n=s
290         );
291     }
292     elsif ( $script eq "read_gff" )
293     {
294         @options = qw(
295             data_in|i=s
296             num|n=s
297         );
298     }
299     elsif ( $script eq "read_2bit" )
300     {
301         @options = qw(
302             data_in|i=s
303             num|n=s
304             no_mask|N
305         );
306     }
307     elsif ( $script eq "read_solexa" )
308     {
309         @options = qw(
310             data_in|i=s
311             num|n=s
312             format|f=s
313             quality|q=s
314         );
315     }
316     elsif ( $script eq "read_solid" )
317     {
318         @options = qw(
319             data_in|i=s
320             num|n=s
321             quality|q=s
322         );
323     }
324     elsif ( $script eq "read_mysql" )
325     {
326         @options = qw(
327             database|d=s
328             query|q=s
329             user|u=s
330             password|p=s
331         );
332     }
333     elsif ( $script eq "read_ucsc_config" )
334     {
335         @options = qw(
336             data_in|i=s
337             num|n=s
338         );
339     }
340     elsif ( $script eq "assemble_tag_contigs" )
341     {
342         @options = qw(
343             check|C
344         );
345     }
346     elsif ( $script eq "calc_fixedstep" )
347     {
348         @options = qw(
349             check|C
350         );
351     }
352     elsif ( $script eq "length_seq" )
353     {
354         @options = qw(
355             no_stream|x
356             data_out|o=s
357         );
358     }
359     elsif ( $script eq "oligo_freq" )
360     {
361         @options = qw(
362             word_size|w=s
363             all|a
364         );
365     }
366     elsif ( $script eq "create_weight_matrix" )
367     {
368         @options = qw(
369             percent|p
370         );
371     }
372     elsif ( $script eq "transliterate_seq" )
373     {
374         @options = qw(
375             search|s=s
376             replace|r=s
377             delete|d=s
378         );
379     }
380     elsif ( $script eq "transliterate_vals" )
381     {
382         @options = qw(
383             keys|k=s
384             search|s=s
385             replace|r=s
386             delete|d=s
387         );
388     }
389     elsif ( $script eq "translate_seq" )
390     {
391         @options = qw(
392             frames|f=s
393         );
394     }
395     elsif ( $script eq "get_genome_align" )
396     {
397         @options = qw(
398             genome|g=s
399             chr|c=s
400             beg|b=s
401             end|e=s
402             len|l=s
403             strand|s=s
404         );
405     }
406     elsif ( $script eq "get_genome_phastcons" )
407     {
408         @options = qw(
409             genome|g=s
410             chr|c=s
411             beg|b=s
412             end|e=s
413             len|l=s
414             flank|f=s
415         );
416     }
417     elsif ( $script eq "split_seq" )
418     {
419         @options = qw(
420             word_size|w=s
421             uniq|u
422         );
423     }
424     elsif ( $script eq "split_bed" )
425     {
426         @options = qw(
427             window_size|w=s
428             step_size|s=s
429         );
430     }
431     elsif ( $script eq "tile_seq" )
432     {
433         @options = qw(
434             identity|i=s
435             supress_indels|s
436         );
437     }
438     elsif ( $script eq "invert_align" )
439     {
440         @options = qw(
441             soft|s
442         );
443     }
444     elsif ( $script eq "patscan_seq" )
445     {
446         @options = qw(
447             patterns|p=s
448             patterns_in|P=s
449             comp|c
450             max_hits|h=s
451             max_misses|m=s
452             genome|g=s
453         );
454     }
455     elsif ( $script eq "blat_seq" )
456     {
457         @options = qw(
458             genome|g=s
459             tile_size|t=s
460             step_size|s=s
461             min_identity|m=s
462             min_score|M=s
463             one_off|o=s
464             ooc|c
465         );
466     }
467     elsif ( $script eq "soap_seq" )
468     {
469         @options = qw(
470             in_file|i=s
471             genome|g=s
472             seed_size|s=s
473             mismatches|m=s
474             gap_size|G=s
475             cpus|c=s
476         );
477     }
478     elsif ( $script eq "match_seq" )
479     {
480         @options = qw(
481             word_size|w=s
482             direction|d=s
483         );
484     }
485     elsif ( $script eq "create_vmatch_index" )
486     {
487         @options = qw(
488             index_name|i=s
489             prefix_length|p=s
490             no_stream|x
491         );
492     }
493     elsif ( $script eq "write_align" )
494     {
495         @options = qw(
496             wrap|w=s
497             no_stream|x
498             no_ruler|R
499             no_consensus|C
500             data_out|o=s
501         );
502     }
503     elsif ( $script eq "write_bed" )
504     {
505         @options = qw(
506             cols|c=s
507             check|C
508             no_stream|x
509             data_out|o=s
510             compress|Z
511         );
512     }
513     elsif ( $script eq "write_psl" )
514     {
515         @options = qw(
516             no_stream|x
517             data_out|o=s
518             compress|Z
519         );
520     }
521     elsif ( $script eq "write_fixedstep" )
522     {
523         @options = qw(
524             no_stream|x
525             data_out|o=s
526             compress|Z
527         );
528     }
529     elsif ( $script eq "write_2bit" )
530     {
531         @options = qw(
532             no_stream|x
533             data_out|o=s
534             no_mask|N
535         );
536     }
537     elsif ( $script eq "write_solid" )
538     {
539         @options = qw(
540             wrap|w=s
541             no_stream|x
542             data_out|o=s
543             compress|Z
544         );
545     }
546     elsif ( $script eq "write_ucsc_config" )
547     {
548         @options = qw(
549             no_stream|x
550             data_out|o=s
551         );
552     }
553     elsif ( $script eq "plot_seqlogo" )
554     {
555         @options = qw(
556             no_stream|x
557             data_out|o=s
558         );
559     }
560     elsif ( $script eq "plot_phastcons_profiles" )
561     {
562         @options = qw(
563             no_stream|x
564             data_out|o=s
565             genome|g=s
566             mean|m
567             median|M
568             flank|f=s
569             terminal|t=s
570             title|T=s
571             xlabel|X=s
572             ylabel|Y=s
573         );
574     }
575     elsif ( $script eq "analyze_vals" )
576     {
577         @options = qw(
578             no_stream|x
579             keys|k=s
580         );
581     }
582     elsif ( $script eq "head_records" )
583     {
584         @options = qw(
585             num|n=s
586         );
587     }
588     elsif ( $script eq "remove_keys" )
589     {
590         @options = qw(
591             keys|k=s
592             save_keys|K=s
593         );
594     }
595     elsif ( $script eq "remove_adaptor" )
596     {
597         @options = qw(
598             adaptor|a=s
599             mismatches|m=s
600             remove|r=s
601             offset|o=s
602         );
603     }
604     elsif ( $script eq "remove_mysql_tables" )
605     {
606         @options = qw(
607             database|d=s
608             tables|t=s
609             keys|k=s
610             user|u=s
611             password|p=s
612             no_stream|x
613         );
614     }
615     elsif ( $script eq "remove_ucsc_tracks" )
616     {
617         @options = qw(
618             database|d=s
619             tracks|t=s
620             keys|k=s
621             config_file|c=s
622             user|u=s
623             password|p=s
624             no_stream|x
625         );
626     }
627     elsif ( $script eq "rename_keys" )
628     {
629         @options = qw(
630             keys|k=s
631         );
632     }
633     elsif ( $script eq "uniq_vals" )
634     {
635         @options = qw(
636             key|k=s
637             invert|i
638         );
639     }
640     elsif ( $script eq "merge_vals" )
641     {
642         @options = qw(
643             keys|k=s
644             delimit|d=s
645         );
646     }
647     elsif ( $script eq "merge_records" )
648     {
649         @options = qw(
650             keys|k=s
651             merge|m=s
652         );
653     }
654     elsif ( $script eq "compute" )
655     {
656         @options = qw(
657             eval|e=s
658         );
659     }
660     elsif ( $script eq "count_records" )
661     {
662         @options = qw(
663             no_stream|x
664             data_out|o=s
665         );
666     }
667     elsif ( $script eq "random_records" )
668     {
669         @options = qw(
670             num|n=s
671         );
672     }
673     elsif ( $script eq "sort_records" )
674     {
675         @options = qw(
676             reverse|r
677             keys|k=s
678         );
679     }
680     elsif ( $script eq "count_vals" )
681     {
682         @options = qw(
683             keys|k=s
684         );
685     }
686     elsif ( $script eq "plot_histogram" )
687     {
688         @options = qw(
689             no_stream|x
690             data_out|o=s
691             terminal|t=s
692             title|T=s
693             xlabel|X=s
694             ylabel|Y=s
695             key|k=s
696             sort|s=s
697         );
698     }
699     elsif ( $script eq "plot_lendist" )
700     {
701         @options = qw(
702             no_stream|x
703             data_out|o=s
704             terminal|t=s
705             title|T=s
706             xlabel|X=s
707             ylabel|Y=s
708             key|k=s
709         );
710     }
711     elsif ( $script eq "plot_chrdist" )
712     {
713         @options = qw(
714             no_stream|x
715             data_out|o=s
716             terminal|t=s
717             title|T=s
718             xlabel|X=s
719             ylabel|Y=s
720         );
721     }
722     elsif ( $script eq "plot_karyogram" )
723     {
724         @options = qw(
725             no_stream|x
726             data_out|o=s
727             genome|g=s
728             feat_color|f=s
729         );
730     }
731     elsif ( $script eq "plot_matches" )
732     {
733         @options = qw(
734             no_stream|x
735             data_out|o=s
736             terminal|t=s
737             title|T=s
738             xlabel|X=s
739             ylabel|Y=s
740             direction|d=s
741         );
742     }
743     elsif ( $script eq "length_vals" )
744     {
745         @options = qw(
746             keys|k=s
747         );
748     }
749     elsif ( $script eq "sum_vals" )
750     {
751         @options = qw(
752             no_stream|x
753             data_out|o=s
754             keys|k=s
755         );
756     }
757     elsif ( $script eq "mean_vals" )
758     {
759         @options = qw(
760             no_stream|x
761             data_out|o=s
762             keys|k=s
763         );
764     }
765     elsif ( $script eq "median_vals" )
766     {
767         @options = qw(
768             no_stream|x
769             data_out|o=s
770             keys|k=s
771         );
772     }
773     elsif ( $script eq "max_vals" )
774     {
775         @options = qw(
776             no_stream|x
777             data_out|o=s
778             keys|k=s
779         );
780     }
781     elsif ( $script eq "min_vals" )
782     {
783         @options = qw(
784             no_stream|x
785             data_out|o=s
786             keys|k=s
787         );
788     }
789     elsif ( $script eq "upload_to_ucsc" )
790     {
791         @options = qw(
792             no_stream|x
793             database|d=s
794             table|t=s
795             short_label|s=s
796             long_label|l=s
797             group|g=s
798             priority|p=f
799             use_score|u
800             visibility|V=s
801             color|c=s
802             check|C
803         );
804     }
805
806     push @options, qw(
807         stream_in|I=s
808         stream_out|O=s
809         verbose|v
810         help|?
811     );
812
813 #    print STDERR Dumper( \@options );
814     
815     GetOptions(
816         \%options,
817         @options,
818     );
819
820 #    print STDERR Dumper( \%options );
821
822     if ( -t STDIN && scalar( keys %options ) == 0 or $options{ "help" } ) {
823         return wantarray ? %options : \%options;
824     }
825
826     $options{ "cols" }      = [ split ",", $options{ "cols" } ]      if defined $options{ "cols" };
827     $options{ "keys" }      = [ split ",", $options{ "keys" } ]      if defined $options{ "keys" };
828     $options{ "no_keys" }   = [ split ",", $options{ "no_keys" } ]   if defined $options{ "no_keys" };
829     $options{ "save_keys" } = [ split ",", $options{ "save_keys" } ] if defined $options{ "save_keys" };
830     $options{ "quals" }     = [ split ",", $options{ "quals" } ]     if defined $options{ "quals" };
831     $options{ "feats" }     = [ split ",", $options{ "feats" } ]     if defined $options{ "feats" };
832     $options{ "frames" }    = [ split ",", $options{ "frames" } ]    if defined $options{ "frames" };
833     $options{ "samples" }   = [ split ",", $options{ "samples" } ]   if defined $options{ "samples" };
834     $options{ "tables" }    = [ split ",", $options{ "tables" } ]    if defined $options{ "tables" };
835     $options{ "tracks" }    = [ split ",", $options{ "tracks" } ]    if defined $options{ "tracks" };
836     
837     # ---- check arguments ----
838
839     if ( $options{ 'data_in' } )
840     {
841         $options{ "files" } = Maasha::Biopieces::getopt_files( $options{ 'data_in' } );
842
843         Maasha::Common::error( qq(Argument to --data_in must be a valid file or fileglob expression) ) if scalar @{ $options{ "files" } } == 0;
844     }
845
846     map { Maasha::Common::error( qq(Argument to --cols must be a whole numbers - not "$_") ) if $_ !~ /^\d+$/ } @{ $options{ "cols" } } if $options{ "cols" };
847
848     # print STDERR Dumper( \%options );
849
850     $real = "beg|end|word_size|wrap|tile_size|len|prefix_length|mismatches|offset|num|skip|cpus|window_size|step_size";
851
852     foreach $opt ( keys %options )
853     {
854         if ( $opt =~ /stream_in|pattern_in|exact_in/ and not -f $options{ $opt } )
855         {
856             Maasha::Common::error( qq(Argument to --$opt must be a valid file or fileglob expression - not "$options{ $opt }") );
857         }
858         elsif ( $opt =~ /$real/ and $options{ $opt } !~ /^\d+$/ )
859         {
860             Maasha::Common::error( qq(Argument to --$opt must be a whole number - not "$options{ $opt }") );
861         }
862         elsif ( $opt =~ /max_hits|max_hits|max_misses|dist|edit_dist|flank|gap|hamming_dist|priority/ and $options{ $opt } !~ /^-?\d+$/ )
863         {
864             Maasha::Common::error( qq(Argument to --$opt must be an integer - not "$options{ $opt }") );
865         }
866         elsif ( $opt =~ /identity|threshold/ and $options{ $opt } !~ /^-?(?:\d+(?:\.\d*)?|\.\d+)$/ )
867         {
868             Maasha::Common::error( qq(Argument to --$opt must be a decimal number - not "$options{ $opt }") );
869         }
870         elsif ( $opt =~ /e_val/ and $options{ $opt } !~ /^([+-]?)(?=\d|\.\d)\d*(\.\d*)?([Ee]([+-]?\d+))?$/ )
871         {
872             Maasha::Common::error( qq(Argument to --$opt must be a float - not "$options{ $opt }") );
873         }
874         elsif ( $opt =~ /strand/ and $options{ $opt } !~ /^(\+|-)$/ )
875         {
876             Maasha::Common::error( qq(Argument to --$opt must be "+" or "-" - not "$options{ $opt }") );
877         }
878         elsif ( $opt eq "genome" )
879         {
880             @genomes = Maasha::Common::ls_dirs( "$ENV{ 'BP_DATA' }/genomes" );
881             map { $_ =~ s/.*\/(.+)$/$1/ } @genomes;
882
883             if ( not grep { $_ =~ /^$options{ $opt }$/ } @genomes ) {
884                 Maasha::Common::error( qq(Genome $options{ $opt } not found in "$ENV{ 'BP_DATA' }/genomes/") );
885             }
886         }
887         elsif ( $opt eq "terminal" and not $options{ $opt } =~ /^(svg|post|dumb|x11)/ )
888         {
889             Maasha::Common::error( qq(Bad --$opt argument "$options{ $opt }") );
890         }
891         elsif ( $opt eq "table" and $options{ $opt } =~ /(-|\.)/ )
892         {
893             Maasha::Common::error( qq(Character '$1' is not allowed in table name: $options{ $opt }) );
894         }
895         elsif ( $opt eq "merge" and $options{ $opt } !~ /^(AandB|AorB|BorA|AnotB|BnotA)$/ )
896         {
897             Maasha::Common::error( qq(Argument to --$opt must be AandB, AorB, BorA, AnotB, or BnotA - not "$options{ $opt }") );
898         }
899         elsif ( $opt eq "format" and $script eq "read_solexa" and $options{ $opt } !~ /octal|decimal/ )
900         {
901             Maasha::Common::error( qq(Argument to --$opt must be octal or decimal - not "$options{ $opt }") );
902         }
903         elsif ( $opt eq "remove" and $script eq "remove_adaptor" and $options{ $opt } !~ /before|after|skip/ )
904         {
905             Maasha::Common::error( qq(Argument to --$opt must be before, after, or skip - not "$options{ $opt }") );
906         }
907     }
908
909     Maasha::Common::error( qq(no --database specified) )                if $script eq "remove_ucsc_tracks"  and not $options{ "database" };
910     Maasha::Common::error( qq(no --index_name specified) )              if $script =~ /create_vmatch_index/ and not $options{ "index_name" };
911     Maasha::Common::error( qq(no --in_file or --genome specified) )     if $script eq "soap_seq" and not $options{ "genome" } and not $options{ "in_file" };
912     Maasha::Common::error( qq(both --in_file and --genome specified) )  if $script eq "soap_seq" and $options{ "genome" } and $options{ "in_file" };
913     Maasha::Common::error( qq(no --genome specified) )                  if $script =~ /get_genome_align|get_genome_phastcons|blat_seq|plot_phastcons_profiles|plot_karyogram/ and not $options{ "genome" };
914     Maasha::Common::error( qq(no --key specified) )                     if $script =~ /plot_lendist|plot_histogram/ and not $options{ "key" };
915     Maasha::Common::error( qq(no --keys speficied) )                    if $script =~ /sort_records|count_vals|sum_vals|mean_vals|median_vals|length_vals/ and not $options{ "keys" };
916
917     if ( $script eq "upload_to_ucsc" )
918     {
919         Maasha::Common::error( qq(no --database specified) ) if not $options{ "database" };
920         Maasha::Common::error( qq(no --table specified) )    if not $options{ "table" };
921     }
922
923     return wantarray ? %options : \%options;
924 }
925
926
927 # >>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> SCRIPTS  <<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<
928
929
930 sub script_print_usage
931 {
932     # Martin A. Hansen, January 2008.
933
934     # Retrieves usage information from file and
935     # prints this nicely formatted.
936
937     my ( $in,        # handle to in stream
938          $out,       # handle to out stream
939          $options,   # options hash
940        ) = @_;
941
942     # Returns nothing.
943
944     my ( $file, $wiki, $lines );
945
946     if ( $options->{ 'data_in' } ) {
947         $file = $options->{ 'data_in' };
948     } else {
949         $file = join "", $ENV{ 'BP_DIR' }, "/bp_usage/", $options->{ 'SCRIPT' }, ".wiki";
950     }
951
952     $wiki = Maasha::Gwiki::gwiki_read( $file );
953
954     ( $wiki->[ 2 ], $wiki->[ 3 ], $wiki->[ 0 ], $wiki->[ 1 ] ) = ( $wiki->[ 0 ], $wiki->[ 1 ], $wiki->[ 2 ], $wiki->[ 3 ] );
955
956     if ( not $options->{ "help" } ) {
957         @{ $wiki } = grep { $_->[ 0 ]->{ 'SECTION' } =~ /Biopiece|summary|Usage|Options|Help/ } @{ $wiki };
958     }
959
960     $lines = Maasha::Gwiki::gwiki2ascii( $wiki );
961
962     print STDERR "$_\n" foreach @{ $lines };
963
964     exit;
965 }
966
967
968 sub script_read_psl
969 {
970     # Martin A. Hansen, August 2007.
971
972     # Read psl table from stream or file.
973
974     my ( $in,        # handle to in stream
975          $out,       # handle to out stream
976          $options,   # options hash
977        ) = @_;
978
979     # Returns nothing.
980
981     my ( $record, $file, $data_in, $num );
982
983     while ( $record = Maasha::Biopieces::get_record( $in ) ) {
984         Maasha::Biopieces::put_record( $record, $out );
985     }
986
987     $num = 1;
988
989     foreach $file ( @{ $options->{ "files" } } )
990     {
991         $data_in = Maasha::Common::read_open( $file );
992
993         while ( $record = Maasha::UCSC::psl_get_entry( $data_in ) ) 
994         {
995             Maasha::Biopieces::put_record( $record, $out );
996
997             goto NUM if $options->{ "num" } and $num == $options->{ "num" };
998
999             $num++;
1000         }
1001     }
1002
1003     NUM:
1004 }
1005
1006
1007 sub script_read_bed
1008 {
1009     # Martin A. Hansen, August 2007.
1010
1011     # Read bed table from stream or file.
1012
1013     my ( $in,        # handle to in stream
1014          $out,       # handle to out stream
1015          $options,   # options hash
1016        ) = @_;
1017
1018     # Returns nothing.
1019
1020     my ( $cols, $file, $record, $bed_entry, $data_in, $num );
1021
1022     $cols = $options->{ 'cols' }->[ 0 ];
1023
1024     while ( $record = Maasha::Biopieces::get_record( $in ) ) {
1025         Maasha::Biopieces::put_record( $record, $out );
1026     }
1027
1028     $num = 1;
1029
1030     foreach $file ( @{ $options->{ "files" } } )
1031     {
1032         $data_in = Maasha::Common::read_open( $file );
1033
1034         while ( $bed_entry = Maasha::UCSC::BED::bed_entry_get( $data_in, $cols, $options->{ 'check' } ) )
1035         {
1036             $record = Maasha::UCSC::BED::bed2biopiece( $bed_entry );
1037
1038             Maasha::Biopieces::put_record( $record, $out );
1039
1040             goto NUM if $options->{ "num" } and $num == $options->{ "num" };
1041
1042             $num++;
1043         }
1044
1045         close $data_in;
1046     }
1047
1048     NUM:
1049
1050     close $data_in if $data_in;
1051 }
1052
1053
1054 sub script_read_fixedstep
1055 {
1056     # Martin A. Hansen, Juli 2008.
1057
1058     # Read fixedstep wiggle format from stream or file.
1059
1060     my ( $in,        # handle to in stream
1061          $out,       # handle to out stream
1062          $options,   # options hash
1063        ) = @_;
1064
1065     # Returns nothing.
1066
1067     my ( $file, $record, $entry, $data_in, $num );
1068
1069     while ( $record = Maasha::Biopieces::get_record( $in ) ) {
1070         Maasha::Biopieces::put_record( $record, $out );
1071     }
1072
1073     $num = 1;
1074
1075     foreach $file ( @{ $options->{ "files" } } )
1076     {
1077         $data_in = Maasha::Common::read_open( $file );
1078
1079         while ( $entry = Maasha::UCSC::Wiggle::fixedstep_entry_get( $data_in ) )
1080         {
1081             $record = Maasha::UCSC::Wiggle::fixedstep2biopiece( $entry );
1082
1083             Maasha::Biopieces::put_record( $record, $out );
1084
1085             goto NUM if $options->{ "num" } and $num == $options->{ "num" };
1086
1087             $num++;
1088         }
1089
1090         close $data_in;
1091     }
1092
1093     NUM:
1094
1095     close $data_in if $data_in;
1096 }
1097
1098
1099 sub script_read_blast_tab
1100 {
1101     # Martin A. Hansen, September 2007.
1102
1103     # Read tabular BLAST output from NCBI blast run with -m8 or -m9.
1104
1105     my ( $in,        # handle to in stream
1106          $out,       # handle to out stream
1107          $options,   # options hash
1108        ) = @_;
1109
1110     # Returns nothing.
1111
1112     my ( $file, $line, @fields, $strand, $record, $data_in, $num );
1113
1114     while ( $record = Maasha::Biopieces::get_record( $in ) ) {
1115         Maasha::Biopieces::put_record( $record, $out );
1116     }
1117
1118     $num = 1;
1119
1120     foreach $file ( @{ $options->{ "files" } } )
1121     {
1122         $data_in = Maasha::Common::read_open( $file );
1123
1124         while ( $line = <$data_in> )
1125         {
1126             chomp $line;
1127
1128             next if $line =~ /^#/;
1129
1130             @fields = split /\t/, $line;
1131
1132             $record->{ "REC_TYPE" }   = "BLAST";
1133             $record->{ "Q_ID" }       = $fields[ 0 ];
1134             $record->{ "S_ID" }       = $fields[ 1 ];
1135             $record->{ "IDENT" }      = $fields[ 2 ];
1136             $record->{ "ALIGN_LEN" }  = $fields[ 3 ];
1137             $record->{ "MISMATCHES" } = $fields[ 4 ];
1138             $record->{ "GAPS" }       = $fields[ 5 ];
1139             $record->{ "Q_BEG" }      = $fields[ 6 ] - 1; # BLAST is 1-based
1140             $record->{ "Q_END" }      = $fields[ 7 ] - 1; # BLAST is 1-based
1141             $record->{ "S_BEG" }      = $fields[ 8 ] - 1; # BLAST is 1-based
1142             $record->{ "S_END" }      = $fields[ 9 ] - 1; # BLAST is 1-based
1143             $record->{ "E_VAL" }      = $fields[ 10 ];
1144             $record->{ "BIT_SCORE" }  = $fields[ 11 ];
1145
1146             if ( $record->{ "S_BEG" } > $record->{ "S_END" } )
1147             {
1148                 $record->{ "STRAND" } = '-';
1149
1150                 ( $record->{ "S_BEG" }, $record->{ "S_END" } ) = ( $record->{ "S_END" }, $record->{ "S_BEG" } );
1151             }
1152             else
1153             {
1154                 $record->{ "STRAND" } = '+';
1155             }
1156
1157             Maasha::Biopieces::put_record( $record, $out );
1158
1159             goto NUM if $options->{ "num" } and $num == $options->{ "num" };
1160
1161             $num++;
1162         }
1163
1164         close $data_in;
1165     }
1166
1167     NUM:
1168
1169     close $data_in if $data_in;
1170 }
1171
1172
1173 sub script_read_embl
1174 {
1175     # Martin A. Hansen, August 2007.
1176
1177     # Read EMBL format.
1178
1179     my ( $in,        # handle to in stream
1180          $out,       # handle to out stream
1181          $options,   # options hash
1182        ) = @_;
1183
1184     # Returns nothing.
1185
1186     my ( %options2, $file, $data_in, $num, $entry, $record );
1187
1188     map { $options2{ "keys" }{ $_ } = 1 }  @{ $options->{ "keys" } };
1189     map { $options2{ "feats" }{ $_ } = 1 } @{ $options->{ "feats" } };
1190     map { $options2{ "quals" }{ $_ } = 1 } @{ $options->{ "quals" } };
1191
1192     while ( $record = Maasha::Biopieces::get_record( $in ) ) {
1193         Maasha::Biopieces::put_record( $record, $out );
1194     }
1195
1196     $num = 1;
1197
1198     foreach $file ( @{ $options->{ "files" } } )
1199     {
1200         $data_in = Maasha::Common::read_open( $file );
1201
1202         while ( $entry = Maasha::EMBL::get_embl_entry( $data_in ) ) 
1203         {
1204             $record = Maasha::EMBL::parse_embl_entry( $entry, \%options2 );
1205
1206             my ( $feat, $feat2, $qual, $qual_val, $record_copy );
1207
1208             $record_copy = dclone $record;
1209
1210             delete $record_copy->{ "FT" };
1211
1212             Maasha::Biopieces::put_record( $record_copy, $out );
1213
1214             delete $record_copy->{ "SEQ" };
1215
1216             foreach $feat ( keys %{ $record->{ "FT" } } )
1217             {
1218                 $record_copy->{ "FEAT_TYPE" } = $feat;
1219
1220                 foreach $feat2 ( @{ $record->{ "FT" }->{ $feat } } )
1221                 {
1222                     foreach $qual ( keys %{ $feat2 } )
1223                     {
1224                         $qual_val = join "; ", @{ $feat2->{ $qual } };
1225
1226                         $qual =~ s/^_//;
1227                         $qual = uc $qual;
1228
1229                         $record_copy->{ $qual } = $qual_val;
1230                     }
1231
1232                     Maasha::Biopieces::put_record( $record_copy, $out );
1233                 }
1234             }
1235
1236             goto NUM if $options->{ "num" } and $num == $options->{ "num" };
1237
1238             $num++;
1239         }
1240
1241         close $data_in;
1242     }
1243
1244     NUM:
1245
1246     close $data_in if $data_in;
1247 }
1248
1249
1250 sub script_read_stockholm
1251 {
1252     # Martin A. Hansen, August 2007.
1253
1254     # Read Stockholm format.
1255
1256     my ( $in,        # handle to in stream
1257          $out,       # handle to out stream
1258          $options,   # options hash
1259        ) = @_;
1260
1261     # Returns nothing.
1262
1263     my ( $data_in, $file, $num, $entry, $record, $record_anno, $record_align, $key, $seq );
1264
1265     while ( $record = Maasha::Biopieces::get_record( $in ) ) {
1266         Maasha::Biopieces::put_record( $record, $out );
1267     }
1268
1269     $num = 1;
1270
1271     foreach $file ( @{ $options->{ "files" } } )
1272     {
1273         $data_in = Maasha::Common::read_open( $file );
1274
1275         while ( $entry = Maasha::Stockholm::get_stockholm_entry( $data_in ) ) 
1276         {
1277             $record = Maasha::Stockholm::parse_stockholm_entry( $entry );
1278
1279             undef $record_anno;
1280
1281             foreach $key ( keys %{ $record->{ "GF" } } ) {
1282                 $record_anno->{ $key } = $record->{ "GF" }->{ $key };
1283             }
1284
1285             $record_anno->{ "ALIGN" } = $num;
1286
1287             Maasha::Biopieces::put_record( $record_anno, $out );
1288
1289             foreach $seq ( @{ $record->{ "ALIGN" } } )
1290             {
1291                 undef $record_align;
1292             
1293                 $record_align = {
1294                     SEQ_NAME  => $seq->[ 0 ],
1295                     SEQ       => $seq->[ 1 ],
1296                 };
1297             
1298                 Maasha::Biopieces::put_record( $record_align, $out );
1299             }
1300
1301             goto NUM if $options->{ "num" } and $num == $options->{ "num" };
1302
1303             $num++;
1304         }
1305
1306         close $data_in;
1307     }
1308
1309     NUM:
1310
1311     close $data_in if $data_in;
1312 }
1313
1314
1315 sub script_read_phastcons
1316 {
1317     # Martin A. Hansen, December 2007.
1318
1319     # Read PhastCons format.
1320
1321     my ( $in,        # handle to in stream
1322          $out,       # handle to out stream
1323          $options,   # options hash
1324        ) = @_;
1325
1326     # Returns nothing.
1327
1328     my ( $data_in, $file, $num, $entry, @records, $record );
1329
1330     $options->{ "min" }       ||= 10;
1331     $options->{ "dist" }      ||= 25;
1332     $options->{ "threshold" } ||= 0.8;
1333     $options->{ "gap" }       ||= 5;
1334
1335     while ( $record = Maasha::Biopieces::get_record( $in ) ) {
1336         Maasha::Biopieces::put_record( $record, $out );
1337     }
1338
1339     $num = 1;
1340
1341     foreach $file ( @{ $options->{ "files" } } )
1342     {
1343         $data_in = Maasha::Common::read_open( $file );
1344
1345         while ( $entry = Maasha::UCSC::fixedstep_get_entry( $data_in ) ) 
1346         {
1347             @records = Maasha::UCSC::phastcons_parse_entry( $entry, $options );
1348
1349             foreach $record ( @records )
1350             {
1351                 $record->{ "REC_TYPE" } = "BED";
1352                 $record->{ "BED_LEN" }  = $record->{ "CHR_END" } - $record->{ "CHR_BEG" } + 1;
1353
1354                 Maasha::Biopieces::put_record( $record, $out );
1355
1356                 goto NUM if $options->{ "num" } and $num == $options->{ "num" };
1357
1358                 $num++;
1359             }
1360         }
1361
1362         close $data_in;
1363     }
1364
1365     NUM:
1366
1367     close $data_in if $data_in;
1368 }
1369
1370
1371 sub script_read_soft
1372 {
1373     # Martin A. Hansen, December 2007.
1374
1375     # Read soft format.
1376     # http://www.ncbi.nlm.nih.gov/geo/info/soft2.html
1377
1378     my ( $in,        # handle to in stream
1379          $out,       # handle to out stream
1380          $options,   # options hash
1381        ) = @_;
1382
1383     # Returns nothing.
1384
1385     my ( $data_in, $file, $num, $records, $record, $soft_index, $fh, @platforms, $plat_table, @samples, $sample, $old_end, $skip );
1386
1387     while ( $record = Maasha::Biopieces::get_record( $in ) ) {
1388         Maasha::Biopieces::put_record( $record, $out );
1389     }
1390
1391     $num = 1;
1392
1393     foreach $file ( @{ $options->{ "files" } } )
1394     {
1395         print STDERR "Creating index for file: $file\n" if $options->{ "verbose" };
1396
1397         $soft_index = Maasha::NCBI::soft_index_file( $file );
1398
1399         $fh         = Maasha::Common::read_open( $file );
1400
1401         @platforms  = grep { $_->{ "SECTION" } =~ /PLATFORM/ } @{ $soft_index };
1402
1403         print STDERR "Getting platform tables for file: $file\n" if $options->{ "verbose" };
1404
1405         $plat_table = Maasha::NCBI::soft_get_platform( $fh, $platforms[ 0 ]->{ "LINE_BEG" }, $platforms[ -1 ]->{ "LINE_END" } );
1406
1407         @samples    = grep { $_->{ "SECTION" } =~ /SAMPLE/ } @{ $soft_index };
1408
1409         $old_end    = $platforms[ -1 ]->{ "LINE_END" };
1410
1411         foreach $sample ( @samples )
1412         {
1413             $skip = 0;
1414             $skip = 1 if ( $options->{ "samples" } and grep { $sample->{ "SECTION" } !~ /$_/ } @{ $options->{ "samples" } } );
1415
1416             print STDERR "Getting samples for dataset: $sample->{ 'SECTION' }\n" if $options->{ "verbose" } and not $skip;
1417
1418             $records = Maasha::NCBI::soft_get_sample( $fh, $plat_table, $sample->{ "LINE_BEG" } - $old_end - 1, $sample->{ "LINE_END" } - $old_end - 1, $skip );
1419
1420             foreach $record ( @{ $records } )
1421             {
1422                 Maasha::Biopieces::put_record( $record, $out );
1423
1424                 goto NUM if $options->{ "num" } and $num == $options->{ "num" };
1425
1426                 $num++;
1427             }
1428
1429             $old_end = $sample->{ "LINE_END" };
1430         }
1431
1432         close $fh;
1433     }
1434
1435     NUM:
1436
1437     close $data_in if $data_in;
1438     close $fh if $fh;
1439 }
1440
1441
1442 sub script_read_gff
1443 {
1444     # Martin A. Hansen, February 2008.
1445
1446     # Read soft format.
1447     # http://www.ncbi.nlm.nih.gov/geo/info/soft2.html
1448
1449     my ( $in,        # handle to in stream
1450          $out,       # handle to out stream
1451          $options,   # options hash
1452        ) = @_;
1453
1454     # Returns nothing.
1455
1456     my ( $data_in, $file, $fh, $num, $record, $entry );
1457
1458     while ( $record = Maasha::Biopieces::get_record( $in ) ) {
1459         Maasha::Biopieces::put_record( $record, $out );
1460     }
1461
1462     $num = 1;
1463
1464     foreach $file ( @{ $options->{ "files" } } )
1465     {
1466         $fh = Maasha::Common::read_open( $file );
1467
1468         while ( $entry = Maasha::GFF::get_entry( $fh ) )
1469         {
1470             Maasha::Biopieces::put_record( $entry, $out );
1471
1472             goto NUM if $options->{ "num" } and $num == $options->{ "num" };
1473
1474             $num++;
1475         }
1476
1477         close $fh;
1478     }
1479
1480     NUM:
1481
1482     close $data_in if $data_in;
1483 }
1484
1485
1486 sub script_read_2bit
1487 {
1488     # Martin A. Hansen, March 2008.
1489
1490     # Read sequences from 2bit file.
1491
1492     my ( $in,        # handle to in stream
1493          $out,       # handle to out stream
1494          $options,   # options hash
1495        ) = @_;
1496
1497     # Returns nothing.
1498
1499     my ( $record, $file, $data_in, $mask, $toc, $line, $num );
1500
1501     $mask = 1 if not $options->{ "no_mask" };
1502
1503     while ( $record = Maasha::Biopieces::get_record( $in ) ) {
1504         Maasha::Biopieces::put_record( $record, $out );
1505     }
1506
1507     $num = 1;
1508
1509     foreach $file ( @{ $options->{ "files" } } )
1510     {
1511         $data_in = Maasha::Common::read_open( $file );
1512
1513         $toc = Maasha::TwoBit::twobit_get_TOC( $data_in );
1514
1515         foreach $line ( @{ $toc } )
1516         {
1517             $record->{ "SEQ_NAME" } = $line->[ 0 ];
1518             $record->{ "SEQ" }      = Maasha::TwoBit::twobit_get_seq( $data_in, $line->[ 1 ], undef, undef, $mask );
1519             $record->{ "SEQ_LEN" }  = length $record->{ "SEQ" };
1520
1521             Maasha::Biopieces::put_record( $record, $out );
1522
1523             goto NUM if $options->{ "num" } and $num == $options->{ "num" };
1524
1525             $num++;
1526         }
1527
1528         close $data_in;
1529     }
1530
1531     NUM:
1532
1533     close $data_in if $data_in;
1534 }
1535
1536
1537 sub script_read_solexa
1538 {
1539     # Martin A. Hansen, March 2008.
1540
1541     # Read Solexa sequence reads from file.
1542
1543     my ( $in,        # handle to in stream
1544          $out,       # handle to out stream
1545          $options,   # options hash
1546        ) = @_;
1547
1548     # Returns nothing.
1549
1550     my ( $record, $file, $data_in, $entry, $num, @seqs, @scores, $i );
1551
1552     $options->{ "format" }  ||= "octal";
1553     $options->{ "quality" } ||= 20;
1554
1555     while ( $record = Maasha::Biopieces::get_record( $in ) ) {
1556         Maasha::Biopieces::put_record( $record, $out );
1557     }
1558
1559     $num = 1;
1560
1561     foreach $file ( @{ $options->{ "files" } } )
1562     {
1563         $data_in = Maasha::Common::read_open( $file );
1564
1565         if ( $options->{ "format" } eq "octal" )
1566         {
1567             while ( $entry = Maasha::Solexa::solexa_get_entry_octal( $data_in ) )
1568             {
1569                 $record = Maasha::Solexa::solexa2biopiece( $entry, $options->{ "quality" } );
1570
1571                 Maasha::Biopieces::put_record( $record, $out );
1572
1573                 goto NUM if $options->{ "num" } and $num == $options->{ "num" };
1574
1575                 $num++;
1576             }
1577         }
1578         else
1579         {
1580             while ( $entry = Maasha::Solexa::solexa_get_entry_decimal( $data_in ) )
1581             {
1582                 $record = Maasha::Solexa::solexa2biopiece( $entry, $options->{ "quality" } );
1583
1584                 Maasha::Biopieces::put_record( $record, $out );
1585
1586                 goto NUM if $options->{ "num" } and $num == $options->{ "num" };
1587
1588                 $num++;
1589             }
1590         }
1591
1592         close $data_in;
1593     }
1594
1595     NUM:
1596
1597     close $data_in if $data_in;
1598 }
1599
1600
1601 sub script_read_solid
1602 {
1603     # Martin A. Hansen, April 2008.
1604
1605     # Read Solid sequence from file.
1606
1607     my ( $in,        # handle to in stream
1608          $out,       # handle to out stream
1609          $options,   # options hash
1610        ) = @_;
1611
1612     # Returns nothing.
1613
1614     my ( $record, $file, $data_in, $line, $num, $seq_name, $seq_cs, $seq_qual, @scores, @seqs, $i );
1615
1616     $options->{ "quality" } ||= 15;
1617
1618     while ( $record = Maasha::Biopieces::get_record( $in ) ) {
1619         Maasha::Biopieces::put_record( $record, $out );
1620     }
1621
1622     $num = 1;
1623
1624     foreach $file ( @{ $options->{ "files" } } )
1625     {
1626         $data_in = Maasha::Common::read_open( $file );
1627
1628         while ( $line = <$data_in> )
1629         {
1630             chomp $line;
1631
1632             ( $seq_name, $seq_cs, $seq_qual ) = split /\t/, $line;
1633
1634             @scores = split /,/, $seq_qual;
1635             @seqs   = split //, Maasha::Solid::color_space2seq( $seq_cs );
1636
1637             for ( $i = 0; $i < @seqs; $i++ ) {
1638                 $seqs[ $i ] = lc $seqs[ $i ] if $scores[ $i ] < $options->{ "quality" };
1639             }
1640
1641             $record = {
1642                 REC_TYPE   => 'SOLID',
1643                 SEQ_NAME   => $seq_name,
1644                 SEQ_CS     => $seq_cs,
1645                 SEQ_QUAL   => join( ";", @scores ),
1646                 SEQ_LEN    => length $seq_cs,
1647                 SEQ        => join( "", @seqs ),
1648                 SCORE_MEAN => sprintf( "%.2f", Maasha::Calc::mean( \@scores ) ),
1649             };
1650
1651             Maasha::Biopieces::put_record( $record, $out );
1652
1653             goto NUM if $options->{ "num" } and $num == $options->{ "num" };
1654
1655             $num++;
1656         }
1657
1658         close $data_in;
1659     }
1660
1661     NUM:
1662
1663     close $data_in if $data_in;
1664 }
1665
1666
1667 sub script_read_mysql
1668 {
1669     # Martin A. Hansen, May 2008.
1670
1671     # Read a MySQL query into stream.
1672
1673     my ( $in,        # handle to in stream
1674          $out,       # handle to out stream
1675          $options,   # options hash
1676        ) = @_;
1677
1678     # Returns nothing.
1679
1680     my ( $record, $dbh, $results );
1681
1682     $options->{ "user" }     ||= Maasha::UCSC::ucsc_get_user();
1683     $options->{ "password" } ||= Maasha::UCSC::ucsc_get_password();
1684
1685     while ( $record = Maasha::Biopieces::get_record( $in ) ) {
1686         Maasha::Biopieces::put_record( $record, $out );
1687     }
1688
1689     $dbh = Maasha::SQL::connect( $options->{ "database" }, $options->{ "user" }, $options->{ "password" } );
1690
1691     $results = Maasha::SQL::query_hashref_list( $dbh, $options->{ "query" } );
1692
1693     Maasha::SQL::disconnect( $dbh );
1694
1695     map { Maasha::Biopieces::put_record( $_ ) } @{ $results };
1696 }
1697
1698
1699 sub script_read_ucsc_config
1700 {
1701     # Martin A. Hansen, November 2008.
1702
1703     # Read track entries from UCSC Genome Browser '.ra' files.
1704
1705     my ( $in,        # handle to in stream
1706          $out,       # handle to out stream
1707          $options,   # options hash
1708        ) = @_;
1709
1710     # Returns nothing.
1711
1712     my ( $record, $file, $data_in, $entry, $num );
1713
1714     while ( $record = Maasha::Biopieces::get_record( $in ) ) {
1715         Maasha::Biopieces::put_record( $record, $out );
1716     }
1717
1718     $num = 1;
1719
1720     foreach $file ( @{ $options->{ "files" } } )
1721     {
1722         $data_in = Maasha::Common::read_open( $file );
1723
1724         while ( $record = Maasha::UCSC::ucsc_config_entry_get( $data_in ) ) 
1725         {
1726             $record->{ 'REC_TYPE' } = "UCSC Config";
1727
1728             Maasha::Biopieces::put_record( $record, $out );
1729
1730             goto NUM if $options->{ "num" } and $num == $options->{ "num" };
1731
1732             $num++;
1733         }
1734
1735         close $data_in;
1736     }
1737
1738     NUM:
1739
1740     close $data_in if $data_in;
1741 }
1742
1743
1744 sub script_assemble_tag_contigs
1745 {
1746     # Martin A. Hansen, November 2008.
1747
1748     # Assemble tags from the stream into
1749     # tag contigs.
1750
1751     # The current implementation is quite
1752     # slow because of heavy use of temporary
1753     # files.
1754
1755     my ( $in,        # handle to in stream
1756          $out,       # handle to out stream
1757          $options,   # options hash
1758        ) = @_;
1759
1760     # Returns nothing.
1761
1762     my ( $bed_file, $tag_file, $fh_in, $fh_out, $cols, $record, $bed_entry, $file_hash, $chr, $strand );
1763     
1764     $bed_file = "$BP_TMP/assemble_tag_contigs.bed";
1765     $fh_out   = Maasha::Filesys::file_write_open( $bed_file );
1766     $cols     = 6; # we only need the first 6 BED columns
1767
1768     while ( $record = Maasha::Biopieces::get_record( $in ) ) 
1769     {
1770         if ( $bed_entry = Maasha::UCSC::BED::biopiece2bed( $record, $cols ) )
1771         {
1772             $strand = $record->{ 'STRAND' } || '+';
1773
1774             Maasha::UCSC::BED::bed_entry_put( $bed_entry, $fh_out, $cols, $options->{ 'check' } );
1775         }
1776     }
1777
1778     close $fh_out;
1779
1780     $file_hash = Maasha::UCSC::BED::bed_file_split_on_chr( $bed_file, $BP_TMP, $cols );
1781
1782     unlink $bed_file;
1783
1784     foreach $chr ( sort keys %{ $file_hash } )
1785     {
1786         $bed_file = $file_hash->{ $chr };
1787         $tag_file = "$bed_file.tc";
1788
1789         Maasha::Common::run( "bed2tag_contigs", "< $bed_file > $tag_file" );
1790
1791         $fh_in = Maasha::Filesys::file_read_open( $tag_file );
1792
1793         while ( $bed_entry = Maasha::UCSC::BED::bed_entry_get( $fh_in, $cols, $options->{ 'check' } ) )
1794         {
1795             if ( $record = Maasha::UCSC::BED::bed2biopiece( $bed_entry ) ) {
1796                 Maasha::Biopieces::put_record( $record, $out );
1797             }
1798         }
1799
1800         close $fh_in;
1801
1802         unlink $bed_file;
1803         unlink $tag_file;
1804     }
1805 }
1806
1807
1808 sub script_length_seq
1809 {
1810     # Martin A. Hansen, August 2007.
1811
1812     # Determine the length of sequences in stream.
1813
1814     my ( $in,        # handle to in stream
1815          $out,       # handle to out stream
1816          $options,   # options hash
1817        ) = @_;
1818
1819     # Returns nothing.
1820
1821     my ( $record, $total );
1822
1823     while ( $record = Maasha::Biopieces::get_record( $in ) ) 
1824     {
1825         if ( $record->{ "SEQ" } )
1826         {
1827             $record->{ "SEQ_LEN" } = length $record->{ "SEQ" };
1828             $total += $record->{ "SEQ_LEN" };
1829         }
1830
1831         Maasha::Biopieces::put_record( $record, $out ) if not $options->{ "no_stream" };
1832     }
1833
1834     Maasha::Biopieces::put_record( { TOTAL_SEQ_LEN => $total }, $out );
1835 }
1836
1837
1838 sub script_analyze_seq
1839 {
1840     # Martin A. Hansen, August 2007.
1841
1842     # Analyze sequence composition of sequences in stream.
1843
1844     my ( $in,     # handle to in stream
1845          $out,    # handle to out stream
1846        ) = @_;
1847
1848     # Returns nothing.
1849
1850     my ( $record, $analysis );
1851
1852     while ( $record = Maasha::Biopieces::get_record( $in ) ) 
1853     {
1854         if ( $record->{ "SEQ" } )
1855         {
1856             $analysis = Maasha::Seq::seq_analyze( $record->{ "SEQ" } );
1857
1858             map { $record->{ $_ } = $analysis->{ $_ } } keys %{ $analysis };
1859         }
1860
1861         Maasha::Biopieces::put_record( $record, $out );
1862     }
1863 }
1864
1865
1866 sub script_analyze_tags
1867 {
1868     # Martin A. Hansen, August 2008.
1869
1870     # Analyze sequence tags in stream.
1871
1872     my ( $in,     # handle to in stream
1873          $out,    # handle to out stream
1874        ) = @_;
1875
1876     # Returns nothing.
1877
1878     my ( $record, $analysis, %len_hash, %clone_hash, $clones, $key, $tag_record );
1879
1880     while ( $record = Maasha::Biopieces::get_record( $in ) ) 
1881     {
1882         if ( $record->{ "SEQ_NAME" } and $record->{ "SEQ" } )
1883         {
1884             if ( $record->{ "SEQ_NAME" } =~ /_(\d+)$/ )
1885             {
1886                 $clones = $1;
1887
1888                 $len_hash{ length( $record->{ "SEQ" } ) }++;
1889                 $clone_hash{ length( $record->{ "SEQ" } ) } += $clones;
1890             }
1891         }
1892         elsif ( $record->{ "Q_ID" } and $record->{ "BED_LEN" } )
1893         {
1894             if ( $record->{ "Q_ID" } =~ /_(\d+)$/ )
1895             {
1896                 $clones = $1;
1897
1898                 $len_hash{ $record->{ "BED_LEN" } }++;
1899                 $clone_hash{ $record->{ "BED_LEN" } } += $clones;
1900             }
1901         }
1902     }
1903
1904     foreach $key ( sort { $a <=> $b } keys %len_hash )
1905     {
1906         $tag_record->{ "TAG_LEN" }    = $key;
1907         $tag_record->{ "TAG_COUNT" }  = $len_hash{ $key };
1908         $tag_record->{ "TAG_CLONES" } = $clone_hash{ $key };
1909  
1910         Maasha::Biopieces::put_record( $tag_record, $out );
1911     }
1912 }
1913
1914
1915 sub script_complexity_seq
1916 {
1917     # Martin A. Hansen, May 2008.
1918
1919     # Generates an index calculated as the most common di-residue over
1920     # the sequence length for all sequences in stream.
1921
1922     my ( $in,     # handle to in stream
1923          $out,    # handle to out stream
1924        ) = @_;
1925
1926     # Returns nothing.
1927
1928     my ( $record, $index );
1929
1930     while ( $record = Maasha::Biopieces::get_record( $in ) ) 
1931     {
1932         $record->{ "SEQ_COMPLEXITY" } = sprintf( "%.2f", Maasha::Seq::seq_complexity( $record->{ "SEQ" } ) ) if $record->{ "SEQ" };
1933
1934         Maasha::Biopieces::put_record( $record, $out );
1935     }
1936 }
1937
1938
1939 sub script_oligo_freq
1940 {
1941     # Martin A. Hansen, August 2007.
1942
1943     # Determine the length of sequences in stream.
1944
1945     my ( $in,        # handle to in stream
1946          $out,       # handle to out stream
1947          $options,   # options hash
1948        ) = @_;
1949
1950     # Returns nothing.
1951
1952     my ( $record, %oligos, @freq_table );
1953
1954     $options->{ "word_size" } ||= 7;
1955
1956     while ( $record = Maasha::Biopieces::get_record( $in ) ) 
1957     {
1958         if ( $record->{ "SEQ" } )
1959         {
1960             map { $oligos{ $_ }++ } Maasha::Seq::seq2oligos( \$record->{ "SEQ" }, $options->{ "word_size" } );
1961
1962             if ( not $options->{ "all" } )
1963             {
1964                 @freq_table = Maasha::Seq::oligo_freq( \%oligos );
1965
1966                 map { Maasha::Biopieces::put_record( $_, $out ) } @freq_table;
1967             
1968                 undef %oligos;
1969             }
1970         }
1971
1972         Maasha::Biopieces::put_record( $record, $out );
1973     }
1974
1975     if ( $options->{ "all" } )
1976     {
1977         @freq_table = Maasha::Seq::oligo_freq( \%oligos );
1978
1979         map { Maasha::Biopieces::put_record( $_, $out ) } @freq_table;
1980     }
1981 }
1982
1983
1984 sub script_create_weight_matrix
1985 {
1986     # Martin A. Hansen, August 2007.
1987
1988     # Creates a weight matrix from an alignmnet.
1989
1990     my ( $in,        # handle to in stream
1991          $out,       # handle to out stream
1992          $options,   # options hash
1993        ) = @_;
1994
1995     # Returns nothing.
1996
1997     my ( $record, $count, $i, $res, %freq_hash, %res_hash, $freq );
1998
1999     $count = 0;
2000     
2001     while ( $record = Maasha::Biopieces::get_record( $in ) ) 
2002     {
2003         if ( $record->{ "SEQ" } )
2004         {
2005             for ( $i = 0; $i < length $record->{ "SEQ" }; $i++ )
2006             {
2007                 $res = substr $record->{ "SEQ" }, $i, 1;
2008
2009                 $freq_hash{ $i }{ $res }++;
2010                 $res_hash{ $res } = 1;
2011             }
2012
2013             $count++;
2014         }
2015         else
2016         {
2017             Maasha::Biopieces::put_record( $record, $out );
2018         }
2019     }
2020
2021     foreach $res ( sort keys %res_hash )
2022     {
2023         undef $record;
2024
2025         $record->{ "V0" } = $res;
2026
2027         for ( $i = 0; $i < keys %freq_hash; $i++ )
2028         {
2029             $freq = $freq_hash{ $i }{ $res } || 0;
2030
2031             if ( $options->{ "percent" } ) {
2032                 $freq = sprintf( "%.0f", 100 * $freq / $count ) if $freq > 0;
2033             }
2034
2035             $record->{ "V" . ( $i + 1 ) } = $freq;
2036         }
2037
2038         Maasha::Biopieces::put_record( $record, $out );
2039     }
2040 }
2041
2042
2043 sub script_calc_bit_scores
2044 {
2045     # Martin A. Hansen, March 2007.
2046
2047     # Calculates the bit scores for each position from an alignmnet in the stream.
2048
2049     my ( $in,        # handle to in stream
2050          $out,       # handle to out stream
2051        ) = @_;
2052
2053     # Returns nothing.
2054
2055     my ( $record, $type, $count, $i, $res, %freq_hash, $bit_max, $bit_height, $bit_diff );
2056
2057     $count = 0;
2058
2059     while ( $record = Maasha::Biopieces::get_record( $in ) ) 
2060     {
2061         if ( $record->{ "SEQ" } )
2062         {
2063             $type = Maasha::Seq::seq_guess_type( $record->{ "SEQ" } ) if not $type;
2064
2065             for ( $i = 0; $i < length $record->{ "SEQ" }; $i++ )
2066             {
2067                 $res = substr $record->{ "SEQ" }, $i, 1;
2068
2069                 next if $res =~ /-|_|~|\./;
2070
2071                 $freq_hash{ $i }{ $res }++;
2072             }
2073
2074             $count++;
2075         }
2076         else
2077         {
2078             Maasha::Biopieces::put_record( $record, $out );
2079         }
2080     }
2081
2082     undef $record;
2083
2084     if ( $type eq "protein" ) {
2085         $bit_max = 4;
2086     } else {
2087         $bit_max = 2;
2088     }
2089
2090     for ( $i = 0; $i < keys %freq_hash; $i++ )
2091     {
2092         $bit_height = Maasha::Seq::seqlogo_calc_bit_height( $freq_hash{ $i }, $count );
2093
2094         $bit_diff = $bit_max - $bit_height;
2095
2096         $record->{ "V" . ( $i ) } = sprintf( "%.2f", $bit_diff );
2097     }
2098
2099     Maasha::Biopieces::put_record( $record, $out );
2100 }
2101
2102
2103 sub script_calc_fixedstep
2104 {
2105     # Martin A. Hansen, September 2008.
2106
2107     # Calculates fixedstep entries from data in the stream.
2108
2109     my ( $in,        # handle to in stream
2110          $out,       # handle to out stream
2111          $options,   # options hash
2112        ) = @_;
2113
2114     # Returns nothing.
2115
2116     my ( $bed_file, $fh_in, $fh_out, $record, $file_hash, $chr, $bed_entry, $fixedstep_file, $fixedstep_entry );
2117
2118     $bed_file = "$BP_TMP/calc_fixedstep.bed";
2119     $fh_out   = Maasha::Filesys::file_write_open( $bed_file );
2120
2121     while ( $record = Maasha::Biopieces::get_record( $in ) ) 
2122     {
2123         if ( $bed_entry = Maasha::UCSC::BED::biopiece2bed( $record ) ) {
2124             Maasha::UCSC::BED::bed_entry_put( $bed_entry, $fh_out, undef, $options->{ 'check' } );
2125         }
2126     }
2127
2128     close $fh_out;
2129
2130     $file_hash = Maasha::UCSC::BED::bed_file_split_on_chr( $bed_file, $BP_TMP );
2131
2132     unlink $bed_file;
2133
2134     foreach $chr ( sort keys %{ $file_hash } )
2135     {
2136         $bed_file       = $file_hash->{ $chr };
2137
2138         $fixedstep_file = Maasha::UCSC::Wiggle::fixedstep_calc( $bed_file, $chr, $options->{ 'use_score' }, $options->{ 'use_log10' } );        
2139
2140         #$fixedstep_file = "$bed_file.fixedstep";
2141         
2142         # Maasha::Common::run( "bed2fixedstep", "< $bed_file > $fixedstep_file" );
2143
2144         $fh_in = Maasha::Filesys::file_read_open( $fixedstep_file );
2145
2146         while ( $fixedstep_entry = Maasha::UCSC::Wiggle::fixedstep_entry_get( $fh_in ) )
2147         {
2148             if ( $record = Maasha::UCSC::Wiggle::fixedstep2biopiece( $fixedstep_entry ) ) {
2149                 Maasha::Biopieces::put_record( $record, $out );
2150             }
2151         }
2152
2153         close $fh_in;
2154
2155         unlink $bed_file;
2156         unlink $fixedstep_file;
2157     }
2158 }
2159
2160
2161 sub script_remove_indels
2162 {
2163     # Martin A. Hansen, August 2007.
2164
2165     # Remove indels from sequences in stream.
2166
2167     my ( $in,     # handle to in stream
2168          $out,    # handle to out stream
2169        ) = @_;
2170
2171     # Returns nothing.
2172
2173     my ( $record );
2174
2175     while ( $record = Maasha::Biopieces::get_record( $in ) ) 
2176     {
2177         $record->{ 'SEQ' } =~ tr/-~.//d if $record->{ "SEQ" };
2178
2179         Maasha::Biopieces::put_record( $record, $out );
2180     }
2181 }
2182
2183
2184 sub script_transliterate_seq
2185 {
2186     # Martin A. Hansen, August 2007.
2187
2188     # Transliterate chars from sequence in record.
2189
2190     my ( $in,        # handle to in stream
2191          $out,       # handle to out stream
2192          $options,   # options hash
2193        ) = @_;
2194
2195     # Returns nothing.
2196
2197     my ( $record, $search, $replace, $delete );
2198
2199     $search  = $options->{ "search" }  || "";
2200     $replace = $options->{ "replace" } || "";
2201     $delete  = $options->{ "delete" }  || "";
2202
2203     while ( $record = Maasha::Biopieces::get_record( $in ) ) 
2204     {
2205         if ( $record->{ "SEQ" } )
2206         {
2207             if ( $search and $replace ) {
2208                 eval "\$record->{ 'SEQ' } =~ tr/$search/$replace/";
2209             } elsif ( $delete ) {
2210                 eval "\$record->{ 'SEQ' } =~ tr/$delete//d";
2211             }
2212         }
2213
2214         Maasha::Biopieces::put_record( $record, $out );
2215     }
2216 }
2217
2218
2219 sub script_transliterate_vals
2220 {
2221     # Martin A. Hansen, April 2008.
2222
2223     # Transliterate chars from values in record.
2224
2225     my ( $in,        # handle to in stream
2226          $out,       # handle to out stream
2227          $options,   # options hash
2228        ) = @_;
2229
2230     # Returns nothing.
2231
2232     my ( $record, $search, $replace, $delete, $key );
2233
2234     $search  = $options->{ "search" }  || "";
2235     $replace = $options->{ "replace" } || "";
2236     $delete  = $options->{ "delete" }  || "";
2237
2238     while ( $record = Maasha::Biopieces::get_record( $in ) ) 
2239     {
2240         foreach $key ( @{ $options->{ "keys" } } )
2241         {
2242             if ( exists $record->{ $key } )
2243             {
2244                 if ( $search and $replace ) {
2245                     eval "\$record->{ $key } =~ tr/$search/$replace/";
2246                 } elsif ( $delete ) {
2247                     eval "\$record->{ $key } =~ tr/$delete//d";
2248                 }
2249             }
2250         }
2251
2252         Maasha::Biopieces::put_record( $record, $out );
2253     }
2254 }
2255
2256
2257 sub script_translate_seq
2258 {
2259     # Martin A. Hansen, February 2008.
2260
2261     # Translate DNA sequence into protein sequence.
2262
2263     my ( $in,        # handle to in stream
2264          $out,       # handle to out stream
2265          $options,   # options hash
2266        ) = @_;
2267
2268     # Returns nothing.
2269
2270     my ( $record, $frame, %new_record );
2271
2272     $options->{ "frames" } ||= [ 1, 2, 3, -1, -2, -3 ];
2273
2274     while ( $record = Maasha::Biopieces::get_record( $in ) ) 
2275     {
2276         if ( $record->{ "SEQ" } )
2277         {
2278             if ( Maasha::Seq::seq_guess_type( $record->{ "SEQ" } ) eq "dna" )
2279             {
2280                 foreach $frame ( @{ $options->{ "frames" } } )
2281                 {
2282                     %new_record = %{ $record };
2283
2284                     $new_record{ "SEQ" }     = Maasha::Seq::translate( $record->{ "SEQ" }, $frame );
2285                     $new_record{ "SEQ_LEN" } = length $new_record{ "SEQ" };
2286                     $new_record{ "FRAME" }   = $frame;
2287
2288                     Maasha::Biopieces::put_record( \%new_record, $out );
2289                 }
2290             }
2291         }
2292         else
2293         {
2294             Maasha::Biopieces::put_record( $record, $out );
2295         }
2296     }
2297 }
2298
2299
2300 sub script_get_genome_align
2301 {
2302     # Martin A. Hansen, April 2008.
2303
2304     # Gets a subalignment from a multiple genome alignment.
2305
2306     my ( $in,        # handle to in stream
2307          $out,       # handle to out stream
2308          $options,   # options hash
2309        ) = @_;
2310
2311     # Returns nothing.
2312
2313     my ( $record, $maf_track, $align, $align_num, $beg, $end, $len, $entry );
2314
2315     $options->{ "strand" } ||= "+";
2316
2317     $align_num = 1;
2318
2319     $maf_track = Maasha::Config::maf_track( $options->{ "genome" } );
2320
2321     if ( $options->{ "chr" } and $options->{ "beg" } and ( $options->{ "end" } or $options->{ "len" } ) )
2322     {
2323         $beg = $options->{ "beg" } - 1;
2324         
2325         if ( $options->{ "end" } ) {
2326             $end = $options->{ "end" };
2327         } elsif ( $options->{ "len" } ) {
2328             $end = $beg + $options->{ "len" };
2329         }
2330
2331         $align = Maasha::UCSC::maf_extract( $BP_TMP, $options->{ "genome" }, $maf_track, $options->{ "chr" }, $beg, $end, $options->{ "strand" } );
2332
2333         foreach $entry ( @{ $align } )
2334         {
2335             $entry->{ "CHR" }     = $record->{ "CHR" };
2336             $entry->{ "CHR_BEG" } = $record->{ "CHR_BEG" };
2337             $entry->{ "CHR_END" } = $record->{ "CHR_END" };
2338             $entry->{ "STRAND" }  = $record->{ "STRAND" } || '+';
2339             $entry->{ "Q_ID" }    = $record->{ "Q_ID" };
2340             $entry->{ "SCORE" }   = $record->{ "SCORE" };
2341
2342             Maasha::Biopieces::put_record( $entry, $out );
2343         }
2344     }
2345
2346     while ( $record = Maasha::Biopieces::get_record( $in ) ) 
2347     {
2348         if ( $record->{ "REC_TYPE" } eq "BED" )
2349         {
2350             $align = Maasha::UCSC::maf_extract( $BP_TMP, $options->{ "genome" }, $maf_track, $record->{ "CHR" }, $record->{ "CHR_BEG" }, $record->{ "CHR_END" }, $record->{ "STRAND" } );
2351         }
2352         elsif ( $record->{ "REC_TYPE" } eq "VMATCH" )
2353         {
2354             $align = Maasha::UCSC::maf_extract( $BP_TMP, $options->{ "genome" }, $maf_track, $record->{ "S_ID" }, $record->{ "S_BEG" }, $record->{ "S_END" } + 1, $record->{ "STRAND" } );
2355         }
2356         elsif ( $record->{ "REC_TYPE" } eq "PSL" )
2357         {
2358             $align = Maasha::UCSC::maf_extract( $BP_TMP, $options->{ "genome" }, $maf_track, $record->{ "S_ID" }, $record->{ "S_BEG" }, $record->{ "S_END" }, $record->{ "STRAND" } );
2359         }
2360         elsif ( $record->{ "REC_TYPE" } eq "BLAST" )
2361         {
2362             $align = Maasha::UCSC::maf_extract( $BP_TMP, $options->{ "genome" }, $maf_track, $record->{ "S_ID" }, $record->{ "S_BEG" }, $record->{ "S_END" }, $record->{ "STRAND" } );
2363         }
2364
2365         foreach $entry ( @{ $align } )
2366         {
2367             $entry->{ "CHR" }     = $record->{ "CHR" };
2368             $entry->{ "CHR_BEG" } = $record->{ "CHR_BEG" };
2369             $entry->{ "CHR_END" } = $record->{ "CHR_END" };
2370             $entry->{ "STRAND" }  = $record->{ "STRAND" };
2371             $entry->{ "Q_ID" }    = $record->{ "Q_ID" };
2372             $entry->{ "SCORE" }   = $record->{ "SCORE" };
2373
2374             Maasha::Biopieces::put_record( $entry, $out );
2375         }
2376
2377         $align_num++;
2378     }
2379 }
2380
2381
2382 sub script_get_genome_phastcons
2383 {
2384     # Martin A. Hansen, February 2008.
2385
2386     # Get phastcons scores from genome intervals.
2387
2388     my ( $in,        # handle to in stream
2389          $out,       # handle to out stream
2390          $options,   # options hash
2391        ) = @_;
2392
2393     # Returns nothing.
2394
2395     my ( $phastcons_file, $phastcons_index, $index, $fh_phastcons, $scores, $record );
2396
2397     $options->{ "flank" } ||= 0;
2398
2399     $phastcons_file  = Maasha::Config::genome_phastcons( $options->{ "genome" } );
2400     $phastcons_index = Maasha::Config::genome_phastcons_index( $options->{ "genome" } );
2401
2402     $index           = Maasha::UCSC::fixedstep_index_retrieve( $phastcons_index );
2403     $fh_phastcons    = Maasha::Common::read_open( $phastcons_file );
2404
2405     if ( defined $options->{ "chr" } and defined $options->{ "beg" } and ( defined $options->{ "end" } or defined $options->{ "len" } ) )
2406     {
2407         $options->{ "beg" } -= 1;   # request is 1-based
2408         $options->{ "end" } -= 1;   # request is 1-based
2409
2410         if ( $options->{ "len" } ) {
2411             $options->{ "end" } = $options->{ "beg" } + $options->{ "len" } - 1;
2412         }
2413
2414         $scores = Maasha::UCSC::fixedstep_index_lookup( $index, $fh_phastcons, $options->{ "chr" }, $options->{ "beg" }, $options->{ "end" }, $options->{ "flank" } );
2415
2416         $record->{ "CHR" }       = $options->{ "chr" };
2417         $record->{ "CHR_BEG" }   = $options->{ "beg" } - $options->{ "flank" };
2418         $record->{ "CHR_END" }   = $options->{ "end" } + $options->{ "flank" };
2419         
2420         $record->{ "PHASTCONS" }   = join ",", @{ $scores };
2421         $record->{ "PHAST_COUNT" } = scalar @{ $scores };  # DEBUG
2422
2423         Maasha::Biopieces::put_record( $record, $out );
2424     }   
2425
2426     while ( $record = Maasha::Biopieces::get_record( $in ) ) 
2427     {
2428         if ( $record->{ "REC_TYPE" } eq "BED" )
2429         {
2430             $scores = Maasha::UCSC::fixedstep_index_lookup( $index, $fh_phastcons, $record->{ "CHR" }, $record->{ "CHR_BEG" }, $record->{ "CHR_END" }, $options->{ "flank" } );
2431         }
2432         elsif ( $record->{ "REC_TYPE" } eq "PSL" )
2433         {
2434             $scores = Maasha::UCSC::fixedstep_index_lookup( $index, $fh_phastcons, $record->{ "S_ID" }, $record->{ "S_BEG" }, $record->{ "S_END" }, $options->{ "flank" } );
2435         }
2436         elsif ( $record->{ "REC_TYPE" } eq "BLAST" )
2437         {
2438             $scores = Maasha::UCSC::fixedstep_index_lookup( $index, $fh_phastcons, $record->{ "S_ID" }, $record->{ "S_BEG" }, $record->{ "S_END" }, $options->{ "flank" } );
2439         }
2440
2441         $record->{ "PHASTCONS" } = join ",", @{ $scores } if @{ $scores };
2442 #        $record->{ "PHAST_COUNT" } = @{ $scores } if @{ $scores };  # DEBUG
2443
2444         Maasha::Biopieces::put_record( $record, $out );
2445     }
2446
2447     close $fh_phastcons if $fh_phastcons;                                                                                                                                          
2448 }
2449
2450
2451 sub script_fold_seq
2452 {
2453     # Martin A. Hansen, December 2007.
2454
2455     # Folds sequences in stream into secondary structures.
2456
2457     my ( $in,     # handle to in stream
2458          $out,    # handle to out stream
2459        ) = @_;
2460
2461     # Returns nothing.
2462
2463     my ( $record, $type, $struct, $index );
2464
2465     while ( $record = Maasha::Biopieces::get_record( $in ) ) 
2466     {
2467         if ( $record->{ "SEQ" } )
2468         {
2469             if ( not $type ) {
2470                 $type = Maasha::Seq::seq_guess_type( $record->{ "SEQ" } );
2471             }
2472             
2473             if ( $type ne "protein" )
2474             {
2475                 ( $struct, $index ) = Maasha::Seq::fold_struct_rnafold( $record->{ "SEQ" } );
2476                 $record->{ "SEC_STRUCT" }  = $struct;
2477                 $record->{ "FREE_ENERGY" } = $index;
2478                 $record->{ "SCORE" }       = abs int $index;
2479                 $record->{ "SIZE" }        = length $struct;
2480                 $record->{ "CONF" }        = "1," x $record->{ "SIZE" };
2481             }
2482         }
2483
2484         Maasha::Biopieces::put_record( $record, $out );
2485     }
2486 }
2487
2488
2489 sub script_split_seq
2490 {
2491     # Martin A. Hansen, August 2007.
2492
2493     # Split a sequence in stream into words.
2494
2495     my ( $in,        # handle to in stream
2496          $out,       # handle to out stream
2497          $options,   # options hash
2498        ) = @_;
2499
2500     # Returns nothing.
2501
2502     my ( $record, $new_record, $i, $subseq, %lookup );
2503
2504     $options->{ "word_size" } ||= 7;
2505
2506     while ( $record = Maasha::Biopieces::get_record( $in ) ) 
2507     {
2508         if ( $record->{ "SEQ_NAME" } and $record->{ "SEQ" } )
2509         {
2510             for ( $i = 0; $i < length( $record->{ "SEQ" } ) - $options->{ "word_size" } + 1; $i++ )
2511             {
2512                 $subseq = substr $record->{ "SEQ" }, $i, $options->{ "word_size" };
2513
2514                 if ( $options->{ "uniq" } and not $lookup{ $subseq } )
2515                 {
2516                     $new_record->{ "SEQ_NAME" } = $record->{ "SEQ_NAME" } . "[" . ( $i + 1 ) . "-" . ( $i + $options->{ "word_size" } ) . "]";
2517                     $new_record->{ "SEQ" }      = $subseq;
2518
2519                     Maasha::Biopieces::put_record( $new_record, $out );
2520
2521                     $lookup{ $subseq } = 1;
2522                 }
2523                 else
2524                 {
2525                     $new_record->{ "SEQ_NAME" } = $record->{ "SEQ_NAME" } . "[" . ( $i + 1 ) . "-" . ( $i + $options->{ "word_size" } ) . "]";
2526                     $new_record->{ "SEQ" }      = $subseq;
2527
2528                     Maasha::Biopieces::put_record( $new_record, $out );
2529                 }
2530             }
2531         }
2532         else
2533         {
2534             Maasha::Biopieces::put_record( $record, $out );
2535         }
2536     }
2537 }
2538
2539
2540 sub script_split_bed
2541 {
2542     # Martin A. Hansen, June 2008.
2543
2544     # Split a BED record into overlapping windows.
2545
2546     my ( $in,        # handle to in stream
2547          $out,       # handle to out stream
2548          $options,   # options hash
2549        ) = @_;
2550
2551     # Returns nothing.
2552
2553     my ( $record, $new_record, $i );
2554
2555     $options->{ "window_size" } ||= 20;
2556     $options->{ "step_size" }   ||= 1;
2557
2558     while ( $record = Maasha::Biopieces::get_record( $in ) ) 
2559     {
2560         if ( $record->{ "CHR" } and $record->{ "CHR_BEG" } and $record->{ "CHR_END" } )
2561         {
2562             $record->{ "BED_LEN" } = $record->{ "CHR_END" } - $record->{ "CHR_BEG" } + 1;
2563
2564             for ( $i = 0; $i < $record->{ "BED_LEN" } - $options->{ "window_size" }; $i += $options->{ "step_size" } )
2565             {
2566                 $new_record->{ "REC_TYPE" } = "BED";
2567                 $new_record->{ "CHR" }      = $record->{ "CHR" };
2568                 $new_record->{ "CHR_BEG" }  = $record->{ "CHR_BEG" } + $i;
2569                 $new_record->{ "CHR_END" }  = $record->{ "CHR_BEG" } + $i + $options->{ "window_size" };
2570                 $new_record->{ "BED_LEN" }  = $options->{ "window_size" };
2571                 $new_record->{ "Q_ID" }     = $record->{ "Q_ID" } . "_$i";
2572                 $new_record->{ "SCORE" }    = $record->{ "SCORE" };
2573                 $new_record->{ "STRAND" }   = $record->{ "STRAND" };
2574
2575                 Maasha::Biopieces::put_record( $new_record, $out );
2576             }
2577         }
2578         else
2579         {
2580             Maasha::Biopieces::put_record( $record, $out );
2581         }
2582     }
2583 }
2584
2585
2586 sub script_tile_seq
2587 {
2588     # Martin A. Hansen, February 2008.
2589
2590     # Using the first sequence in stream as reference, tile
2591     # all subsequent sequences based on pairwise alignments.
2592
2593     my ( $in,        # handle to in stream
2594          $out,       # handle to out stream
2595          $options,   # options hash
2596        ) = @_;
2597
2598     # Returns nothing.
2599
2600     my ( $record, $first, $ref_entry, @entries );
2601
2602     $first = 1;
2603
2604     while ( $record = Maasha::Biopieces::get_record( $in ) ) 
2605     {
2606         if ( $record->{ "SEQ_NAME" } and $record->{ "SEQ" } )
2607         {
2608             if ( $first )
2609             {
2610                 $ref_entry = [ $record->{ "SEQ_NAME" }, $record->{ "SEQ" } ];
2611
2612                 $first = 0;
2613             }
2614             else
2615             {
2616                 push @entries, [ $record->{ "SEQ_NAME" }, $record->{ "SEQ" } ];
2617             }
2618         }
2619         else
2620         {
2621             Maasha::Biopieces::put_record( $record, $out );
2622         }
2623     }
2624
2625     @entries = Maasha::Align::align_tile( $ref_entry, \@entries, $options );
2626
2627     map { Maasha::Biopieces::put_record( { SEQ_NAME => $_->[ SEQ_NAME ], SEQ => $_->[ SEQ ] }, $out ) } @entries;
2628 }
2629
2630
2631 sub script_invert_align
2632 {
2633     # Martin A. Hansen, February 2008.
2634
2635     # Inverts an alignment showing only non-mathing residues
2636     # using the first sequence as reference.
2637
2638     my ( $in,        # handle to in stream
2639          $out,       # handle to out stream
2640          $options,   # options hash
2641        ) = @_;
2642
2643     # Returns nothing.
2644
2645     my ( $record, @entries );
2646
2647     while ( $record = Maasha::Biopieces::get_record( $in ) ) 
2648     {
2649         if ( $record->{ "SEQ_NAME" } and $record->{ "SEQ" } )
2650         {
2651             push @entries, [ $record->{ "SEQ_NAME" }, $record->{ "SEQ" } ];
2652         }
2653         else
2654         {
2655             Maasha::Biopieces::put_record( $record, $out );
2656         }
2657     }
2658
2659     Maasha::Align::align_invert( \@entries, $options->{ "soft" } );
2660
2661     map { Maasha::Biopieces::put_record( { SEQ_NAME => $_->[ SEQ_NAME ], SEQ => $_->[ SEQ ] }, $out ) } @entries;
2662 }
2663
2664
2665 sub script_patscan_seq
2666 {
2667     # Martin A. Hansen, August 2007.
2668
2669     # Locates patterns in sequences using scan_for_matches.
2670
2671     my ( $in,        # handle to in stream
2672          $out,       # handle to out stream
2673          $options,   # options hash
2674        ) = @_;
2675
2676     # Returns nothing.
2677
2678     my ( $genome_file, @args, $arg, $type, $seq_file, $pat_file, $out_file, $fh_in, $fh_out, $record, $patterns, $pattern, $entry, $result, %head_hash, $i );
2679
2680     if ( $options->{ "patterns" } ) {
2681         $patterns = Maasha::Patscan::parse_patterns( $options->{ "patterns" } );
2682     } elsif ( -f $options->{ "patterns_in" } ) {
2683         $patterns = Maasha::Patscan::read_patterns( $options->{ "patterns_in" } );
2684     }
2685
2686     $genome_file = "$ENV{ 'BP_DATA' }/genomes/$options->{ 'genome' }/fasta/$options->{ 'genome' }.fna" if $options->{ 'genome' };
2687
2688     push @args, "-c"                            if $options->{ "comp" };
2689     push @args, "-m $options->{ 'max_hits' }"   if $options->{ 'max_hits' };
2690     push @args, "-n $options->{ 'max_misses' }" if $options->{ 'max_hits' };
2691
2692     $seq_file = "$BP_TMP/patscan.seq";
2693     $pat_file = "$BP_TMP/patscan.pat";
2694     $out_file = "$BP_TMP/patscan.out";
2695
2696     $fh_out = Maasha::Common::write_open( $seq_file );
2697
2698     $i = 0;
2699
2700     while ( $record = Maasha::Biopieces::get_record( $in ) ) 
2701     {
2702         if ( $record->{ "SEQ" } and $record->{ "SEQ_NAME" } )
2703         {
2704             $type = Maasha::Seq::seq_guess_type( $record->{ "SEQ" } ) if not $type;
2705
2706             Maasha::Fasta::put_entry( [ $i, $record->{ "SEQ" } ], $fh_out );
2707
2708             $head_hash{ $i } = $record->{ "SEQ_NAME" };
2709
2710             $i++;
2711         }
2712     }
2713
2714     close $fh_out;
2715
2716     $arg  = join " ", @args;
2717     $arg .= " -p" if $type eq "protein";
2718
2719     foreach $pattern ( @{ $patterns } )
2720     {
2721         $fh_out = Maasha::Common::write_open( $pat_file );
2722
2723         print $fh_out "$pattern\n";
2724
2725         close $fh_out;
2726
2727         if ( $options->{ 'genome' } ) {
2728             `scan_for_matches $arg $pat_file < $genome_file > $out_file`;
2729             # Maasha::Common::run( "scan_for_matches", "$arg $pat_file < $genome_file > $out_file" );
2730         } else {
2731             `scan_for_matches $arg $pat_file < $seq_file > $out_file`;
2732             # Maasha::Common::run( "scan_for_matches", "$arg $pat_file < $seq_file > $out_file" );
2733         }
2734
2735         $fh_in = Maasha::Common::read_open( $out_file );
2736
2737         while ( $entry = Maasha::Fasta::get_entry( $fh_in ) )
2738         {
2739             $result = Maasha::Patscan::parse_scan_result( $entry, $pattern );
2740
2741             if ( $options->{ 'genome' } )
2742             {
2743                 $result->{ "CHR" }     = $result->{ "S_ID" };
2744                 $result->{ "CHR_BEG" } = $result->{ "S_BEG" }; 
2745                 $result->{ "CHR_END" } = $result->{ "S_END" }; 
2746
2747                 delete $result->{ "S_ID" };
2748                 delete $result->{ "S_BEG" };
2749                 delete $result->{ "S_END" };
2750             }
2751             else
2752             {
2753                 $result->{ "S_ID" } = $head_hash{ $result->{ "S_ID" } };
2754             }
2755
2756             Maasha::Biopieces::put_record( $result, $out );
2757         }
2758
2759         close $fh_in;
2760     }
2761
2762     unlink $pat_file;
2763     unlink $seq_file;
2764     unlink $out_file;
2765 }
2766
2767
2768 sub script_blat_seq
2769 {
2770     # Martin A. Hansen, August 2007.
2771
2772     # BLATs sequences in stream against a given genome.
2773
2774     my ( $in,        # handle to in stream
2775          $out,       # handle to out stream
2776          $options,   # options hash
2777        ) = @_;
2778
2779     # Returns nothing.
2780
2781     my ( $blat_args, $genome_file, $query_file, $fh_in, $fh_out, $type, $record, $result_file, $entries, $entry );
2782
2783     $genome_file = "$ENV{ 'BP_DATA' }/genomes/$options->{ 'genome' }/fasta/$options->{ 'genome' }.fna";
2784
2785     $options->{ 'tile_size' }    ||= 11;
2786     $options->{ 'one_off' }      ||= 0;
2787     $options->{ 'min_identity' } ||= 90;
2788     $options->{ 'min_score' }    ||= 0;
2789     $options->{ 'step_size' }    ||= $options->{ 'tile_size' };
2790
2791     $blat_args .= " -tileSize=$options->{ 'tile_size' }";
2792     $blat_args .= " -oneOff=$options->{ 'one_off' }";
2793     $blat_args .= " -minIdentity=$options->{ 'min_identity' }";
2794     $blat_args .= " -minScore=$options->{ 'min_score' }";
2795     $blat_args .= " -stepSize=$options->{ 'step_size' }";
2796 #    $blat_args .= " -ooc=" . Maasha::Config::genome_blat_ooc( $options->{ "genome" }, 11 ) if $options->{ 'ooc' };
2797
2798     $query_file = "$BP_TMP/blat.seq";
2799
2800     $fh_out = Maasha::Common::write_open( $query_file );
2801
2802     while ( $record = Maasha::Biopieces::get_record( $in ) ) 
2803     {
2804         if ( $entry = Maasha::Fasta::biopiece2fasta( $record ) )
2805         {
2806             $type = Maasha::Seq::seq_guess_type( $entry->[ SEQ ] ) if not $type;
2807             Maasha::Fasta::put_entry( $entry, $fh_out, 80 );
2808         }
2809
2810         Maasha::Biopieces::put_record( $record, $out );
2811     }
2812
2813     close $fh_out;
2814
2815     $blat_args .= " -t=dnax" if $type eq "protein";
2816     $blat_args .= " -q=$type";
2817
2818     $result_file = "$BP_TMP/blat.psl";
2819
2820     Maasha::Common::run( "blat", "$genome_file $query_file $blat_args $result_file > /dev/null 2>&1" );
2821
2822     unlink $query_file;
2823
2824     $entries = Maasha::UCSC::psl_get_entries( $result_file );
2825
2826     map { Maasha::Biopieces::put_record( $_, $out ) } @{ $entries };
2827
2828     unlink $result_file;
2829 }
2830
2831
2832 sub script_soap_seq
2833 {
2834     # Martin A. Hansen, July 2008.
2835
2836     # soap sequences in stream against a given file or genome.
2837
2838     my ( $in,        # handle to in stream
2839          $out,       # handle to out stream
2840          $options,   # options hash
2841        ) = @_;
2842
2843     # Returns nothing.
2844
2845     my ( $genome, $tmp_in, $tmp_out, $fh_in, $fh_out, $record, $line, @fields, $entry, $count, $args );
2846
2847     $options->{ "seed_size" }  ||= 10;
2848     $options->{ "mismatches" } ||= 2;
2849     $options->{ "gap_size" }   ||= 0;
2850     $options->{ "cpus" }       ||= 1;
2851
2852     if ( $options->{ "genome" } ) {
2853         $options->{ "in_file" } = "$ENV{ 'BP_DATA' }/genomes/$options->{ 'genome' }/fasta/$options->{ 'genome' }.fna";
2854     }
2855
2856     $tmp_in  = "$BP_TMP/soap_query.seq";
2857     $tmp_out = "$BP_TMP/soap.result";
2858
2859     $fh_out = Maasha::Common::write_open( $tmp_in );
2860  
2861     $count = 0;
2862
2863     while ( $record = Maasha::Biopieces::get_record( $in ) ) 
2864     {
2865         if ( $entry = Maasha::Fasta::biopiece2fasta( $record ) )
2866         {
2867             Maasha::Fasta::put_entry( $entry, $fh_out );
2868
2869             $count++;
2870         }
2871
2872         Maasha::Biopieces::put_record( $record, $out );
2873     }
2874
2875     close $fh_out;
2876
2877     if ( $count > 0 )
2878     {
2879         $args = join( " ",
2880             "-s $options->{ 'seed_size' }",
2881             "-r 2",
2882             "-a $tmp_in",
2883             "-v $options->{ 'mismatches' }",
2884             "-g $options->{ 'gap_size' }",
2885             "-p $options->{ 'cpus' }",
2886             "-d $options->{ 'in_file' }",
2887             "-o $tmp_out",
2888         );
2889
2890         $args .= " > /dev/null 2>&1" if not $options->{ 'verbose' };
2891
2892         Maasha::Common::run( "soap", $args, 1 );
2893
2894         unlink $tmp_in;
2895
2896         $fh_out = Maasha::Common::read_open( $tmp_out );
2897
2898         undef $record;
2899
2900         while ( $line = <$fh_out> )
2901         {
2902             chomp $line;
2903
2904             @fields = split /\t/, $line;
2905
2906             $record->{ "REC_TYPE" }   = "SOAP";
2907             $record->{ "Q_ID" }       = $fields[ 0 ];
2908             $record->{ "SCORE" }      = $fields[ 3 ];
2909             $record->{ "STRAND" }     = $fields[ 6 ];
2910             $record->{ "S_ID" }       = $fields[ 7 ];
2911             $record->{ "S_BEG" }      = $fields[ 8 ] - 1; # soap is 1-based
2912             $record->{ "S_END" }      = $fields[ 8 ] + $fields[ 5 ] - 2;
2913
2914             Maasha::Biopieces::put_record( $record, $out );
2915         }
2916
2917         close $fh_out;
2918     }
2919
2920     unlink $tmp_out;
2921 }
2922
2923
2924 sub script_match_seq
2925 {
2926     # Martin A. Hansen, August 2007.
2927
2928     # BLATs sequences in stream against a given genome.
2929
2930     my ( $in,        # handle to in stream
2931          $out,       # handle to out stream
2932          $options,   # options hash
2933        ) = @_;
2934
2935     # Returns nothing.
2936
2937     my ( $record, @entries, $results );
2938
2939     $options->{ "word_size" } ||= 20;
2940     $options->{ "direction" } ||= "both";
2941
2942     while ( $record = Maasha::Biopieces::get_record( $in ) ) 
2943     {
2944         if ( $record->{ "SEQ_NAME" } and $record->{ "SEQ" } ) {
2945             push @entries, [ $record->{ "SEQ_NAME" }, $record->{ "SEQ" } ];
2946         }
2947
2948         Maasha::Biopieces::put_record( $record, $out );
2949     }
2950
2951     if ( @entries == 1 )
2952     {
2953         $results = Maasha::Match::match_mummer( [ $entries[ 0 ] ], [ $entries[ 0 ] ], $options, $BP_TMP );
2954
2955         map { Maasha::Biopieces::put_record( $_, $out ) } @{ $results };
2956     }
2957     elsif ( @entries == 2 )
2958     {
2959         $results = Maasha::Match::match_mummer( [ $entries[ 0 ] ], [ $entries[ 1 ] ], $options, $BP_TMP );
2960
2961         map { Maasha::Biopieces::put_record( $_, $out ) } @{ $results };
2962     }
2963 }
2964
2965
2966 sub script_create_vmatch_index
2967 {
2968     # Martin A. Hansen, January 2008.
2969
2970     # Create a vmatch index from sequences in the stream.
2971
2972     my ( $in,        # handle to in stream
2973          $out,       # handle to out stream
2974          $options,   # options hash
2975        ) = @_;
2976
2977     # Returns nothing.
2978
2979     my ( $record, $file_tmp, $fh_tmp, $type, $entry );
2980
2981     if ( $options->{ "index_name" } )
2982     {
2983         $file_tmp = $options->{ 'index_name' };
2984         $fh_tmp   = Maasha::Common::write_open( $file_tmp );
2985     }
2986
2987     while ( $record = Maasha::Biopieces::get_record( $in ) ) 
2988     {
2989         if ( $options->{ "index_name" } and $entry = Maasha::Fasta::biopiece2fasta( $record ) )
2990         {
2991             Maasha::Fasta::put_entry( $entry, $fh_tmp );
2992
2993             $type = Maasha::Seq::seq_guess_type( $entry->[ SEQ ] ) if not defined $type;
2994         }
2995
2996         Maasha::Biopieces::put_record( $record, $out ) if not $options->{ "no_stream" };
2997     }
2998
2999     if ( $options->{ "index_name" } )
3000     {
3001         close $fh_tmp;
3002     
3003         if ( $type eq "protein" ) {
3004             Maasha::Common::run( "mkvtree", "-db $file_tmp -protein -pl $options->{ 'prefix_length' } -allout -indexname $file_tmp > /dev/null 2>&1" );
3005         } else {
3006             Maasha::Common::run( "mkvtree", "-db $file_tmp -dna -pl $options->{ 'prefix_length' } -allout -indexname $file_tmp > /dev/null 2>&1" );
3007         }
3008
3009         unlink $file_tmp;
3010     }
3011 }
3012
3013
3014 sub script_write_align
3015 {
3016     # Martin A. Hansen, August 2007.
3017
3018     # Write pretty alignments aligned sequences in stream.
3019
3020     my ( $in,        # handle to in stream
3021          $out,       # handle to out stream
3022          $options,   # options hash
3023        ) = @_;
3024
3025     # Returns nothing.
3026
3027     my ( $fh, $record, @entries );
3028
3029     $fh = write_stream( $options->{ "data_out" } ) ;
3030
3031     while ( $record = Maasha::Biopieces::get_record( $in ) ) 
3032     {
3033         if ( $record->{ "SEQ_NAME" } and $record->{ "SEQ" } ) {
3034             push @entries, [ $record->{ "SEQ_NAME" }, $record->{ "SEQ" } ];
3035         }
3036
3037         Maasha::Biopieces::put_record( $record, $out ) if not $options->{ "no_stream" };
3038     }
3039
3040     if ( scalar( @entries ) == 2 ) {
3041         Maasha::Align::align_print_pairwise( $entries[ 0 ], $entries[ 1 ], $fh, $options->{ "wrap" } );
3042     } elsif ( scalar ( @entries ) > 2 ) {
3043         Maasha::Align::align_print_multi( \@entries, $fh, $options->{ "wrap" }, $options->{ "no_ruler" }, $options->{ "no_consensus" } );
3044     }
3045
3046     close $fh if $fh;
3047 }
3048
3049
3050 sub script_write_bed
3051 {
3052     # Martin A. Hansen, August 2007.
3053
3054     # Write BED format for the UCSC genome browser using records in stream.
3055
3056     my ( $in,        # handle to in stream
3057          $out,       # handle to out stream
3058          $options,   # options hash
3059        ) = @_;
3060
3061     # Returns nothing.
3062
3063     my ( $cols, $fh, $record, $bed_entry, $new_record );
3064
3065     $cols = $options->{ 'cols' }->[ 0 ];
3066
3067     $fh = Maasha::Biopieces::write_stream( $options->{ 'data_out' }, $options->{ 'compress' } );
3068
3069     while ( $record = Maasha::Biopieces::get_record( $in ) ) 
3070     {
3071         $record = Maasha::UCSC::psl2record( $record ) if $record->{ 'tBaseInsert' }; # Dirty addition to allow Affy data from MySQL to be dumped
3072
3073         if ( $bed_entry = Maasha::UCSC::BED::biopiece2bed( $record, $cols ) ) {
3074             Maasha::UCSC::BED::bed_entry_put( $bed_entry, $fh, $cols, $options->{ 'check' } );
3075         }
3076
3077         Maasha::Biopieces::put_record( $record, $out ) if not $options->{ 'no_stream' };
3078     }
3079
3080     close $fh;
3081 }
3082
3083
3084 sub script_write_psl
3085 {
3086     # Martin A. Hansen, August 2007.
3087
3088     # Write PSL output from stream.
3089
3090     my ( $in,        # handle to in stream
3091          $out,       # handle to out stream
3092          $options,   # options hash
3093        ) = @_;
3094
3095     # Returns nothing.
3096
3097     my ( $fh, $record, @output, $first );
3098
3099     $first = 1;
3100
3101     $fh = write_stream( $options->{ "data_out" }, $options->{ "compress" } );
3102
3103     while ( $record = Maasha::Biopieces::get_record( $in ) ) 
3104     {
3105         Maasha::Biopieces::put_record( $record, $out ) if not $options->{ "no_stream" };
3106
3107         if ( $record->{ "REC_TYPE" } and $record->{ "REC_TYPE" } eq "PSL" )
3108         {
3109             Maasha::UCSC::psl_put_header( $fh ) if $first;
3110             Maasha::UCSC::psl_put_entry( $record, $fh );
3111             $first = 0;
3112         }
3113     }
3114
3115     close $fh;
3116 }
3117
3118
3119 sub script_write_fixedstep
3120 {
3121     # Martin A. Hansen, Juli 2008.
3122
3123     # Write fixedStep entries from recrods in the stream.
3124
3125     my ( $in,        # handle to in stream
3126          $out,       # handle to out stream
3127          $options,   # options hash
3128        ) = @_;
3129
3130     # Returns nothing.
3131
3132     my ( $fh, $record, $entry );
3133
3134     $fh = write_stream( $options->{ "data_out" }, $options->{ "compress" } );
3135
3136     while ( $record = Maasha::Biopieces::get_record( $in ) ) 
3137     {
3138         if ( $entry = Maasha::UCSC::Wiggle::biopiece2fixedstep( $record ) ) {
3139             Maasha::UCSC::Wiggle::fixedstep_entry_put( $entry, $fh );
3140         }
3141
3142         Maasha::Biopieces::put_record( $record, $out ) if not $options->{ "no_stream" };
3143     }
3144
3145     close $fh;
3146 }
3147
3148
3149 sub script_write_2bit
3150 {
3151     # Martin A. Hansen, March 2008.
3152
3153     # Write sequence entries from stream in 2bit format.
3154
3155     my ( $in,        # handle to in stream
3156          $out,       # handle to out stream
3157          $options,   # options hash
3158        ) = @_;
3159
3160     # Returns nothing.
3161
3162     my ( $record, $mask, $tmp_file, $fh_tmp, $fh_in, $fh_out, $entry );
3163
3164     $mask = 1 if not $options->{ "no_mask" };
3165
3166     $tmp_file = "$BP_TMP/write_2bit.fna";
3167     $fh_tmp   = Maasha::Common::write_open( $tmp_file );
3168
3169     $fh_out = write_stream( $options->{ "data_out" } );
3170
3171     while ( $record = Maasha::Biopieces::get_record( $in ) ) 
3172     {
3173         if ( $entry = Maasha::Fasta::biopiece2fasta( $record ) ) {
3174             Maasha::Fasta::put_entry( $entry, $fh_tmp );
3175         }
3176
3177         Maasha::Biopieces::put_record( $record, $out ) if not $options->{ "no_stream" };
3178     }
3179
3180     close $fh_tmp;
3181
3182     $fh_in = Maasha::Common::read_open( $tmp_file );
3183
3184     Maasha::TwoBit::fasta2twobit( $fh_in, $fh_out, $mask );
3185
3186     close $fh_in;
3187     close $fh_out;
3188
3189     unlink $tmp_file;
3190 }
3191
3192
3193 sub script_write_solid
3194 {
3195     # Martin A. Hansen, April 2008.
3196
3197     # Write di-base encoded Solid sequence from entries in stream.
3198
3199     my ( $in,        # handle to in stream
3200          $out,       # handle to out stream
3201          $options,   # options hash
3202        ) = @_;
3203
3204     # Returns nothing.
3205
3206     my ( $record, $fh, $entry );
3207
3208     $fh = write_stream( $options->{ "data_out" }, $options->{ "compress" } );
3209
3210     while ( $record = Maasha::Biopieces::get_record( $in ) ) 
3211     {
3212         if ( $entry = Maasha::Fasta::biopiece2fasta( $record ) )
3213         {
3214             $entry->[ SEQ ] = Maasha::Solid::seq2color_space( uc $entry->[ SEQ ] );
3215
3216             Maasha::Fasta::put_entry( $entry, $fh, $options->{ "wrap" } );
3217         }
3218
3219         Maasha::Biopieces::put_record( $record, $out ) if not $options->{ "no_stream" };
3220     }
3221
3222     close $fh;
3223 }
3224
3225
3226 sub script_write_ucsc_config
3227 {
3228     # Martin A. Hansen, November 2008.
3229
3230     # Write UCSC Genome Broser configuration (.ra file type) from
3231     # records in the stream.
3232
3233     my ( $in,        # handle to in stream
3234          $out,       # handle to out stream
3235          $options,   # options hash
3236        ) = @_;
3237
3238     # Returns nothing.
3239
3240     my ( $record, $fh );
3241
3242     $fh = write_stream( $options->{ "data_out" } );
3243
3244     while ( $record = Maasha::Biopieces::get_record( $in ) ) 
3245     {
3246         Maasha::UCSC::ucsc_config_entry_put( $record, $fh ) if $record->{ "REC_TYPE" } eq "UCSC Config";
3247
3248         Maasha::Biopieces::put_record( $record, $out ) if not $options->{ "no_stream" };
3249     }
3250
3251     close $fh;
3252 }
3253
3254
3255 sub script_plot_seqlogo
3256 {
3257     # Martin A. Hansen, August 2007.
3258
3259     # Calculates and writes a sequence logo for alignments.
3260
3261     my ( $in,        # handle to in stream
3262          $out,       # handle to out stream
3263          $options,   # options hash
3264        ) = @_;
3265
3266     # Returns nothing.
3267
3268     my ( $record, @entries, $logo, $fh );
3269
3270     while ( $record = Maasha::Biopieces::get_record( $in ) ) 
3271     {
3272         if ( $record->{ "SEQ_NAME" } and $record->{ "SEQ" } ) {
3273             push @entries, [ $record->{ "SEQ_NAME" }, $record->{ "SEQ" } ];
3274         }
3275
3276         Maasha::Biopieces::put_record( $record, $out ) if not $options->{ "no_stream" };
3277     }
3278
3279     $logo = Maasha::Plot::seq_logo( \@entries );
3280
3281     $fh = write_stream( $options->{ "data_out" } );
3282
3283     print $fh $logo;
3284
3285     close $fh;
3286 }
3287
3288
3289 sub script_plot_phastcons_profiles
3290 {
3291     # Martin A. Hansen, January 2008.
3292
3293     # Plots PhastCons profiles.
3294
3295     my ( $in,        # handle to in stream
3296          $out,       # handle to out stream
3297          $options,   # options hash
3298        ) = @_;
3299
3300     # Returns nothing.
3301
3302     my ( $phastcons_file, $phastcons_index, $index, $fh_phastcons, $record, $scores, $AoA, $plot, $fh );
3303
3304     $options->{ "title" } ||= "PhastCons Profiles";
3305
3306     $phastcons_file  = Maasha::Config::genome_phastcons( $options->{ "genome" } );
3307     $phastcons_index = Maasha::Config::genome_phastcons_index( $options->{ "genome" } );
3308
3309     $index           = Maasha::UCSC::fixedstep_index_retrieve( $phastcons_index );
3310     $fh_phastcons    = Maasha::Common::read_open( $phastcons_file );
3311
3312     while ( $record = Maasha::Biopieces::get_record( $in ) ) 
3313     {
3314         if ( $record->{ "CHR" } and $record->{ "CHR_BEG" } and $record->{ "CHR_END" } )
3315         {
3316             $scores = Maasha::UCSC::fixedstep_index_lookup( $index, $fh_phastcons, $record->{ "CHR" },
3317                                                                                    $record->{ "CHR_BEG" },
3318                                                                                    $record->{ "CHR_END" },
3319                                                                                    $options->{ "flank" } );
3320
3321             push @{ $AoA }, [ @{ $scores } ];
3322         }
3323
3324         Maasha::Biopieces::put_record( $record, $out ) if not $options->{ "no_stream" };
3325     }
3326
3327     Maasha::UCSC::phastcons_normalize( $AoA );
3328
3329     $AoA = [ [ Maasha::UCSC::phastcons_mean( $AoA ) ] ] if $options->{ "mean" };
3330     $AoA = [ [ Maasha::UCSC::phastcons_median( $AoA ) ] ] if $options->{ "median" };
3331
3332     $AoA = Maasha::Matrix::matrix_flip( $AoA );
3333
3334     $plot = Maasha::Plot::lineplot_simple( $AoA, $options, $BP_TMP );
3335
3336     $fh = write_stream( $options->{ "data_out" } );
3337
3338     print $fh "$_\n" foreach @{ $plot };
3339
3340     close $fh;
3341 }
3342
3343
3344 sub script_analyze_bed
3345 {
3346     # Martin A. Hansen, March 2008.
3347
3348     # Analyze BED entries in stream.
3349
3350     my ( $in,        # handle to in stream
3351          $out,       # handle to out stream
3352          $options,   # options hash
3353        ) = @_;
3354
3355     # Returns nothing.
3356
3357     my ( $record );
3358
3359     while ( $record = Maasha::Biopieces::get_record( $in ) ) 
3360     {
3361         $record = Maasha::UCSC::bed_analyze( $record ) if $record->{ "REC_TYPE" } eq "BED";
3362
3363         Maasha::Biopieces::put_record( $record, $out );
3364     }
3365 }
3366
3367
3368 sub script_analyze_vals
3369 {
3370     # Martin A. Hansen, August 2007.
3371
3372     # Analyze values for given keys in stream.
3373
3374     my ( $in,        # handle to in stream
3375          $out,       # handle to out stream
3376          $options,   # options hash
3377        ) = @_;
3378
3379     # Returns nothing.
3380
3381     my ( $record, $key, @keys, %key_hash, $analysis, $len );
3382
3383     map { $key_hash{ $_ } = 1 } @{ $options->{ "keys" } };
3384
3385     while ( $record = Maasha::Biopieces::get_record( $in ) ) 
3386     {
3387         foreach $key ( keys %{ $record } )
3388         {
3389             next if $options->{ "keys" } and not exists $key_hash{ $key };
3390
3391             $analysis->{ $key }->{ "COUNT" }++;
3392
3393             if ( Maasha::Calc::is_a_number( $record->{ $key } ) )
3394             {
3395                 $analysis->{ $key }->{ "TYPE" } = "num";
3396                 $analysis->{ $key }->{ "SUM" } += $record->{ $key };
3397                 $analysis->{ $key }->{ "MAX" } = $record->{ $key } if $record->{ $key } > $analysis->{ $key }->{ "MAX" } or not $analysis->{ $key }->{ "MAX" };
3398                 $analysis->{ $key }->{ "MIN" } = $record->{ $key } if $record->{ $key } < $analysis->{ $key }->{ "MIN" } or not $analysis->{ $key }->{ "MIN" };
3399             }
3400             else
3401             {
3402                 $len = length $record->{ $key };
3403
3404                 $analysis->{ $key }->{ "TYPE" } = "alph";
3405                 $analysis->{ $key }->{ "SUM" } += $len;
3406                 $analysis->{ $key }->{ "MAX" } = $len if $len > $analysis->{ $key }->{ "MAX" } or not $analysis->{ $key }->{ "MAX" };
3407                 $analysis->{ $key }->{ "MIN" } = $len if $len < $analysis->{ $key }->{ "MIM" } or not $analysis->{ $key }->{ "MIN" };
3408             }
3409         }
3410
3411         Maasha::Biopieces::put_record( $record, $out ) if not $options->{ "no_stream" };
3412     }
3413
3414     foreach $key ( keys %{ $analysis } )
3415     {
3416         $analysis->{ $key }->{ "MEAN" } = sprintf "%.2f", $analysis->{ $key }->{ "SUM" } / $analysis->{ $key }->{ "COUNT" };
3417         $analysis->{ $key }->{ "SUM" }  = sprintf "%.2f", $analysis->{ $key }->{ "SUM" };
3418     }
3419
3420     my ( $keys, $types, $counts, $mins, $maxs, $sums, $means );
3421
3422     $keys   = "KEY  ";
3423     $types  = "TYPE ";
3424     $counts = "COUNT";
3425     $mins   = "MIN  ";
3426     $maxs   = "MAX  ";
3427     $sums   = "SUM  ";
3428     $means  = "MEAN ";
3429
3430     if ( $options->{ "keys" } ) {
3431         @keys = @{ $options->{ "keys" } };
3432     } else {
3433         @keys = keys %{ $analysis };
3434     }
3435
3436     foreach $key ( @keys )
3437     {
3438         $keys   .= sprintf "% 15s", $key;
3439         $types  .= sprintf "% 15s", $analysis->{ $key }->{ "TYPE" };
3440         $counts .= sprintf "% 15s", $analysis->{ $key }->{ "COUNT" };
3441         $mins   .= sprintf "% 15s", $analysis->{ $key }->{ "MIN" };
3442         $maxs   .= sprintf "% 15s", $analysis->{ $key }->{ "MAX" };
3443         $sums   .= sprintf "% 15s", $analysis->{ $key }->{ "SUM" };
3444         $means  .= sprintf "% 15s", $analysis->{ $key }->{ "MEAN" };
3445     }
3446
3447     print $out "$keys\n";
3448     print $out "$types\n";
3449     print $out "$counts\n";
3450     print $out "$mins\n";
3451     print $out "$maxs\n";
3452     print $out "$sums\n";
3453     print $out "$means\n";
3454 }
3455
3456
3457 sub script_head_records
3458 {
3459     # Martin A. Hansen, August 2007.
3460
3461     # Display the first sequences in stream.
3462
3463     my ( $in,        # handle to in stream
3464          $out,       # handle to out stream
3465          $options,   # options hash
3466        ) = @_;
3467
3468     # Returns nothing.
3469
3470     my ( $record, $count );
3471
3472     $options->{ "num" } ||= 10;
3473
3474     $count = 0;
3475
3476     while ( $record = Maasha::Biopieces::get_record( $in ) ) 
3477     {
3478         $count++;
3479
3480         Maasha::Biopieces::put_record( $record, $out );
3481
3482         last if $count == $options->{ "num" };
3483     }
3484 }
3485
3486
3487 sub script_remove_keys
3488 {
3489     # Martin A. Hansen, August 2007.
3490
3491     # Remove keys from stream.
3492
3493     my ( $in,        # handle to in stream
3494          $out,       # handle to out stream
3495          $options,   # options hash
3496        ) = @_;
3497
3498     # Returns nothing.
3499
3500     my ( $record, $new_record );
3501
3502     while ( $record = Maasha::Biopieces::get_record( $in ) ) 
3503     {
3504         if ( $options->{ "keys" } )
3505         {
3506             map { delete $record->{ $_ } } @{ $options->{ "keys" } };
3507         }
3508         elsif ( $options->{ "save_keys" } )
3509         {
3510             map { $new_record->{ $_ } = $record->{ $_ } if exists $record->{ $_ } } @{ $options->{ "save_keys" } };
3511
3512             $record = $new_record;
3513         }
3514
3515         Maasha::Biopieces::put_record( $record, $out ) if keys %{ $record };
3516     }
3517 }
3518
3519
3520 sub script_remove_adaptor
3521 {
3522     # Martin A. Hansen, August 2008.
3523
3524     # Find and remove adaptor from sequences in the stream.
3525
3526     my ( $in,        # handle to in stream
3527          $out,       # handle to out stream
3528          $options,   # options hash
3529        ) = @_;
3530
3531     # Returns nothing.
3532
3533     my ( $record, $adaptor, $seq, $adaptor_len, $seq_len, $offset, $max_match, $max_mismatch, $pos );
3534
3535     $options->{ "remove" } ||= "after";
3536
3537     $max_mismatch = $options->{ "mismatches" } || 0;
3538     $offset       = $options->{ "offset" };
3539
3540     if ( not defined $offset ) {
3541         $offset = 0;
3542     } else {
3543         $offset--;
3544     }
3545
3546     $adaptor      = uc $options->{ "adaptor" };
3547     $adaptor_len  = length $adaptor;
3548
3549     while ( $record = Maasha::Biopieces::get_record( $in ) ) 
3550     {
3551         if ( $record->{ "SEQ" } )
3552         {
3553             $seq     = uc $record->{ "SEQ" };
3554             $seq_len = length $seq;
3555
3556             $pos = Maasha::Common::index_m( $seq, $adaptor, $seq_len, $adaptor_len, $offset, $max_mismatch );
3557
3558             $record->{ "ADAPTOR_POS" } = $pos;
3559
3560             if ( $pos >= 0 and $options->{ "remove" } ne "skip" )
3561             {
3562                 if ( $options->{ "remove" } eq "after" )
3563                 {
3564                     $record->{ "SEQ" }     = substr $record->{ "SEQ" }, 0, $pos;
3565                     $record->{ "SEQ_LEN" } = $pos;
3566                 }
3567                 else
3568                 {
3569                     $record->{ "SEQ" }     = substr $record->{ "SEQ" }, $pos + $adaptor_len;
3570                     $record->{ "SEQ_LEN" } = length $record->{ "SEQ" };
3571                 }
3572             }
3573
3574             Maasha::Biopieces::put_record( $record, $out );
3575         }
3576         else
3577         {
3578             Maasha::Biopieces::put_record( $record, $out );
3579         }
3580     }
3581 }
3582
3583
3584 sub script_remove_mysql_tables
3585 {
3586     # Martin A. Hansen, November 2008.
3587
3588     # Remove MySQL tables from values in stream.
3589
3590     my ( $in,        # handle to in stream
3591          $out,       # handle to out stream
3592          $options,   # options hash
3593        ) = @_;
3594
3595     # Returns nothing.
3596
3597     my ( $record, %table_hash, $dbh, $table );
3598
3599     $options->{ "user" }     ||= Maasha::UCSC::ucsc_get_user();
3600     $options->{ "password" } ||= Maasha::UCSC::ucsc_get_password();
3601
3602     map { $table_hash{ $_ } = 1 } @{ $options->{ 'tables' } };
3603
3604     while ( $record = Maasha::Biopieces::get_record( $in ) )
3605     {
3606         map { $table_hash{ $record->{ $_ } } = 1 } @{ $options->{ 'keys' } };
3607
3608         Maasha::Biopieces::put_record( $record, $out ) if not $options->{ 'no_stream' };
3609     }
3610
3611     $dbh = Maasha::SQL::connect( $options->{ "database" }, $options->{ "user" }, $options->{ "password" } );
3612
3613     foreach $table ( sort keys %table_hash )
3614     {
3615         if ( Maasha::SQL::table_exists( $dbh, $table ) )
3616         {
3617             print STDERR qq(Removing table "$table" from database "$options->{ 'database' }" ... ) if $options->{ 'verbose' };
3618             Maasha::SQL::delete_table( $dbh, $table );
3619             print STDERR "done.\n" if $options->{ 'verbose' };
3620         }
3621         else
3622         {
3623             print STDERR qq(WARNING: table "$table" not found in database "$options->{ 'database' }\n");
3624         }
3625     }
3626
3627     Maasha::SQL::disconnect( $dbh );
3628 }
3629
3630
3631 sub script_remove_ucsc_tracks
3632 {
3633     # Martin A. Hansen, November 2008.
3634
3635     # Remove track from MySQL tables and config file.
3636
3637     my ( $in,        # handle to in stream
3638          $out,       # handle to out stream
3639          $options,   # options hash
3640        ) = @_;
3641
3642     # Returns nothing.
3643
3644     my ( $record, %track_hash, $fh_in, $fh_out, $track, @tracks, @new_tracks, $dbh );
3645
3646     $options->{ 'user' }        ||= Maasha::UCSC::ucsc_get_user();
3647     $options->{ 'password' }    ||= Maasha::UCSC::ucsc_get_password();
3648     $options->{ 'config_file' } ||= "$ENV{ 'HOME' }/ucsc/my_tracks.ra";
3649
3650     map { $track_hash{ $_ } = 1 } @{ $options->{ 'tracks' } };
3651
3652     while ( $record = Maasha::Biopieces::get_record( $in ) )
3653     {
3654         map { $track_hash{ $record->{ $_ } } = 1 } @{ $options->{ 'keys' } };
3655
3656         Maasha::Biopieces::put_record( $record, $out ) if not $options->{ 'no_stream' };
3657     }
3658
3659     $fh_in = Maasha::Filesys::file_read_open( $options->{ 'config_file' } );
3660     
3661     while ( $track = Maasha::UCSC::ucsc_config_entry_get( $fh_in ) ) {
3662         push @tracks, $track;
3663     }
3664
3665     close $fh_in;
3666
3667     foreach $track ( @tracks )
3668     {
3669         if ( $track->{ 'database' } eq $options->{ 'database' } and exists $track_hash{ $track->{ 'track' } } ) {
3670             print STDERR qq(Removing track "$track->{ 'track' }" from config file.\n) if $options->{ 'verbose' };
3671         } else {
3672             push @new_tracks, $track;
3673         }
3674     }
3675
3676     rename "$options->{ 'config_file' }", "$options->{ 'config_file' }~";
3677
3678     $fh_out = Maasha::Filesys::file_write_open( $options->{ 'config_file' } );
3679
3680     map { Maasha::UCSC::ucsc_config_entry_put( $_, $fh_out ) } @new_tracks;
3681
3682     close $fh_out;
3683
3684     # ---- locate track in database ----
3685
3686     $dbh = Maasha::SQL::connect( $options->{ "database" }, $options->{ "user" }, $options->{ "password" } );
3687
3688     foreach $track ( sort keys %track_hash )
3689     {
3690         if ( Maasha::SQL::table_exists( $dbh, $track ) )
3691         {
3692             print STDERR qq(Removing table "$track" from database "$options->{ 'database' }" ... ) if $options->{ 'verbose' };
3693             Maasha::SQL::delete_table( $dbh, $track );
3694             print STDERR "done.\n" if $options->{ 'verbose' };
3695         }
3696         else
3697         {
3698             print STDERR qq(WARNING: table "$track" not found in database "$options->{ 'database' }\n");
3699         }
3700     }
3701
3702     Maasha::SQL::disconnect( $dbh );
3703
3704     Maasha::Common::run( "ucscMakeTracks.pl", "-b > /dev/null 2>&1" );
3705 }
3706
3707
3708 sub script_rename_keys
3709 {
3710     # Martin A. Hansen, August 2007.
3711
3712     # Rename keys in stream.
3713
3714     my ( $in,        # handle to in stream
3715          $out,       # handle to out stream
3716          $options,   # options hash
3717        ) = @_;
3718
3719     # Returns nothing.
3720
3721     my ( $record );
3722
3723     while ( $record = Maasha::Biopieces::get_record( $in ) ) 
3724     {
3725         if ( exists $record->{ $options->{ "keys" }->[ 0 ] } )
3726         {
3727             $record->{ $options->{ "keys" }->[ 1 ] } = $record->{ $options->{ "keys" }->[ 0 ] };
3728
3729             delete $record->{ $options->{ "keys" }->[ 0 ] };
3730         }
3731
3732         Maasha::Biopieces::put_record( $record, $out );
3733     }
3734 }
3735
3736
3737 sub script_uniq_vals
3738 {
3739     # Martin A. Hansen, August 2007.
3740
3741     # Find unique values in stream.
3742
3743     my ( $in,        # handle to in stream
3744          $out,       # handle to out stream
3745          $options,   # options hash
3746        ) = @_;
3747
3748     # Returns nothing.
3749
3750     my ( %hash, $record );
3751
3752     while ( $record = Maasha::Biopieces::get_record( $in ) ) 
3753     {
3754         if ( $record->{ $options->{ "key" } } )
3755         {
3756             if ( not $hash{ $record->{ $options->{ "key" } } } and not $options->{ "invert" } )
3757             {
3758                 Maasha::Biopieces::put_record( $record, $out );
3759
3760                 $hash{ $record->{ $options->{ "key" } } } = 1;
3761             }
3762             elsif ( $hash{ $record->{ $options->{ "key" } } } and $options->{ "invert" } )
3763             {
3764                 Maasha::Biopieces::put_record( $record, $out );
3765             }
3766             else
3767             {
3768                 $hash{ $record->{ $options->{ "key" } } } = 1;
3769             }
3770         }
3771         else
3772         {
3773             Maasha::Biopieces::put_record( $record, $out );
3774         }
3775     }
3776 }
3777
3778
3779 sub script_merge_vals
3780 {
3781     # Martin A. Hansen, August 2007.
3782
3783     # Rename keys in stream.
3784
3785     my ( $in,        # handle to in stream
3786          $out,       # handle to out stream
3787          $options,   # options hash
3788        ) = @_;
3789
3790     # Returns nothing.
3791
3792     my ( $record, @join, $i );
3793
3794     $options->{ "delimit" } ||= '_';
3795
3796     while ( $record = Maasha::Biopieces::get_record( $in ) ) 
3797     {
3798         if ( exists $record->{ $options->{ "keys" }->[ 0 ] } )
3799         {
3800             @join = $record->{ $options->{ "keys" }->[ 0 ] };
3801             
3802             for ( $i = 1; $i < @{ $options->{ "keys" } }; $i++ ) {
3803                 push @join, $record->{ $options->{ "keys" }->[ $i ] } if exists $record->{ $options->{ "keys" }->[ $i ] };
3804             }
3805
3806             $record->{ $options->{ "keys" }->[ 0 ] } = join $options->{ "delimit" }, @join;
3807         }
3808
3809         Maasha::Biopieces::put_record( $record, $out );
3810     }
3811 }
3812
3813
3814 sub script_merge_records
3815 {
3816     # Martin A. Hansen, July 2008.
3817
3818     # Merges records in the stream based on identical values of two given keys.
3819
3820     my ( $in,        # handle to in stream
3821          $out,       # handle to out stream
3822          $options,   # options hash
3823        ) = @_;
3824
3825     # Returns nothing.
3826
3827     my ( $merge, $record, $file1, $file2, $fh1, $fh2, $key1, $key2, @keys1, @keys2, @vals1, @vals2,
3828          $num1, $num2, $num, $cmp, $i );
3829
3830     $merge = $options->{ "merge" } || "AandB";
3831
3832     $file1 = "$BP_TMP/merge_records1.tmp";
3833     $file2 = "$BP_TMP/merge_records2.tmp";
3834
3835     $fh1   = Maasha::Common::write_open( $file1 );
3836     $fh2   = Maasha::Common::write_open( $file2 );
3837
3838     $key1  = $options->{ "keys" }->[ 0 ];
3839     $key2  = $options->{ "keys" }->[ 1 ];
3840
3841     $num   = $key2 =~ s/n$//;
3842     $num1  = 0;
3843     $num2  = 0;
3844
3845     while ( $record = Maasha::Biopieces::get_record( $in ) ) 
3846     {
3847         if ( exists $record->{ $key1 } )
3848         {
3849             @keys1 = $key1;
3850             @vals1 = $record->{ $key1 };
3851
3852             delete $record->{ $key1 };
3853
3854             map { push @keys1, $_; push @vals1, $record->{ $_ } } keys %{ $record };
3855
3856             print $fh1 join( "\t", @vals1 ), "\n";
3857
3858             $num1++;
3859         }
3860         elsif ( exists $record->{ $key2 } )
3861         {
3862             @keys2 = $key2;
3863             @vals2 = $record->{ $key2 };
3864
3865             delete $record->{ $key2 };
3866
3867             map { push @keys2, $_; push @vals2, $record->{ $_ } } keys %{ $record };
3868
3869             print $fh2 join( "\t", @vals2 ), "\n";
3870
3871             $num2++;
3872         }
3873     }
3874
3875     close $fh1;
3876     close $fh2;
3877
3878     if ( $num )
3879     {
3880         Maasha::Common::run( "sort", "-k 1,1n $file1 > $file1.sort" ) and rename "$file1.sort", $file1;
3881         Maasha::Common::run( "sort", "-k 1,1n $file2 > $file2.sort" ) and rename "$file2.sort", $file2;
3882     }
3883     else
3884     {
3885         Maasha::Common::run( "sort", "-k 1,1 $file1 > $file1.sort" ) and rename "$file1.sort", $file1;
3886         Maasha::Common::run( "sort", "-k 1,1 $file2 > $file2.sort" ) and rename "$file2.sort", $file2;
3887     }
3888
3889     $fh1 = Maasha::Common::read_open( $file1 );
3890     $fh2 = Maasha::Common::read_open( $file2 );
3891
3892     @vals1 = Maasha::Common::get_fields( $fh1 );
3893     @vals2 = Maasha::Common::get_fields( $fh2 );
3894
3895     while ( $num1 > 0 and $num2 > 0 )
3896     {
3897         undef $record;
3898
3899         if ( $num ) {
3900             $cmp = $vals1[ 0 ] <=> $vals2[ 0 ];
3901         } else {
3902             $cmp = $vals1[ 0 ] cmp $vals2[ 0 ];
3903         }
3904
3905         if ( $cmp < 0 )
3906         {
3907             if ( $merge =~ /^(AorB|AnotB)$/ )
3908             {
3909                 for ( $i = 0; $i < @keys1; $i++ ) {
3910                     $record->{ $keys1[ $i ] } = $vals1[ $i ];
3911                 }
3912
3913                 Maasha::Biopieces::put_record( $record, $out );
3914             }
3915
3916             @vals1 = Maasha::Common::get_fields( $fh1 );
3917             $num1--;
3918         }
3919         elsif ( $cmp > 0 )
3920         {
3921             if ( $merge =~ /^(BorA|BnotA)$/ )
3922             {
3923                 for ( $i = 0; $i < @keys2; $i++ ) {
3924                     $record->{ $keys2[ $i ] } = $vals2[ $i ];
3925                 }
3926
3927                 Maasha::Biopieces::put_record( $record, $out );
3928             }
3929
3930             @vals2 = Maasha::Common::get_fields( $fh2 );
3931             $num2--;
3932         }
3933         else
3934         {
3935             if ( $merge =~ /^(AandB|AorB|BorA)$/ )
3936             {
3937                 for ( $i = 0; $i < @keys1; $i++ ) {
3938                     $record->{ $keys1[ $i ] } = $vals1[ $i ];
3939                 }
3940
3941                 for ( $i = 1; $i < @keys2; $i++ ) {
3942                     $record->{ $keys2[ $i ] } = $vals2[ $i ];
3943                 }
3944             
3945                 Maasha::Biopieces::put_record( $record, $out );
3946             }
3947
3948             @vals1 = Maasha::Common::get_fields( $fh1 );
3949             @vals2 = Maasha::Common::get_fields( $fh2 );
3950             $num1--;
3951             $num2--;
3952         }
3953     }
3954
3955     close $fh1;
3956     close $fh2;
3957
3958     unlink $file1;
3959     unlink $file2;
3960
3961     if ( $num1 > 0 and $merge =~ /^(AorB|AnotB)$/ )
3962     {
3963         undef $record;
3964
3965         for ( $i = 0; $i < @keys1; $i++ ) {
3966             $record->{ $keys1[ $i ] } = $vals1[ $i ];
3967         }
3968
3969         Maasha::Biopieces::put_record( $record, $out );
3970     }
3971
3972     if ( $num2 > 0 and $merge =~ /^(BorA|BnotA)$/ )
3973     {
3974         undef $record;
3975
3976         for ( $i = 0; $i < @keys2; $i++ ) {
3977             $record->{ $keys2[ $i ] } = $vals2[ $i ];
3978         }
3979
3980         Maasha::Biopieces::put_record( $record, $out );
3981     }
3982 }
3983
3984
3985 sub script_compute
3986 {
3987     # Martin A. Hansen, August 2007.
3988
3989     # Evaluate extression for records in stream.
3990
3991     my ( $in,        # handle to in stream
3992          $out,       # handle to out stream
3993          $options,   # options hash
3994        ) = @_;
3995
3996     # Returns nothing.
3997
3998     my ( $record, $eval_key, @keys, $eval_val );
3999
4000     while ( $record = Maasha::Biopieces::get_record( $in ) ) 
4001     {
4002         if ( $options->{ "eval" } )
4003         {
4004             if ( $options->{ "eval" } =~ /^(\S+)\s*=\s*(.+)$/ )
4005             {
4006                 $eval_key = $1;
4007                 $eval_val = $2;
4008
4009                 if ( not @keys )
4010                 {
4011                     @keys = split /\s+|\+|-|\*|\/|\*\*/, $eval_val;
4012
4013                     @keys = grep { exists $record->{ $_ } } @keys;
4014                 }
4015
4016                 map { $eval_val =~ s/\Q$_\E/$record->{ $_ }/g } @keys;
4017
4018                 $record->{ $eval_key } = eval "$eval_val";
4019                 Maasha::Common::error( qq(eval "$eval_key = $eval_val" failed -> $@) ) if $@;
4020             }
4021             else
4022             {
4023                 Maasha::Common::error( qq(Bad compute expression: "$options->{ 'eval' }"\n) );
4024             }
4025         } 
4026
4027         Maasha::Biopieces::put_record( $record, $out );
4028     }
4029 }
4030
4031
4032 sub script_flip_tab
4033 {
4034     # Martin A. Hansen, June 2008.
4035
4036     # Flip a table.
4037
4038     my ( $in,        # handle to in stream
4039          $out,       # handle to out stream
4040          $options,   # options hash
4041        ) = @_;
4042
4043     # Returns nothing.
4044
4045     my ( $record, $key, $A, $B, @rows, @matrix, $row, $i );
4046
4047     while ( $record = Maasha::Biopieces::get_record( $in ) ) 
4048     {
4049         undef @rows;
4050
4051         foreach $key ( sort { $A = $a; $B = $b; $A =~ s/^V(\d+)$/$1/; $B =~ s/^V(\d+)$/$1/; $A <=> $B } keys %{ $record } )
4052         {
4053             push @rows, $record->{ $key };
4054
4055         }
4056
4057         push @matrix, [ @rows ];
4058     }
4059
4060     undef $record;
4061
4062     @matrix = Maasha::Matrix::matrix_flip( \@matrix );
4063
4064     foreach $row ( @matrix )
4065     {
4066         for ( $i = 0; $i < @{ $row }; $i++ ) {
4067             $record->{ "V$i" } = $row->[ $i ];
4068         }
4069
4070         Maasha::Biopieces::put_record( $record, $out );
4071     }
4072 }
4073
4074
4075 sub script_count_records
4076 {
4077     # Martin A. Hansen, August 2007.
4078
4079     # Count records in stream.
4080
4081     my ( $in,        # handle to in stream
4082          $out,       # handle to out stream
4083          $options,   # options hash
4084        ) = @_;
4085
4086     # Returns nothing.
4087
4088     my ( $record, $count, $result, $fh, $line );
4089
4090     $count = 0;
4091
4092     if ( $options->{ "no_stream" } )
4093     {
4094         while ( $line = <$in> )
4095         {
4096             chomp $line;
4097
4098             $count++ if $line eq "---";
4099         }
4100     }
4101     else
4102     {
4103         while ( $record = Maasha::Biopieces::get_record( $in ) ) 
4104         {
4105             Maasha::Biopieces::put_record( $record, $out );
4106
4107             $count++;
4108         }
4109     }
4110
4111     $result = { "RECORDS_COUNT" => $count };
4112
4113     $fh = write_stream( $options->{ "data_out" } );
4114
4115     Maasha::Biopieces::put_record( $result, $fh );
4116
4117     close $fh;
4118 }
4119
4120
4121 sub script_random_records
4122 {
4123     # Martin A. Hansen, August 2007.
4124
4125     # Pick a number or random records from stream.
4126
4127     my ( $in,        # handle to in stream
4128          $out,       # handle to out stream
4129          $options,   # options hash
4130        ) = @_;
4131
4132     # Returns nothing.
4133
4134     my ( $record, $tmp_file, $fh_out, $fh_in, $count, $i, %rand_hash, $rand, $max );
4135
4136     $options->{ "num" } ||= 10;
4137
4138     $tmp_file = "$BP_TMP/random_records.tmp";
4139
4140     $fh_out = Maasha::Common::write_open( $tmp_file );
4141
4142     $count = 0;
4143
4144     while ( $record = Maasha::Biopieces::get_record( $in ) ) 
4145     {
4146         Maasha::Biopieces::put_record( $record, $fh_out );
4147
4148         $count++;
4149     }
4150
4151     close $fh_out;
4152
4153     $max = 0;
4154     $i   = 0;
4155
4156     Maasha::Common::error( qq(Requested random records > records in stream) ) if $options->{ "num" } > $count;
4157
4158     while ( $i < $options->{ "num" } )
4159     {
4160         $rand = int( rand( $count ) );
4161     
4162         if ( not exists $rand_hash{ $rand } )
4163         {
4164             $rand_hash{ $rand } = 1;
4165
4166             $max = $rand if $rand > $max;
4167
4168             $i++;
4169         }
4170     }
4171
4172     $fh_in = Maasha::Common::read_open( $tmp_file );
4173
4174     $count = 0;
4175
4176     while ( $record = Maasha::Biopieces::get_record( $fh_in ) ) 
4177     {
4178         Maasha::Biopieces::put_record( $record, $out ) if exists $rand_hash{ $count };
4179
4180         last if $count == $max;
4181
4182         $count++;
4183     }
4184
4185     close $fh_in;
4186
4187     unlink $tmp_file;
4188 }
4189
4190
4191 sub script_sort_records
4192 {
4193     # Martin A. Hansen, August 2007.
4194
4195     # Sort to sort records according to keys.
4196
4197     my ( $in,        # handle to in stream
4198          $out,       # handle to out stream
4199          $options,   # options hash
4200        ) = @_;
4201
4202     # Returns nothing.
4203
4204     my ( @keys, $key, @sort_cmd, $sort_str, $sort_sub, @records, $record, $i );
4205
4206     foreach $key ( @{ $options->{ "keys" } } )
4207     {
4208         if ( $key =~ s/n$// ) {
4209             push @sort_cmd, qq(\$a->{ "$key" } <=> \$b->{ "$key" });
4210         } else {
4211             push @sort_cmd, qq(\$a->{ "$key" } cmp \$b->{ "$key" });
4212         }
4213     }
4214
4215     $sort_str = join " or ", @sort_cmd;
4216     $sort_sub = eval "sub { $sort_str }";   # NB security issue!
4217
4218     while ( $record = Maasha::Biopieces::get_record( $in ) ) {
4219         push @records, $record;
4220     }
4221
4222     @records = sort $sort_sub @records;
4223
4224     if ( $options->{ "reverse" } )
4225     {
4226         for ( $i = scalar @records - 1; $i >= 0; $i-- ) {
4227             Maasha::Biopieces::put_record( $records[ $i ], $out );
4228         }
4229     }
4230     else
4231     {
4232         for ( $i = 0; $i < scalar @records; $i++ ) {
4233             Maasha::Biopieces::put_record( $records[ $i ], $out );
4234         }
4235     }
4236 }
4237
4238
4239 sub script_count_vals
4240 {
4241     # Martin A. Hansen, August 2007.
4242
4243     # Count records in stream.
4244
4245     my ( $in,        # handle to in stream
4246          $out,       # handle to out stream
4247          $options,   # options hash
4248        ) = @_;
4249
4250     # Returns nothing.
4251
4252     my ( $num, $record, %count_hash, @records, $tmp_file, $fh_out, $fh_in, $cache );
4253
4254     $tmp_file = "$BP_TMP/count_cache.tmp";
4255
4256     $fh_out   = Maasha::Common::write_open( $tmp_file );
4257
4258     $cache    = 0;
4259     $num      = 0;
4260
4261     while ( $record = Maasha::Biopieces::get_record( $in ) ) 
4262     {
4263         map { $count_hash{ $_ }{ $record->{ $_ } }++ if exists $record->{ $_ } } @{ $options->{ "keys" } };
4264
4265         push @records, $record;
4266
4267         if ( scalar @records > 5_000_000 )   # too many records to hold in memory - use disk cache
4268         {
4269             map { Maasha::Biopieces::put_record( $_, $fh_out ) } @records;
4270
4271             undef @records;
4272
4273             $cache = 1;
4274         }
4275
4276         print STDERR "verbose: records read $num\n" if ( $options->{ 'verbose' } and ( $num % 1_000_000 ) == 0 );
4277
4278         $num++;
4279     }
4280
4281     close $fh_out;
4282
4283     if ( $cache )
4284     {
4285         $num   = 0;
4286
4287         $fh_in = Maasha::Common::read_open( $tmp_file );
4288
4289         while ( $record = Maasha::Biopieces::get_record( $fh_in ) )
4290         {
4291             map { $record->{ $_ . "_COUNT" } = $count_hash{ $_ }{ $record->{ $_ } } if exists $record->{ $_ } } @{ $options->{ "keys" } };
4292
4293             Maasha::Biopieces::put_record( $record, $out );
4294
4295             print STDERR "verbose: cache read $num\n" if ( $options->{ 'verbose' } and ( $num % 1_000_000 ) == 0 );
4296
4297             $num++;
4298         }
4299     
4300         close $fh_in;
4301     }
4302
4303     foreach $record ( @records )
4304     {
4305         map { $record->{ $_ . "_COUNT" } = $count_hash{ $_ }{ $record->{ $_ } } if exists $record->{ $_ } } @{ $options->{ "keys" } };
4306
4307         Maasha::Biopieces::put_record( $record, $out );
4308     }
4309
4310     unlink $tmp_file;
4311 }
4312
4313
4314 sub script_plot_histogram
4315 {
4316     # Martin A. Hansen, September 2007.
4317
4318     # Plot a simple histogram for a given key using GNU plot.
4319
4320     my ( $in,        # handle to in stream
4321          $out,       # handle to out stream
4322          $options,   # options hash
4323        ) = @_;
4324
4325     # Returns nothing.
4326
4327     my ( $record, %data_hash, $max, @data_list, $i, $result, $fh );
4328
4329     $options->{ "title" } ||= "Histogram";
4330     $options->{ "sort" }  ||= "num";
4331
4332     while ( $record = Maasha::Biopieces::get_record( $in ) ) 
4333     {
4334         $data_hash{ $record->{ $options->{ "key" } } }++ if defined $record->{ $options->{ "key" } };
4335
4336         Maasha::Biopieces::put_record( $record, $out ) if not $options->{ "no_stream" };
4337     }
4338
4339     if ( $options->{ "sort" } eq "num" ) {
4340         map { push @data_list, [ $_, $data_hash{ $_ } ] } sort { $a <=> $b } keys %data_hash;
4341     } else {
4342         map { push @data_list, [ $_, $data_hash{ $_ } ] } sort keys %data_hash;
4343     }
4344
4345     $result = Maasha::Plot::histogram_simple( \@data_list, $options );
4346
4347     $fh = write_stream( $options->{ "data_out" } );
4348
4349     print $fh "$_\n" foreach @{ $result };
4350
4351     close $fh;
4352 }
4353
4354
4355 sub script_plot_lendist
4356 {
4357     # Martin A. Hansen, August 2007.
4358
4359     # Plot length distribution using GNU plot.
4360
4361     my ( $in,        # handle to in stream
4362          $out,       # handle to out stream
4363          $options,   # options hash
4364        ) = @_;
4365
4366     # Returns nothing.
4367
4368     my ( $record, %data_hash, $max, @data_list, $i, $result, $fh );
4369
4370     $options->{ "title" } ||= "Length Distribution";
4371
4372     while ( $record = Maasha::Biopieces::get_record( $in ) ) 
4373     {
4374         $data_hash{ $record->{ $options->{ "key" } } }++ if defined $record->{ $options->{ "key" } };
4375
4376         Maasha::Biopieces::put_record( $record, $out ) if not $options->{ "no_stream" };
4377     }
4378
4379     $max = Maasha::Calc::list_max( [ keys %data_hash ] );
4380
4381     for ( $i = 0; $i < $max; $i++ ) {
4382         push @data_list, [ $i, $data_hash{ $i } || 0 ];
4383     }
4384
4385     $result = Maasha::Plot::histogram_lendist( \@data_list, $options );
4386
4387     $fh = write_stream( $options->{ "data_out" } );
4388
4389     print $fh "$_\n" foreach @{ $result };
4390
4391     close $fh;
4392 }
4393
4394
4395 sub script_plot_chrdist
4396 {
4397     # Martin A. Hansen, August 2007.
4398
4399     # Plot chromosome distribution using GNU plot.
4400
4401     my ( $in,        # handle to in stream
4402          $out,       # handle to out stream
4403          $options,   # options hash
4404        ) = @_;
4405
4406     # Returns nothing.
4407
4408     my ( $record, %data_hash, @data_list, $elem, $sort_key, $count, $result, $fh );
4409
4410     $options->{ "title" } ||= "Chromosome Distribution";
4411
4412     while ( $record = Maasha::Biopieces::get_record( $in ) ) 
4413     {
4414         if ( $record->{ "CHR" } ) {                                                             # generic
4415             $data_hash{ $record->{ "CHR" } }++;
4416         } elsif ( $record->{ "REC_TYPE" } eq "PATSCAN" and $record->{ "S_ID" } =~ /^chr/i ) {   # patscan
4417             $data_hash{ $record->{ "S_ID" } }++;
4418         } elsif ( $record->{ "REC_TYPE" } eq "PSL" and $record->{ "S_ID" } =~ /^chr/i ) {       # BLAT / PSL
4419             $data_hash{ $record->{ "S_ID" } }++;
4420         } elsif ( $record->{ "REC_TYPE" } eq "BLAST" and $record->{ "S_ID" } =~ /^chr/i ) {     # BLAST
4421             $data_hash{ $record->{ "S_ID" } }++;
4422         }
4423
4424         Maasha::Biopieces::put_record( $record, $out ) if not $options->{ "no_stream" };
4425     }
4426
4427     foreach $elem ( keys %data_hash )
4428     {
4429         $sort_key = $elem;
4430
4431         $sort_key =~ s/chr//i;
4432     
4433         $sort_key =~ s/^X(.*)/99$1/;
4434         $sort_key =~ s/^Y(.*)/99$1/;
4435         $sort_key =~ s/^Z(.*)/999$1/;
4436         $sort_key =~ s/^M(.*)/9999$1/;
4437         $sort_key =~ s/^U(.*)/99999$1/;
4438
4439         $count = $sort_key =~ tr/_//;
4440
4441         $sort_key =~ s/_.*/"999999" x $count/ex;
4442
4443         push @data_list, [ $elem, $data_hash{ $elem }, $sort_key ];
4444     }
4445
4446     @data_list = sort { $a->[ 2 ] <=> $b->[ 2 ] } @data_list;
4447
4448     $result = Maasha::Plot::histogram_chrdist( \@data_list, $options );
4449
4450     $fh = write_stream( $options->{ "data_out" } );
4451
4452     print $fh "$_\n" foreach @{ $result };
4453
4454     close $fh;
4455 }
4456
4457
4458 sub script_plot_karyogram
4459 {
4460     # Martin A. Hansen, August 2007.
4461
4462     # Plot hits on karyogram.
4463
4464     my ( $in,        # handle to in stream
4465          $out,       # handle to out stream
4466          $options,   # options hash
4467        ) = @_;
4468
4469     # Returns nothing.
4470
4471     my ( %options, $record, @data, $fh, $result, %data_hash );
4472
4473     $options->{ "genome" }     ||= "human";
4474     $options->{ "feat_color" } ||= "black";
4475
4476     while ( $record = Maasha::Biopieces::get_record( $in ) ) 
4477     {
4478         if ( $record->{ "CHR" } and $record->{ "CHR_BEG" } and $record->{ "CHR_END" } )
4479         {
4480             push @{ $data_hash{ $record->{ "CHR" } } }, [ $record->{ "CHR_BEG" }, $record->{ "CHR_END" }, $options->{ "feat_color" } ];
4481         }
4482
4483         Maasha::Biopieces::put_record( $record, $out ) if not $options->{ "no_stream" };
4484     }
4485
4486     $result = Maasha::Plot::karyogram( \%data_hash, \%options );
4487
4488     $fh = write_stream( $options->{ "data_out" } );
4489
4490     print $fh $result;
4491
4492     close $fh;
4493 }
4494
4495
4496 sub script_plot_matches
4497 {
4498     # Martin A. Hansen, August 2007.
4499
4500     # Plot matches in 2D generating a dotplot.
4501
4502     my ( $in,        # handle to in stream
4503          $out,       # handle to out stream
4504          $options,   # options hash
4505        ) = @_;
4506
4507     # Returns nothing.
4508
4509     my ( $record, @data, $fh, $result, %data_hash );
4510
4511     $options->{ "direction" } ||= "both";
4512
4513     while ( $record = Maasha::Biopieces::get_record( $in ) ) 
4514     {
4515         if ( defined $record->{ "Q_BEG" } and defined $record->{ "S_BEG" } and $record->{ "Q_END" } and $record->{ "S_END" } ) {
4516             push @data, $record;
4517         }
4518
4519         Maasha::Biopieces::put_record( $record, $out ) if not $options->{ "no_stream" };
4520     }
4521
4522     $options->{ "title" }  ||= "plot_matches";
4523     $options->{ "xlabel" } ||= $data[ 0 ]->{ "Q_ID" };
4524     $options->{ "ylabel" } ||= $data[ 0 ]->{ "S_ID" };
4525
4526     $result = Maasha::Plot::dotplot_matches( \@data, $options, $BP_TMP );
4527
4528     $fh = write_stream( $options->{ "data_out" } );
4529
4530     print $fh "$_\n" foreach @{ $result };
4531
4532     close $fh;
4533 }
4534
4535
4536 sub script_length_vals
4537 {
4538     # Martin A. Hansen, August 2007.
4539
4540     # Determine the length of the value for given keys.
4541
4542     my ( $in,        # handle to in stream
4543          $out,       # handle to out stream
4544          $options,   # options hash
4545        ) = @_;
4546
4547     # Returns nothing.
4548
4549     my ( $record, $key );
4550
4551     while ( $record = Maasha::Biopieces::get_record( $in ) ) 
4552     {
4553         foreach $key ( @{ $options->{ "keys" } } )
4554         {
4555             if ( $record->{ $key } ) {
4556                 $record->{ $key . "_LEN" } = length $record->{ $key };
4557             }
4558         }
4559
4560         Maasha::Biopieces::put_record( $record, $out );
4561     }
4562 }
4563
4564
4565 sub script_sum_vals
4566 {
4567     # Martin A. Hansen, August 2007.
4568
4569     # Calculates the sums for values of given keys.
4570
4571     my ( $in,        # handle to in stream
4572          $out,       # handle to out stream
4573          $options,   # options hash
4574        ) = @_;
4575
4576     # Returns nothing.
4577
4578     my ( $record, $key, %sum_hash, $fh );
4579
4580     while ( $record = Maasha::Biopieces::get_record( $in ) ) 
4581     {
4582         foreach $key ( @{ $options->{ "keys" } } )
4583         {
4584             if ( $record->{ $key } ) {
4585                 $sum_hash{ $key } += $record->{ $key };
4586             }
4587         }
4588
4589         Maasha::Biopieces::put_record( $record, $out ) if not $options->{ "no_stream" };
4590     }
4591
4592     $fh = write_stream( $options->{ "data_out" } );
4593
4594     foreach $key ( @{ $options->{ "keys" } } ) {
4595         Maasha::Biopieces::put_record( { $key . "_SUM" => $sum_hash{ $key } || 0 } , $fh );
4596     }
4597
4598     close $fh;
4599 }
4600
4601
4602 sub script_mean_vals
4603 {
4604     # Martin A. Hansen, August 2007.
4605
4606     # Calculate the mean of values of given keys.
4607
4608     my ( $in,        # handle to in stream
4609          $out,       # handle to out stream
4610          $options,   # options hash
4611        ) = @_;
4612
4613     # Returns nothing.
4614
4615     my ( $record, $key, %sum_hash, %count_hash, $mean, $fh );
4616
4617     while ( $record = Maasha::Biopieces::get_record( $in ) ) 
4618     {
4619         foreach $key ( @{ $options->{ "keys" } } )
4620         {
4621             if ( $record->{ $key } )
4622             {
4623                 $sum_hash{ $key } += $record->{ $key };
4624                 $count_hash{ $key }++;
4625             }
4626         }
4627
4628         Maasha::Biopieces::put_record( $record, $out ) if not $options->{ "no_stream" };
4629     }
4630
4631     $fh = write_stream( $options->{ "data_out" } );
4632
4633     foreach $key ( @{ $options->{ "keys" } } )
4634     {
4635         if ( $count_hash{ $key } ) {
4636             $mean = sprintf( "%.2f", ( $sum_hash{ $key } / $count_hash{ $key } ) );
4637         } else {
4638             $mean = "N/A";
4639         }
4640
4641         Maasha::Biopieces::put_record( { $key . "_MEAN" => $mean } , $fh );
4642     }
4643
4644     close $fh;
4645 }
4646
4647
4648 sub script_median_vals
4649 {
4650     # Martin A. Hansen, March 2008.
4651
4652     # Calculate the median values of given keys.
4653
4654     my ( $in,        # handle to in stream
4655          $out,       # handle to out stream
4656          $options,   # options hash
4657        ) = @_;
4658
4659     # Returns nothing.
4660
4661     my ( $record, $key, %median_hash, $median, $fh );
4662
4663     while ( $record = Maasha::Biopieces::get_record( $in ) ) 
4664     {
4665         foreach $key ( @{ $options->{ "keys" } } ) {
4666             push @{ $median_hash{ $key } }, $record->{ $key } if defined $record->{ $key };
4667         }
4668
4669         Maasha::Biopieces::put_record( $record, $out ) if not $options->{ "no_stream" };
4670     }
4671
4672     $fh = write_stream( $options->{ "data_out" } );
4673
4674     foreach $key ( @{ $options->{ "keys" } } )
4675     {
4676         if ( $median_hash{ $key } ) {
4677             $median = Maasha::Calc::median( $median_hash{ $key } );
4678         } else {
4679             $median = "N/A";
4680         }
4681
4682         Maasha::Biopieces::put_record( { $key . "_MEDIAN" => $median } , $fh );
4683     }
4684
4685     close $fh;
4686 }
4687
4688
4689 sub script_max_vals
4690 {
4691     # Martin A. Hansen, February 2008.
4692
4693     # Determine the maximum values of given keys.
4694
4695     my ( $in,        # handle to in stream
4696          $out,       # handle to out stream
4697          $options,   # options hash
4698        ) = @_;
4699
4700     # Returns nothing.
4701
4702     my ( $record, $key, $fh, %max_hash, $max_record );
4703
4704     while ( $record = Maasha::Biopieces::get_record( $in ) ) 
4705     {
4706         foreach $key ( @{ $options->{ "keys" } } )
4707         {
4708             if ( $record->{ $key } )
4709             {
4710                 $max_hash{ $key } = $record->{ $key } if $record->{ $key } > $max_hash{ $key };
4711             }
4712         }
4713
4714         Maasha::Biopieces::put_record( $record, $out ) if not $options->{ "no_stream" };
4715     }
4716
4717     $fh = write_stream( $options->{ "data_out" } );
4718
4719     foreach $key ( @{ $options->{ "keys" } } )
4720     {
4721         $max_record->{ $key . "_MAX" } = $max_hash{ $key };
4722     }
4723
4724     Maasha::Biopieces::put_record( $max_record, $fh );
4725
4726     close $fh;
4727 }
4728
4729
4730 sub script_min_vals
4731 {
4732     # Martin A. Hansen, February 2008.
4733
4734     # Determine the minimum values of given keys.
4735
4736     my ( $in,        # handle to in stream
4737          $out,       # handle to out stream
4738          $options,   # options hash
4739        ) = @_;
4740
4741     # Returns nothing.
4742
4743     my ( $record, $key, $fh, %min_hash, $min_record );
4744
4745     while ( $record = Maasha::Biopieces::get_record( $in ) ) 
4746     {
4747         foreach $key ( @{ $options->{ "keys" } } )
4748         {
4749             if ( defined $record->{ $key } )
4750             {
4751                 if ( exists $min_hash{ $key } ) {
4752                     $min_hash{ $key } = $record->{ $key } if $record->{ $key } < $min_hash{ $key };
4753                 } else {
4754                     $min_hash{ $key } = $record->{ $key }; 
4755                 }
4756             }
4757         }
4758
4759         Maasha::Biopieces::put_record( $record, $out ) if not $options->{ "no_stream" };
4760     }
4761
4762     $fh = write_stream( $options->{ "data_out" } );
4763
4764     foreach $key ( @{ $options->{ "keys" } } )
4765     {
4766         $min_record->{ $key . "_MIN" } = $min_hash{ $key };
4767     }
4768
4769     Maasha::Biopieces::put_record( $min_record, $fh );
4770
4771     close $fh;
4772 }
4773
4774
4775 sub script_upload_to_ucsc
4776 {
4777     # Martin A. Hansen, August 2007.
4778
4779     # Calculate the mean of values of given keys.
4780
4781     # This routine has developed into the most ugly hack. Do something!
4782
4783     my ( $in,        # handle to in stream
4784          $out,       # handle to out stream
4785          $options,   # options hash
4786        ) = @_;
4787
4788     # Returns nothing.
4789
4790     my ( $record, $file, $wib_file, $wig_file, $wib_dir, $fh_out, $i, $first, $format, $type, $columns, $append, $entry );
4791
4792     $options->{ "short_label" } ||= $options->{ 'table' };
4793     $options->{ "long_label" }  ||= $options->{ 'table' };
4794     $options->{ "group" }       ||= $ENV{ "LOGNAME" };
4795     $options->{ "priority" }    ||= 1;
4796     $options->{ "visibility" }  ||= "pack";
4797     $options->{ "color" }       ||= join( ",", int( rand( 255 ) ), int( rand( 255 ) ), int( rand( 255 ) ) );
4798     $options->{ "chunk_size" }  ||= 10_000_000_000;    # Due to 32-bit UCSC compilation really large tables cannot be loaded in one go.
4799
4800     $file   = "$BP_TMP/ucsc_upload.tmp";
4801     $append = 0;
4802     $first  = 1;
4803     $i      = 0;
4804
4805     $fh_out = Maasha::Common::write_open( $file );
4806
4807     while ( $record = Maasha::Biopieces::get_record( $in ) ) 
4808     {
4809         Maasha::Biopieces::put_record( $record, $out ) if not $options->{ "no_stream" };
4810
4811         if ( $record->{ "REC_TYPE" } eq "fixed_step" )
4812         {
4813             $format = "WIGGLE";
4814
4815             if ( $entry = Maasha::UCSC::Wiggle::biopiece2fixedstep( $record ) ) {
4816                 Maasha::UCSC::Wiggle::fixedstep_entry_put( $entry, $fh_out );
4817             }
4818         }
4819         elsif ( $record->{ "REC_TYPE" } eq "PSL" )
4820         {
4821             $format = "PSL";
4822
4823             Maasha::UCSC::psl_put_header( $fh_out ) if $first;
4824             Maasha::UCSC::psl_put_entry( $record, $fh_out );
4825             
4826             $first = 0;
4827         }
4828         elsif ( $record->{ "REC_TYPE" } eq "BED" and $record->{ "SEC_STRUCT" } )
4829         {
4830             # chrom chromStart  chromEnd    name    score   strand  size    secStr  conf 
4831
4832             $format  = "BED_SS";
4833
4834             print $fh_out join ( "\t",
4835                 $record->{ "CHR" },
4836                 $record->{ "CHR_BEG" },
4837                 $record->{ "CHR_END" } + 1,
4838                 $record->{ "Q_ID" },
4839                 $record->{ "SCORE" },
4840                 $record->{ "STRAND" },
4841                 $record->{ "SIZE" },
4842                 $record->{ "SEC_STRUCT" },
4843                 $record->{ "CONF" },
4844             ), "\n";
4845         }
4846         elsif ( $record->{ "REC_TYPE" } eq "BED" )
4847         {
4848             $format  = "BED";
4849             $columns = $record->{ "BED_COLS" };
4850
4851             if ( $entry = Maasha::UCSC::BED::biopiece2bed( $record, $columns ) ) {
4852                 Maasha::UCSC::BED::bed_entry_put( $entry, $fh_out, $columns, $options->{ 'check' } );
4853             }
4854         }
4855         elsif ( $record->{ "REC_TYPE" } eq "PATSCAN" and $record->{ "CHR" } )
4856         {
4857             $format  = "BED";
4858             $columns = 6;
4859
4860             if ( $entry = Maasha::UCSC::BED::biopiece2bed( $record, $columns ) ) {
4861                 Maasha::UCSC::BED::bed_entry_put( $entry, $fh_out, $columns, $options->{ 'check' } );
4862             }
4863         }
4864         elsif ( $record->{ "REC_TYPE" } eq "BLAST" and $record->{ "S_ID" } =~ /^chr/ )
4865         {
4866             $format  = "BED";
4867             $columns = 6;
4868
4869             $record->{ "SCORE" } = $record->{ "BIT_SCORE" } * 1000;
4870
4871             if ( $entry = Maasha::UCSC::BED::biopiece2bed( $record, $columns ) ) {
4872                 Maasha::UCSC::BED::bed_entry_put( $entry, $fh_out, $columns, $options->{ 'check' } );
4873             }
4874         }
4875         elsif ( $record->{ "REC_TYPE" } eq "VMATCH" and $record->{ "S_ID" } =~ /^chr/i )
4876         {
4877             $format  = "BED";
4878             $columns = 6;
4879
4880             if ( $entry = Maasha::UCSC::BED::biopiece2bed( $record, $columns ) ) {
4881                 Maasha::UCSC::BED::bed_entry_put( $entry, $fh_out, $columns, $options->{ 'check' } );
4882             }
4883         }
4884
4885         if ( $i == $options->{ "chunk_size" } )
4886         {
4887             close $fh_out;
4888
4889             if ( $format eq "BED" ) {
4890                 Maasha::UCSC::bed_upload_to_ucsc( $BP_TMP, $file, $options, $append );
4891             } elsif ( $format eq "PSL" ) {
4892                 Maasha::UCSC::psl_upload_to_ucsc( $file, $options, $append ); 
4893             }
4894
4895             unlink $file;
4896
4897             $first = 1;
4898
4899             $append = 1;
4900
4901             $fh_out = Maasha::Common::write_open( $file );
4902         }
4903
4904         $i++;
4905     }
4906
4907     close $fh_out;
4908
4909     if ( exists $options->{ "database" } and $options->{ "table" } )
4910     {
4911         if ( $format eq "BED" )
4912         {
4913             $type = "bed $columns";
4914
4915             Maasha::UCSC::bed_upload_to_ucsc( $BP_TMP, $file, $options, $append );
4916         }
4917         elsif ( $format eq "BED_SS" )
4918         {
4919             $type = "type bed 6 +";
4920         
4921             Maasha::UCSC::bed_upload_to_ucsc( $BP_TMP, $file, $options, $append );
4922         }
4923         elsif ( $format eq "PSL" )
4924         {
4925             $type = "psl";
4926
4927             Maasha::UCSC::psl_upload_to_ucsc( $file, $options, $append ); 
4928         }
4929         elsif ( $format eq "WIGGLE" )
4930         {
4931             $options->{ "visibility" } = "full";
4932
4933             $wig_file = "$options->{ 'table' }.wig";
4934             $wib_file = "$options->{ 'table' }.wib";
4935
4936             $wib_dir  = "$ENV{ 'HOME' }/ucsc/wib";
4937
4938             Maasha::Common::dir_create_if_not_exists( $wib_dir );
4939
4940             if ( $options->{ 'verbose' } ) {
4941                 `cd $BP_TMP && wigEncode $file $wig_file $wib_file`;
4942             } else {
4943                 `cd $BP_TMP && wigEncode $file $wig_file $wib_file > /dev/null 2>&1`;
4944             }
4945
4946             Maasha::Common::run( "mv", "$BP_TMP/$wib_file $wib_dir" );
4947
4948             unlink $file;
4949
4950             $file = $wig_file;
4951
4952             $type = "wig 0";
4953
4954             Maasha::UCSC::wiggle_upload_to_ucsc( $BP_TMP, $wib_dir, $file, $options );
4955         }
4956
4957         unlink $file;
4958
4959         Maasha::UCSC::ucsc_update_config( $options, $type );
4960     }
4961 }
4962
4963
4964 # >>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>><<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<
4965
4966 1;
4967
4968 __END__
4969