#! /usr/bin/perl -sw #eval 'exec perl -swS $0 ${1+"$@"}' if 0; #/*@@ # @file VizLauncher # @date Thu 15 Mar 2001 # @author Thomas Radke # @desc # Script to launch visualization applications directly # from within a web browser for a given MIME type and input file # @enddesc # @version $Header: /mnt/data2/cvs2svn/cvs-repositories/VizTools/VizLauncher/VizLauncher,v 1.14 2004-11-10 15:35:08 goodale Exp $ #@@*/ ############################################################################### # Global variables # ############################################################################### $tmpdir = '/tmp'; # where to put temporary files $xterm = 'xterm -e'; # how to run a non-X program (eg. gnuplot) $xmessage = 'xmessage -center'; # how to bring up a menu $DX_NETWORK_DIRS = 'DX_NETWORK_DIRS'; # shell environment variable # where to search for OpenDX *.net files $DX_IMPORT_HDF5 = 'DX_IMPORT_HDF5'; # shell environment variable # used by OpenDX ImportHDF5xxx modules # to pass an alternative data source # location (do not change this !) $AMIRA_VFD = 'AMIRA_HXHDF5_HDF5_VFD'; $AMIRA_HOST = 'AMIRA_HXHDF5_HDF5_HOST'; $AMIRA_PORT = 'AMIRA_HXHDF5_HDF5_PORT'; $AMIRA_FILE = 'AMIRA_HXHDF5_HDF5_FILE'; $AMIRA_MODE = 'AMIRA_HXHDF5_HDF5_MODE'; $AMIRA_TIMER = 'AMIRA_HXHDF5_HDF5_TIMER'; # same for Amira ############################################################################### # VizTools database # ############################################################################### # # # Feel free to add your own tools here, one hash entry per program. # # # # # # The hash key serves as a short name for the program (used in menues). # # # # The individual hash values are: # # # # - program: the real name of the program # # If no path is given, the script will look it up # # in your $PATH environment # # # # - mimetype: the MIME type that this program can process # # You can have a list of MIME types in here, with items # # separated by spaces. # # # # - function: the perl function to execute when this program # # is to be called # # These functions can be defined at the bottom of this script. # ############################################################################### $viztools{'xgraph'}{'program'} = 'xgraph'; $viztools{'xgraph'}{'mimetype'} = 'application/x-graph'; $viztools{'xgraph'}{'function'} = LaunchXgraph; $viztools{'gnuplot'}{'program'} = 'gnuplot'; $viztools{'gnuplot'}{'mimetype'} = 'application/gnuplot'; $viztools{'gnuplot'}{'function'} = LaunchGnuplot; $viztools{'h5ls'}{'program'} = 'h5ls'; $viztools{'h5ls'}{'mimetype'} = 'data/x-.*hdf5'; $viztools{'h5ls'}{'function'} = LaunchHDF5Tool; $viztools{'h5dump'}{'program'} = 'h5dump'; $viztools{'h5dump'}{'mimetype'} = 'data/x-.*hdf5'; $viztools{'h5dump'}{'function'} = LaunchHDF5Tool; $viztools{'OpenDX'}{'program'} = 'dx'; $viztools{'OpenDX'}{'mimetype'} = 'data/x-.*hdf5'; $viztools{'OpenDX'}{'function'} = LaunchOpenDX; #$viztools{'Amira'}{'program'} = 'amira2000'; #$viztools{'Amira'}{'mimetype'} = 'data/x-hdf5 data/x-streamed-hdf5'; #$viztools{'Amira'}{'function'} = LaunchAmira; $viztools{'IsoView'}{'program'} = 'IsoView'; $viztools{'IsoView'}{'mimetype'} = 'data/x-streamed-isosurfaces'; $viztools{'IsoView'}{'function'} = LaunchIsoView; $viztools{'Vision'}{'program'} = 'Vision2.0'; $viztools{'Vision'}{'mimetype'} = 'data/x-hdf5 data/x-streamed-hdf5'; $viztools{'Vision'}{'function'} = LaunchLCAVision; ############################################################################### # VizTools filename to mime-type translator # ############################################################################### $file2mime{"streamed-hdf5"} = "data/x-streamed-hdf5"; $file2mime{"streamed-isosurfaces"} = "data/x-streamed-isosurfaces"; ############################################################################### # Perl main # ############################################################################### # remove "if 0" from the command line #$#ARGV -= 2; # parse the command line and set the global variables which are passed # to the functions to finally launch things $file = shift (@ARGV); $mimetype = shift (@ARGV); $url = shift (@ARGV); if(! $mimetype) { if($0 =~ /VizLauncher-(.+)$/) { $mimetype = $file2mime{$1}; $url = ""; } } # either just give the filename (when called from the command line) # or all three options together (when called from the browser) if (! $file || ($mimetype xor $url)) { if ($file) { print STDERR "MIME type is missing\n" if (! $mimetype); print STDERR "URL is missing\n" if (! $url); } print "Usage: VizLauncher \[ \]\n\n"; exit; } if (! $mimetype) { if (! -e $file) {die "File $file not found\n"}; $url = `basename $file`; $mimetype = &ParseMimeType($file); } # get list of directories to search for executables # pathnames beginning with a "." are ignored @bindirs = reverse grep (m!^[^.]!, split (/:/, $ENV{'PATH'}, 999)); $num_choices = 0; $choice_buttons = ''; foreach $key (keys %viztools) { next if ($mimetype !~ $viztools{$key}{'mimetype'}); # next if ($viztools{$key}{'mimetype'} !~ /(^|\s+)$mimetype(\s+|$)/); # check if program is executable if (! -x $viztools{$key}{'program'}) { foreach $dir (@bindirs) { if (-x "$dir/$viztools{$key}{'program'}") { $viztools{$key}{'program'} = "$dir/$viztools{$key}{'program'}"; last; } } if (! -x $viztools{$key}{'program'}) { warn "program \'$viztools{$key}{'program'}\' not found\n"; next; } } # increment counter and add program to buttons if ($num_choices++ > 0) { $choice_buttons .= ","; } $choice_buttons .= "$key"; } die ("No program found to process MIME type \'$mimetype\'") if ! $num_choices; if ($num_choices > 1) { $spaces = ' ' x ((27 - length ($url)) / 2); $program = `$xmessage -buttons quit,$choice_buttons -default quit -print \' Click on a button below to launch a visualization on data from \n$spaces $url\n\n\'`; chomp ($program); if (! $program || $program eq 'quit') { exit (0); } } else { $program = $choice_buttons; } &{$viztools{$program}{'function'}}; ############################################################################### # Perl subroutines # ############################################################################### # # # You can use the following global variables which are set in main(): # # # # - $mimetype the MIME type to process # # - $url the URL of the (remote) data # # - $file the name of the local datafile as downloaded by the browser # # # ############################################################################### sub GetFileInfo { my ($datafile, $comment_char) = @_; my (@dummy); my ($parfile, $dimensions, $xlabel, $ylabel, $zlabel, @timesteps); open (DATA, $datafile) || die ("Couldn't open data file \'$datafile\' !\n"); while () { s/ $//; $parfile = $1 if (! $parfile && /^${comment_char}Parameter file (.+)/); $xlabel = $1 if (! $xlabel && /^${comment_char}x-label (.+)/); $ylabel = $1 if (! $ylabel && /^${comment_char}y-label (.+)/); $zlabel = $1 if (! $zlabel && /^${comment_char}z-label (.+)/); push (@timesteps, $1) if (/^${comment_char}Time = (.+)/); if (! $dimensions && ! /^$/ && ! /^${comment_char}/) { @dummy = split (/\s+/); $dimensions = $#dummy; } } close (DATA); # cut off the grid integer indices from the y- and z-label $ylabel =~ s/(.+\)),(.+)/$1/ if ($ylabel); $zlabel =~ s/(.+\)),(.+)/$1/ if ($zlabel); return ($parfile, $dimensions, $xlabel, $ylabel, $zlabel, @timesteps); } sub ParseMimeType { my($data) = @_; my ($file,$ext); $file = $ENV{"HOME"}."/.mime.types"; open (MIME, "<$file") || die ("Could not find a .mime.types file\n"); $data =~ /\.([^\.]*)$/; $ext = $1; while () { return $1 if (/type=([^\s]*)\s*exts\s*=.*[\"\s,]$ext[\"\s,].*/); } die "Could not find application for extension $ext in .mime.types\n"; } sub LaunchXgraph { my ($xgraph_options); my ($parfile, $dummy, $xlabel, $ylabel) = GetFileInfo ($file, '"'); # set the options to xgraph $xgraph_options = '-bb '; $xgraph_options .= "-t \'$parfile\' " if $parfile; $xgraph_options .= "-x \'$xlabel\' " if $xlabel; $xgraph_options .= "-y \'$ylabel\' " if $ylabel; # don't want the stdout messages from xgraph system ("$viztools{$program}{'program'} $xgraph_options $file > /dev/null"); } sub LaunchGnuplot { my ($i, $supports_pm3d); my ($parfile, $dimensions, $xlabel, $ylabel, $zlabel, @timesteps) = GetFileInfo ($file, '#'); if (! @timesteps) { die ("No timesteps found in datafile \'$file\' !\n"); } if ($dimensions != 1 && $dimensions != 2) { die ("Don't know how to plot data in datafile \'$file\' !\n"); } # create the gnuplot commands file open (GNUPLOT, "> $tmpdir/gnuplot.$$") || die "Couldn't create temporary file for gnuplot commands\n"; # for splots, check whether gnuplot supports the pm3d mode if ($dimensions > 1) { print GNUPLOT "set pm3d"; close (GNUPLOT); system ("$viztools{$program}{'program'} $tmpdir/gnuplot.$$ 2>1 /dev/null"); $supports_pm3d = ! $?; open (GNUPLOT, "> $tmpdir/gnuplot.$$") || die "Couldn't create temporary file for gnuplot commands\n"; } print GNUPLOT "set title \"$parfile\"\n" if ($parfile); print GNUPLOT "set xlabel \"$xlabel\"\n" if ($xlabel); print GNUPLOT "set ylabel \"$ylabel\"\n" if ($ylabel); if ($dimensions == 1) { print GNUPLOT "plot \"$file\" with lines"; } else { print GNUPLOT "set zlabel \"$zlabel\"\n" if ($zlabel); print GNUPLOT "set contour\n"; print GNUPLOT "set hidden3d\n"; print GNUPLOT "set pm3d\n" if ($supports_pm3d); print GNUPLOT "unset colorbox\n" if ($supports_pm3d); for ($i = 0; $i <= $#timesteps; $i++) { print GNUPLOT "splot \"$file\" index $i title \"T = $timesteps[$i]\" " . "with lines\n"; print GNUPLOT "set view ,30+$i\n"; } print GNUPLOT "print \"\\nTo rerun the animation, " . "just type\\n\\n load \\\"$tmpdir/gnuplot.$$\\\"\\n\"\n"; print GNUPLOT "print \"To plot individual timesteps, " . "have a closer look into this file.\\n\"\n"; } close (GNUPLOT); system ("$xterm $viztools{$program}{'program'} $tmpdir/gnuplot.$$ \"-\""); # clean up temporary files unlink ("$tmpdir/gnuplot.$$"); } sub LaunchHDF5Tool { my ($hostname, $dataport, $hdf5file, $result); if ($mimetype eq 'data/x-streamed-hdf5' || $mimetype eq 'data/x-streamed-ahfinder-hdf5') { open (FILE, "< $file") || die "Cannot open input file \'$file\'\n"; while () { if (/Hostname:\s*([\w.-]+)/) { $hostname = $1; } elsif (/Data port:\s*(\d+)/) { $dataport = $1; } } close (FILE); die "Couldn\'t find hostname/port information in file \'$file\'\n" unless $hostname && $dataport; $hdf5file = "$hostname:$dataport"; } else { $hdf5file = $file; } if ($program eq 'h5ls') { $result = `$viztools{$program}{'program'} -v $hdf5file`; } else { $result = `$viztools{$program}{'program'} $hdf5file`; } if ($result) { if (open (OUTPUT, "| $xmessage -buttons close -default close -file -")) { print OUTPUT $result; close (OUTPUT); } } } sub LaunchOpenDX { my ($cmd); my ($hostname, $dataport); my ($dxmodule, $dxprogram, @dxprograms, $dxprogramdirs, $dxdir, $dxfile); if ($mimetype =~ 'data/x-streamed-.*hdf5') { open (FILE, "< $file") || die "Cannot open input file \'$file\'\n"; while () { if (/Hostname:\s*([\w.-]+)/) { $hostname = $1; } elsif (/Data port:\s*(\d+)/) { $dataport = $1; } } close (FILE); die ("Couldn\'t find hostname/port information in file \'$file\'\n") unless $hostname && $dataport; $ENV{$DX_IMPORT_HDF5} = "$hostname:$dataport"; if ($mimetype eq 'data/x-streamed-hdf5') { $dxmodule = 'ImportHDF5'; } else { $dxmodule = 'ImportAHFinderStream'; } } else { $ENV{$DX_IMPORT_HDF5} = "$file"; if ($mimetype eq 'data/x-hdf5') { $dxmodule = 'ImportHDF5'; } else { $dxmodule = 'ImportAHFinderFile'; } } # get the directories to search for DX programs # only absolute pathnames are searched die ("No OpenDX network programs found " . "(environment \$$DX_NETWORK_DIRS not set)\n") if (! $ENV{$DX_NETWORK_DIRS}); # collect all DX programs which contain the corresponding HDF5 import module # pathnames in $DX_NETWORK_DIRS beginning with a "." are ignored %dxprograms = (); foreach $dxdir (grep (m!^[^.]!, split (/:/, $ENV{$DX_NETWORK_DIRS}, 999))) { foreach $dxfile (<$dxdir/*.net>) { if (open (FILE, $dxfile)) { while () { if (/\W$dxmodule\W/ && ! /\/{2}.*\W$dxmodule\W/) { chomp ($dxprogram = `basename $dxfile ".net"`); $dxprograms{$dxprogram} = "$dxdir/$dxprogram"; last; } } close (FILE); } } } die ("No OpenDX network program with module \'$dxmodule\' found " . "in \$$DX_NETWORK_DIRS\n") if (! %dxprograms); if (keys (%dxprograms) > 1) { $spaces = ' ' x ((27 - length ($url)) / 2); $cmd = "$xmessage -buttons quit," . join (',', keys %dxprograms) . " " . "-default quit " . "-print \'\n Choose an OpenDX network to run \n\n\'"; chomp ($dxprogram = `$cmd`); if (! "$dxprogram" || "$dxprogram" eq 'quit') { exit (0); } } else { ($dxprogram) = keys (%dxprograms); } $dxprogram = $dxprograms{$dxprogram}; # don't want the stdout messages from OpenDX system ("$viztools{$program}{'program'} " . "-execute_on_change -noConfirmedQuit -noEditorOnError " . "-noAnchorAtStartup -image " . "-noAnchorAtStartup -noImageRWNetFile -image " . "-program $dxprogram > /dev/null"); } sub LaunchAmira { # print "Starting $viztools{$program}{'program'} ($file)\n"; if ($mimetype eq 'data/x-streamed-hdf5' or $mimetype eq 'data/x-hdf5' ) { $ENV{$AMIRA_VFD} = "stream"; $ENV{$AMIRA_MODE} = "wait"; $ENV{$AMIRA_TIMER} = "10000"; foreach (qx {cat $file}) { if (/hostname:\s*([\w.-]+)/i) { $ENV{$AMIRA_HOST} = $1; } elsif (/data port:\s*(\d+)/i) { $ENV{$AMIRA_PORT} = $1; } elsif (/data file:\s*(\d+)/i) { $ENV{$AMIRA_FILE} = $1; } } } # this is ugly, but I could not think of anything better: # # We need a file to tickle Amira HDF5 file loading # callback. Amira checks if the named file really # exists, so we just create a dummy: my $tmp_file = "/tmp/.dummy.$<.h5"; my $log_file = "/tmp/.dummy.$<.h5"; `cat $file > $tmp_file`; system ("$viztools{$program}{'program'} $tmp_file > $log_file 2>&1"); `rm $tmp_file`; } sub LaunchIsoView { my ($hostname, $controlport, $dataport); open (FILE, "< $file") || die ("Cannot open input file \'$file\'\n"); while () { $hostname = $1 if (/Hostname:\s*([\w.-]+)/); $controlport = $1 if (/Control port:\s*(\d+)/); $dataport = $1 if (/Data port:\s*(\d+)/); } close (FILE); die ("Couldn\'t find hostname/port information in file \'$file\'\n") unless $hostname && $controlport && $dataport; # don't want the stdout messages from IsoView system ("$viztools{$program}{'program'} -h $hostname " . "-cp $controlport -dp $dataport > /dev/null"); } sub LaunchLCAVision { my ($hostname, $dataport, $hdf5file, $result); if ($mimetype eq 'data/x-streamed-hdf5') { open (FILE, "< $file") || die "Cannot open input file \'$file\'\n"; while () { if (/Hostname:\s*([\w.-]+)/) { $hostname = $1; } elsif (/Data port:\s*(\d+)/) { $dataport = $1; } } close (FILE); die "Couldn\'t find hostname/port information in file \'$file\'\n" unless $hostname && $dataport; $hdf5file = "$hostname:$dataport"; } else { $hdf5file = $file; } # no way to get reasonable error messages from LCA Vision # because a lot of debuggin info is written to stderr too system ("$viztools{$program}{'program'} $hdf5file > /dev/null 2>&1"); }