Overview
The Elixir system is designed for flexibility. To this end, Elixir
programs should not have hard-wired parameters which are system or
camera dependent. In addition, it is necessary to have a method to
provide programs with the appropriate values for various parameters
for different situations. The Elixir system uses a simple collection
of text-based configuration files with an organized data heirarchy to
achieve these goals.
Elixir Configuration Files
The Elixir configuration files consist of human-readable ASCII text.
The file defines keyword / value pairs in a very simple fashion: the
keyword is the first complete string of characters on each line until
the first whitespace character (space or tab) is
found. The value for that keyword is all following characters until
the first EOL character. Config keyword values may be referenced in
the config file by prepending a dollar sign: $keyword. Keyword
references found in the value of another keyword are deferenced to
define that keyword. If a keyword is present in the config file
multiple times, the last entry is taken by default.
In addition to keyword definition, the only other special function is
file interpolation. A line beginning with the word 'input' will be
replaced by the contents of the file listed after the word 'input'.
All input lines in a given file are first interpolated before the
input lines within those files are interpolated. This point is
important if file names depend on variables: the value of the variable
will be the value available at a given input nesting depth.
Elixir Configuration Functions - C APIs
It is assumed that all C programs which need to access the Elixir
configuration information use the APIs defined in the Elixir C library
'libohana'. This ensures that the rules for variable interpolation
are consistently applied, and that variable overrides will be
performed as expected.
There are three main C APIs to access the Elixir configuration
information:
char *SelectConfigFile (int *argc, char **argv, char *progname);
char *LoadConfigFile (char *);
char *ScanConfig (char *config, char *field, char *mode, int Nentry, ...);
The first function selects the appropriate config file for the given
program. The argument 'progname' should be set to "ptolemy" for
all Elixir programs. In the discussion that follows, the value of
progname is assumed to be 'ptolemy'. This function finds the config
file appropriate to the Elixir system by searching a set of standard
locations. The following list represents the precedence of the
various possible config files. First, if there is a command-line
argument '-c filename', this file is taken as the config file. Next,
if the environment variable PTOLEMY exists, its value is used as the
config file. Next, two local file names are constructed from
'ptolemy': ptolemy.rc and .ptolemyrc. If one of these exists, it is
used for the config file. Finally, the '.ptolemyrc' config file is
searched for in the user's home directory. If ~/.ptolemyrc exists, it
is used for the config file. In practice in the Elixir system, the
local files 'ptolemyrc' and '.ptolemyrc' are not used.
SelectConfigFile also prepares the Elixir config system for two
special types of command-line arguments which allow the user to
override keyword values on an individual basis. The command-line
argument sequence -D keyword value sets the value of the given
keyword. The -C value command-line argument sequence sets the
value of a special keyword 'CONFIG'. An arbitrary number of -D
arguments may be given, while only one -C argument makes sense. These
two command-line arguments override the values of keywords in the
config files. SelectConfigFile strips off all of the Elixir
command-line arguments (-c, -C, -D) from the argv list and resets the
value of argc.
The second function, LoadConfigFile, loads a complete config
file from the file determined by SelectConfigFile, including
interpolation of any input lines. The return value from
LoadConfigFile is an allocated buffer of type char, ending with an EOL
character.
ScanConfig (config, "KEYWORD", "%d", 0, &value);
The third function, ScanConfig, is used to extract data
values from the config file. An example call is shown above. This
function operates like a C scanf statement in that the returned
variable type is defined by a C-style format entry. Unlike 'scanf',
only a single variable is allowed. The Nentry argument should be set
to 0 to retrieve the default value of the keyword (the last value).
However, if Nentry is set to an integer N > 0, the value of the Nth
entry of that keyword is returned to the value. This facility makes
it possible for an Elixir program to access the values of a repeated
keyword. The return value of ScanConfig is (char *) NULL on failure
and a pointer to the entry in the config file on success. In
practice, the return value is rarely used. Note that the
LoadConfigFile and ScanConfig functions may be conveniently used
without the SelectConfigFile function to interact with any text
keyword/value file outside of the Elixir system. This facility is
used by a few elixir programs to load other types of configuration
information not stored within the standard elixir config system (ie,
filtname, photcode).
Elixir Configuration Functions - gconfig
Elixir programs in languages other than C may also need to access the
Elixir configuration system. A simplified access is provided to these
types of program with the 'gconfig' program. This program takes all
of the command-line arguments described above, and uses the same C
APIs to load the same config file that any of the C Elixir programs
would load if called with the same options. If there are no
command-line arguments (except elixir options), then the complete
config file is written to standard output. This can be used to store
a complete, static, interpolated version of the config file. If
command-line arguments exist, they are assumed to be keywords and the
corresponding values are returned.
This function can be used in a shell or Perl program to determine
keyword values as needed. For example, a perl program may determine
the current value of the keyword 'CATDIR' with the following lines:
$catdir = `gconfig CATDIR`; chop ($catdir);
if ($?) { print STDERR "error in config file\n"; }
This should be used with some caution: If such a shell script or perl
script can be called with elixir options (-c, -C, -D), the script
author must take care to trap and pass these options along to elixir
subsystems.
Elixir Configuration Files - Heirarchical Organization
The configuration system described above is very simplistic, but it
can be used to define a complex organization of configuration
information. The system currently used for Elixir at CFHT is only one
possibilty.
The flexibility in the Elixir configuration system is simply provided
by a top-level config file with a series of input lines which load
files defined by a config variable. Each of these input files contain
a specific, related collection of config information; which collection
is loaded depends on the value of the appropriate variable.
A concrete example is given below. The four config files define four
types of data values. The first file consists of system independent
reference data which is used by elixir programs for any type of
analysis. This typically includes the location of the USNO and HST
GSC astrometric references. The next line defines the top-level
organization of a project. This file contains information about data
that should be considered together. For example, at CFHT, the main
analysis of the cfh12k data during the observing runs is organized
into the cfh12k project (or 'config' since that is the variable name
used). As a result, the storage locations for raw data, intermediate
data projects, detrend processing products, final results and result
databases, etc, are all stored in related locations defined by this
file. At the same time, since we are processing data stored on
archived tapes, we also have the 'archive' config, which defines these
same types of locations in places independent of the main analysis.
Also, individual projects on for example taurus have been isolated in
their own config.
The 'mode' entry is used to define an analysis mode for the 'elixir'
program, which organizes the large-scale analysis systems. Different
modes here define completely different types of operations. For
example, one analysis mode is the 'imstats' mode, used to perform a
quick-look analysis of all images (fwhm, sky, bias, etc). Another
'mode' is used to process batches of images to generate master detrend
images.
CONFDIR /data/milo/elixir/config
CONFIG cfh12k
camera cfh12k
mode default
input $CONFDIR/elixir/elixir.refs
input $CONFDIR/elixir/config.$CONFIG
input $CONFDIR/elixir/mode.$mode
The next input file loads camera-specific parameters. This includes,
for example, the abstracted names of keywords needed by certain
program and information about the default astrometric calibration. At
CFHT, the default camera is currently set to cfh12k, but a different
camera can be invoked by setting the variable 'camera' to, for
example, uh8k or suprime.
|