Elixir Configuration System

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.