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

Yes i try to do it, but give me "uninitialized value" errors and doesnt' work, because i'm unable to integrate variables inside. Have you idea on how to do it ?
  • Comment on Re^2: Perl tk - How to integrate external scripts

Replies are listed 'Best First'.
Re^3: Perl tk - How to integrate external scripts
by thundergnat (Deacon) on Jan 27, 2012 at 17:04 UTC

    You are going to need the pass the file name to the get_statistics subroutine when you call it, which means you probably are going to need to save it in a globally accessible variable. You really should also be checking for definedness / existence of the file and success on open too. Also good practice to use lexical file handles and 3 argument opens. (Not critical but they can help avoid subtle bugs.)

    my $current_file;
    $mw-> Button (-text =>'Get Statistics', -command =>\&get_statistics($current_file));
    ## Fixed as pointed out by Eliya++ below.
    $mw-> Button (-text =>'Get Statistics', -command => sub{ get_statistic +s($current_file)}); sub open_file { my $open = $mw->getOpenFile( -filetypes => $types_OPEN, -defaultextension => '.sff' ); if (defined $open and -e $open){ $te->Load( "$open"); $current_file = $open; } sub get_statistics { # blah blah my $fastaFile = shift; unless (defined $fastaFile){ warn "No file name supplied.\n"; return; } open my $FASTA, '<', $fastaFile or warn "Couldn't open file: $!\n"; # blah blah while (<$FASTA>) { # blah blah
    };
       $mw-> Button (-text =>'Get Statistics', -command =>\&get_statistics($current_file));

      The \&get_statistics($current_file) wouldn't work, as it would call the function right away (with an empty $current_file) at the time the button is set up, and set a reference to its return value as the button callback...  In other words, \&func is quite different from \&func(), with the former being a coderef to the function.

      What you more likely want is

      $mw-> Button (-text =>'Get Statistics', -command => sub { get_statisti +cs($current_file) } );

      which would call the function with the current value of $current_file at the time the button is pressed.

      Though, as the variable is global anyway, there's no real need to pass it, so you could also leave it at

      -command => \&get_statistics

      and access $current_file directly in the routine.

      The OP's problem is primarily having made $open (i.e. the name of the selected file) scoped locally to the sub open_file, so it's not available outside of the routine.

Re^3: Perl tk - How to integrate external scripts
by chessgui (Scribe) on Jan 27, 2012 at 17:17 UTC
    Just leave it alone, run it separately as a system command and redirect its output to a file:
    system('perl.exe yourstatisticalroutine.pl inputfile.name >outputfile. +name');
    (Since this is a system command you have to find out the proper format of that on your system. This code is tested on Win32.)
      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

        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; ...
        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.