views:

700

answers:

2

I am working with VMD (a molecular dynamics visualization package) and I want to open VMD from a Perl script, run a Tcl script, print the output to a log file, then close VMD and return to the Perl script. The ordinary syntax to do this is:

system("vmd -dispdev text -eofexit < program.tcl > LOG");

which breaks down as follows, as best as I understand:

  • system("");: executes Bourne Shell commands contained in quotes
  • vmd: calls VMD
  • -dispdev text: opens VMD in text mode
  • -eofexit: terminates VMD when EOF on STDIN is reached
  • < prog.tcl: sets prog.tcl as STDIN; vmd will terminate when prog.tcl completes
  • > LOG: writes STOUT to file <LOG>

Now this would work perfectly, except that my Tcl script takes arguments. What I'd like to do is something like:

system("vmd -dispdev text -eofexit < program.tcl string1 string2 > LOG");

however, in this case the shell tries to read string1 and string2 as files. With my limited understanding of redirection, I'm not sure exactly what is going in the first line, what exactly goes wrong in the second, or what a good solution would be. Any help would be appreciated.

A: 

Sorry, don't think you can pass arguments to your Tcl script directly when its being executed within another program like vmd. I would suggest passing the parameters via a file as a workaround. Eg. In the Perl script, before calling vmd, write the parameters to a file in Tcl syntax:

open PARAMS, '>myparams.tcl';
print PARAMS "set arg1 $string1; set arg2 $string2";
close PARAMS;

Then at the start of program.tcl, instead of using command line arguments ($argv), have it read the parameter file to pick up the argument values:

source myparams.tcl
Colin Macleod
Perfect, I didn't know `source`. I have the VMD command running inside a loop, and I thought I was going to have to rewrite the entire Tcl script each time; this is much better. Too bad there's no way to pass the arguments directly though.
A: 

What you're doing is sending the contents of the program.tcl file to vmd, not the output of executing the program. If I understand you, you want to connect the Tcl program to vmd with a pipe:

system("program.tcl arg1 arg2 | vmd -... > output.file");

Edit:

So, if vmd reads Tcl code on stdin, you can still pass parameters without using a temp file:

system("( echo 'set arg1 str1; set arg2 str2'; cat program.tcl; ) | vmd ... > output_file");

or

open my $fh, '<', 'program.tcl';
my @tcl = <$fh>;
close $fh;
unshift @tcl, "set arg1 str1\n", "set arg2 str2\n";
open $fh, '|-', 'vmd ... > output.file' or die 'msg...';
print $fh join('', @tcl);
close $fh or die 'msg...';
glenn jackman
In that case, the shell would attempt to execute `program.tcl` as a shell command. If I piped `./program.tcl arg1 arg2` to VMD it would only send the output.