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