http://www.perlmonks.org?node_id=950722


in reply to Re^3: Perl tk - How to integrate external scripts
in thread Perl tk - How to integrate external scripts

Thank for your answer but unfortunately it still doesn't work. The code with your suggestions is:
# the firs button : $mw-> Button (-text =>'Open', -command =>\&open_file)->place(-x=>240, + -y=>35); #The seocnd button: $mw-> Button (-text =>'Get Statistics',-command =>\&get_statistics)->p +lace(-x=>320, -y=>35); # The sub open : sub open_file {my $open = $mw->getOpenFile( -filetypes => $types_OPEN, -defaultextension => '.sff'); $te->Load( "$open");} if (defined $open and -e $open){ $te->Load( "$open"); $current_file = $open; } # the sub get statistic: sub get_statistics {my $stat = Statistics::Descriptive::Full->new(); my (%distrib); my @bins = qw/18 19 20 21 22 23 24 25 26 27 28/; my $fastaFile = shift; unless (defined $fastaFile){ warn "No file name supplied.\n"; return; } open my $FASTA, '<', $fastaFile or warn "Couldn't open file: $!\n"; my $junkFirstOne = <FASTA>; while (<$FASTA>) {chomp; my ($def,@seqlines) = split /\n/, $_; my $seq = join '', @seqlines; $stat->add_data(length($seq));} %distrib = $stat->frequency_distribution(\@bins); print "Total reads:\t" . $stat->count() . "\n"; print "Total nt:\t" . $stat->sum() . "\n"; print "Mean length:\t" . $stat->mean() . "\n"; print "Median length:\t" . $stat->median() . "\n"; print "Mode length:\t" . $stat->mode() . "\n"; print "Max length:\t" . $stat->max() . "\n"; print "Min length:\t" . $stat->min() . "\n"; print "Length\t# Seqs\n"; foreach (sort {$a <=> $b} keys %distrib) { print "$_\t$distrib{$_}\n"; }}; # The scrolled window: $te = $mw->Scrolled( q/TextUndo/, -scrollbars => 'se', -background => +'white', -font => [-family =>'arial',-size => '12',-weight=> 'bold'], +-wrap => 'none',)->pack(-anchor =>'n',-side=>'right',-fill=>'none');
It say me (after load the $open file in the scrolled window and push the get_statistic button) : "No file name supplied". Where i need to correct the script to make it works ? Thanks

Replies are listed 'Best First'.
Re^5: Perl tk - How to integrate external scripts
by Eliya (Vicar) on Jan 30, 2012 at 12:19 UTC

    As has already been mentioned, your problem is that $open is scoped locally to the sub open_file. This doesn't work, because that way the variable is not accessible outside of the sub (when you click the Get Statistics button).

    Make it a global variable

    my $open; # variable with file scope # The sub open : sub open_file {$open = $mw->getOpenFile( # no my here! ...

    and then simply use the variable inside of get_statistics:

    sub get_statistics { ... my $fastaFile = $open; ...

    Alternatively, use the variable $current_file.  You do have assigned $open to it, but you are not using it anywhere...

    sub get_statistics { ... my $fastaFile = $current_file; ...
      Thank you very much for your answer, i've tried with your advices but it still doesn't work. Can you correct here the script to make it works ? It's clear i'm a newbie.
      my $open; $mw-> Button (-text =>'Open', -command =>\&open_file)->place(-x=>240, +-y=>35); $mw-> Button (-text =>'Get Statistics',-command =>[\&get_statistics, $ +open])->place(-x=>320, -y=>35); sub open_file {$open = $mw->getOpenFile( -filetypes => $types_OPEN, -defaultextension => '.sff'); $te->Load( "$open");} if (defined $open and -e $open){ $te->Load( "$open"); $fastaFile = $open; } sub get_statistics {my $stat = Statistics::Descriptive::Full->new(); my (%distrib); my @bins = qw/18 19 20 21 22 23 24 25 26 27 28/; my $fastaFile = $open; unless (defined $fastaFile){ warn "No file name supplied.\n"; return; } open my $FASTA, '<', $fastaFile or warn "Couldn't open file: $!\n"; my $junkFirstOne = <FASTA>; while (<$FASTA>) {chomp; my ($def,@seqlines) = split /\n/, $_; my $seq = join '', @seqlines; $stat->add_data(length($seq));} %distrib = $stat->frequency_distribution(\@bins); print "Total reads:\t" . $stat->count() . "\n"; print "Total nt:\t" . $stat->sum() . "\n"; print "Mean length:\t" . $stat->mean() . "\n"; print "Median length:\t" . $stat->median() . "\n"; print "Mode length:\t" . $stat->mode() . "\n"; print "Max length:\t" . $stat->max() . "\n"; print "Min length:\t" . $stat->min() . "\n"; print "Length\t# Seqs\n"; foreach (sort {$a <=> $b} keys %distrib) { print "$_\t$distrib{$_}\n"; }};

        Well, in what way does it "not work"?

        Here's a minimal version that works in the sense that when you first click "Open" and select a file, and then click "Get Statistics", the latter routine prints the selected file name to the console.  And if it can print the file name, it should also be able to do something else with it.

        #!/usr/bin/perl -w use strict; use Tk; my $open; # declare global variable, my $mw = MainWindow->new(); $mw-> Button( -text =>'Open', -command => \&open_file )->pac +k(); $mw-> Button( -text =>'Get Statistics', -command => \&get_statistics ) +->pack(); MainLoop(); sub open_file { $open = $mw->getOpenFile(); # set it, } sub get_statistics { my $fastafile = $open; # and use it. print STDERR "selected file: $fastafile\n"; }
Re^5: Perl tk - How to integrate external scripts
by chessgui (Scribe) on Jan 30, 2012 at 10:40 UTC
    By leave it alone I mean that you leave the statistical routine unchanged (as it worked before) in a separate file called 'yourstatisticalroutine.pl' (or whatever name it has now). Execute this script as an external system process by the system command I mentioned then operate on the file to which its output was is redirected. The script you supplied does the opposite: the statistical routine is copy pasted and I see no 'system' command at all. Now your routine tries to get the file name from the argument list of the main program (which is probably empty). If you choose to do it this way the -command bind should look something like this:
    $mw-> Button (-text =>'Get Statistics', -command =>[ \&get_statistics, 'datafile.name' ] )->p +lace(-x=>320, -y=>35);
    In this way your get_statistics routine will be called with the argument 'datafile.name'. You should store your data to be analyzed in this file.
      Thanks but in this way i need to know before what is "datafile.name". I wanted instead that this would be the $open variable called with the get_open( that show all my directories). chosed a file with get open in my dir and on that working the get statistic command: get_open => $open => get_statistics on $open Is there a really way ?
        Make $open a global variable and use it instead of 'datafile.name':
        -command => [ \&get_statistics , $open ]
        Variables are global by default - if you don't understand this just take care never to declare it with 'my' ( don't write "my $open='foo';" just "$open='foo';" ). Set the value for $open with your file selection widget and the bind will call the get_statistics routine with the appropriate value ('value of the $open global variable at the time of the button click') as an argument for you.