Hi Rick,
thanks for this question - I do believe that a command line facility
will greatly enhance the usability of ncl (even more;-))!
I also apologise beforehand for the length of the email - and it's going
to be a bit technical.
To begin with, I believe your option 1 is actually already feasible,
although with a slightly different syntax. With a script named (say)
'my_ncl_prog.ncl', you can do something like
mask=5 smooth=True ncl my_ncl_prog.ncl
and get the 'arguments' from within my_ncl_prog via
begin
auto = getenv("auto")
smooth = getenv("smooth")
...
end
at least as strings. The reason is that the shell sets environment
variables for the program executed (which is ncl) when used in the above
fashion. If a certain parameter is not set, the ncl variable will be set
to a missing indicator (or so I understand the output from the print()
command when I tried it). With this in mind, I wouldn't see a particular
improvement one gets from option 1.
What I really would like to have is the possibility to run an ncl script
like I run any other program from a shell - or say like a ordinary shell
or perl script. That is, if I have a file 'my_ncl_prog' containing the
ncl code, I want to be able to do something like (just an example)
my_ncl_prog --title="My super plot" -p -o myplot.ps input.dat
In this case, the options would mean (plus a few more I want the script
to handle):
-t|--title=... Set the title of the plot to ...
--ps Generate a PostScript file
--pdf Generate a pdf file
-e|--eps Generate an encapsulated PostScript file
-o|--output=... Name of the output file
The last argument (without any preciding switch) apparently is the name
of an input data file. If neither --ps, --pdf or --pdf is given, I would
want it to show the plot in a (X11) window.
This requires to things: a) ncl scripts should be runnable from the
shell, and b) the script gets all the command line arguments given to
it, and c) there's a way to handle them.
a) is relatively straightforward: In every Unix shell I know, a
construct like the following in the first line of the script
#! /whatever/path/holds/ncl
will cause the shell to launch the program /whatever/path/holds/ncl and
pipe the contents of the script into <stdin> of that program. That is
how we run shell or perl or tk/tcl or python scripts, right? I remember
that the book "programming Perl" by L. Wall et al. even gives another
construction that works with perl if the shell is not able to do that.
The construction does work with ncl (I've tried it), apart from the fact
ncl complains about the wrong or unknown character # in the first line
(it still runs the script afterwards). This could easily be remedied by
allowing # to be a comment character in general, or by letting ncl
ignore the first line of any script if it starts with a '#' or '#!'.
I guess that the environment approach to 'arguments', as described
above, would then work immediately, as in
auto=5 smooth=True my_ncl_prog
and with the appropriate getenv() calls within the script itself.
b) is probably a bit harder. Ordinary shell scripts get all command line
arguments in $*; the name of the shell script is in $0, the first
argument in $1, and so on. The user then has to interpret these. Perl
has its @ARGV array to hold the command line arguments (and $0 to hold
the script's name), and again lets the user handle the further
processing.
In ncl, why can't we get an 'argv' array holding all the command line
arguments?
c) Processing the command line arguments really depends on the level of
sophistication you want your program to have. For a very simple example,
assume we have a script that is called with two arguments denoting the
input file and an output file. In a shell or in Perl this is as easy as
(I use shell notation here)
#! /bin/sh
input_file=$1
output_file=$2
...
With ncl, one could do
#! /.../ncl
begin
input_file = argv(0)
output_file = argv(1)
...
end
If you want to use options, I personally favour Perl's Getopt::Long; it
allows both single and double dashed options, recognises abbreviations,
and allows to declare if you want options to have arguments (and their
type). See http://www.perldoc.com/perl5.8.0/lib/Getopt/Long.html for
more. Perl also has a standard interface to command line options (much
like the shell's getopts) called Getopt::Std; here, multiple single
character options can be combined into one (like -abc is the same like
-a -b -c; we all know that from the standard Unix programs). See
http://www.perldoc.com/perl5.8.0/lib/Getopt/Std.html for more.
With the Long version, in Perl I would do something like this (@ at the
beginning in Perl denotes that it is an array or a list, a $ a scalar
variable, and the ';' at the end of each line just belongs to Perl):
@options = ("dryrun|n", "version=i", "number:f");
and then
$result = GetOptions(@options);
The @options list tells Perl that that we allow options --dryrun (which
is equivalent to -n), --version (which requires an integer argument) and
--number (which may have an optional floating type / real argument).
Now, BEFORE the call to GetOptions, all command line arguments (that is,
the switches, their possible arguments, and any positional command line
arguments like the file names in the example above) are contained in the
array @ARGV. AFTER the call, @ARGV only contains positional arguments;
GetOptions has parsed all arguments and extracted the switches and their
possible arguments which are allowed according to the @options array. In
addition, whenever an option has bee set, a variable $opt_<switch> is
available, which holds the value given to that switch. $result tells you
if an error occured (e.g., if an unknown option was specified). Or, if,
for example, the --version switch did not have an integer argument, the
routine will stop with an error.
An example of how to use these variables (in perl; perl and C
afficionados will recognise the '= ? :' syntax)):
@options = ("dryrun|n", "version=i", "number:f");
$result = GetOptions(@options);
if ($result == 0) {
usage();
exit;
}
$dryrun = defined($opt_dryrun) ? $opt_dryrun : 0
$version = $opt_version
$number = defined($opt_number) ? $opt_number : $default_number
and then later on (assuming that the positional arguments are again
input and output file names)
$input_file = $ARGV[0];
$output_file = $ARGV[1]
or so. Of course, the $default_* are some default settings. Oh, in perl,
0 = False.
Now, I've no idea if that can be put into ncl. But if you already have
an array containing all command line arguments, you can probably
relative easily provide an ncl function which is called like (sorry
about all the typos and syntax errors; I just hope you get the idea)
allowed_options = (/ "dryrun|n", "version=i", "number:f" /)
get_options(argv, allowed_options, options)
where options is a logical variable (False if some wrong / not allowed
options were given, True otherwise), and put the values into its
attributes? You could use them like
if (isatt(options@dryrun)) then
...
endif
if (isatt(options@number)) then
number = options@number
else
number = default_number
endif
and so on.
Putting that all together - my initial example would look like (I think)
#! /usr/local/bin/ncl
begin
load "..."
n_args = dimsizes(argv) ; How do I get the number of
; elements of an array in ncl??
allowed = (/ "title=s", "ps", "eps", "pdf", "output=s" /)
get_options(argv, allowed, options)
if (n_args eq 0 or not options) then
usage()
exit
endif
if (isatt(options@title)) then
title = options@title
else
title = ""
endif
if (isatt(options@output)) then
outfile = options@output
else
outfile = "myplot"
endif
if (isatt(options@ps)) then
gsn_open_wks("ps", outfile)
else
if (isatt(options@eps)) then
gsn_open_wks("eps", outfile)
else
if (isatt(options@pdf)) then
gsn_open_wks("pdf", outfile)
else
gsn_open_wks("x11", outfile)
endif
endif
endif
infile = argv(0)
; Do the plot etc.
end
Just my thoughts. Again, sorry for the length of this email.
Chris.
On Thu, 2004-02-19 at 22:56, Rick Grubin wrote:
> Dear NCL users,
>
> The NCL Development Team is considering introducing command line options
> and arguments into NCL. The Team would appreciate user input before any
> decisions are made.
>
> If you would find this functionality useful, please let us know how
> you would use it. Specific examples are welcome.
>
> Below are two possible methods for implementing command line options
> and arguments. Would either, or both, meet your needs? Other ideas
> are welcome.
>
> 1. Command line arguments are user defined, and consist of [name=value] pairs
>
> Example arguments and usage:
> mask=5
> smooth=True
>
> ncl mask=5 smooth=True myScript.ncl
>
> Within an NCL script, the method for retrieval of specified information
> from the command line might look something like:
>
> begin
> mask_val = get_ARGS("mask")
> make_smooth = get_ARGS("smooth")
> ...
> end
>
> A function like "get_ARGS()" is currently a placeholder function, to
> illustrate how accessing command line arguments might occur.
>
>
> 2. Command line options are pre-defined, and may take one of two forms:
> options with single dashes, or options with double dashes.
>
> Single dash:
> -option=value pairs, or simply -option
>
> Example options and usage:
> -f myData.nc
> -v T
> -r
>
> ncl -f myData.nc -v T -r myScript.ncl
>
> Double dash:
> --option=value pairs, or simply --option
>
> Example options and usage:
> --file=myData.nc
> --variable=T
> --version
>
> ncl --file=myData.nc --variable=T --version myScript.ncl
>
> For information provided via command line options, NCL code might look
> something like:
>
> begin
> datafile = get_ARGS("file") ; -f myData.nc or --file=myData.nc
> g = addfile(datafile, "r")
>
> tvar = get_ARGS("variable") ; -v T or --variable=T
> var_to_plot = g->$tvar$
> ...
> end
>
>
> Please note that the NCL script name to execute (if one is provided) is
> always the last argument on the command line, regardless of the method chosen
> for command line arguments/options. As well, the name of the NCL script
> to execute would be available to the user within that script.
>
> Thank you for your input!
>
> The NCL Development Team
>
> _______________________________________________
> ncl-talk mailing list
> ncl-talk@ucar.edu
> http://mailman.ucar.edu/mailman/listinfo/ncl-talk
-- Dr Christian Marquardt Research Scientist Met Office FitzRoy Road Exeter EX1 3PB United Kingdom Tel: +44 (0)1392 88 4820 Fax: +44 (0)1392 885681 E-mail: christian.marquardt AT metoffice.com http://www.metoffice.com_______________________________________________ ncl-talk mailing list ncl-talk@ucar.edu http://mailman.ucar.edu/mailman/listinfo/ncl-talk
This archive was generated by hypermail 2b29 : Mon Feb 23 2004 - 08:34:19 MST