MIRIAD-Style Argument Handling: mirtask.keys

Like other UNIX programs, MIRIAD tasks accept input parameters from the user via command-line arguments. The way in which MIRIAD tasks do this, however, is different than the usual UNIX way.

Each task defines a number of “keywords”. The MIRIAD keyword-handling subsystem can be used to obtain zero or more values of each keyword from the command-line arguments. The values of a given keyword do not necessarily all have to be of the same type. The user specifies the values of these keywords on the command-line with an assignment syntax:

invert vis=3c286.uv map=3c286.mp imsize=824,724 slop=0.5 select='ant(1,3),pol(xx)'

Here, the vis keyword has a single string value (interpretable specifically as a filename), the imsize keyword has two integer values, and the select keyword has two string values. (Note that the keyword-handling routines process parentheses in string-valued keywords and do not consider the keyword to have the values “ant(1”, “3)”, and “pol(xx)”.)

Boolean-valued keywords are called “options” and are implemented by an options pseudo-keyword:

invert options=mfs,double

Here the options mfs and double have True values while all other options are False.

Handling keywords in miriad-python

Tasks in MIRIAD obtain the values of keywords in a procedural way. In miriad-python, keywords are generally specified declaratively and their values are obtained automatically, although there is support for the more general procedural approach.

To parse arguments in a miriad-python task:

  1. Instantiate a KeySpec object.
  2. Specify the keywords your task accepts.
  3. Use the KeySpec.process() method to obtain a data structure populated with the settings for all keywords based on your specification.

Here’s a simple example:

from mirtask import keys

ks = keys.KeySpec ()
ks.keyword ('param', 'd', 0.25)
ks.keyword ('mode', 'a', 'deconvolve')
ks.option ('verbose', 'noop')

opts = ks.process ()
if opts.param < 0:
   die ('"param" must be positive, not %f' % opts.param)
if opts.mode not in ('deconvolve', 'stirfry'):
   die ('Unknown operation mode "%s"' % opts.mode)
if opts.verbose:
   print "Being verbose starting now!"

The methods on KeySpec to define keywords are:

  • keyword() defines a keyword that takes a single, typed value, with a default if the keyword is left unspecified.
  • mkeyword() defines a keyword that takes multiple values of the same type.
  • keymatch() defines a keyword that takes on one or more enumerated values with minimum-match string expansion.
  • option() defines one or more options.
  • custom() defines a keyword that is handled in a custom way by the caller.

The object returned by process() has an attribute for each keyword defined using the above functions.

  • For keywords defined with keyword(), the attribute is equal to the user’s provided value or the default.
  • For keywords defined with mkeyword(), the attribute is a list of the values provided by the user, with the list being empty if the user provided none.
  • For keywords defined with keymatch(), the attribute is a list of the values provided by the user expanded out to their full values if the user abbreviated any. As above, the list may be empty.
  • For options defined with option(), the attribute is either True or False.
  • For keywords defined with custom(), the attribute is whatever value was returned by a user-specified routine.

If the user-specified values do not match the expectations defined by the specification (e.g., a keyword that should be integer-typed is passed the value “abcd”) then a MiriadError is raised in process().

Keyword Types

Keyword types in MIRIAD and miriad-python are identified by single letters. The following types are available:

Character Description
i (The character is the lower-case letter i.) An integer value.
d A floating-point (“double”) value.
a A character string value.
f A filename value. These are essentially treated like character strings, but there are special hooks in the MIRIAD processing code to expand out shell glob patterns into multiple values.
t A time or angle value. These are parsed according to one of several formats, described below. The output is always a floating-point number but its meaning depends on the parse format.

Keyword Formats

Keywords describing a time or angle can be parsed according to one of several formats. You must specify one of these formats when declaring the keyword.

Name Description
dms The argument is an angle measured in degrees, written as “dd:mm:ss.s” or “dd.ddd”. The output is the angle in radians.
hms The argument is an angle/time measured in hours, written as “hh:mm:ss.s” or “hh.hhh”. The output is the angle/time in radians.
dtime The argument is a day fraction, i.e. the portion of a day that has elapsed at that local time. The user can provide it in the format “hh:mm:ss.s” or “hh.hhhh”. The output is the day fraction, a number in the range [0, 1].
atime The argument is an absolute time, specified as either “yyMMMdd.ddd” or “yyMMMdd:hh:mm:ss.s”, or as an epoch, “bYYYY” or “jYYYY”. The output is in Julian days.
time Either an absolute time or a day fraction. The output is either a Julian day value or a day fraction.

Integration with the UVDAT Subsystem

The keyword subsystem can integrate with MIRIAD’s UVDAT subsystem. This integration is necessary because the UVDAT subsystem uses the MIRIAD keyword-handling routines to obtain settings for UV data selection, whether calibration should be applied, and so on.

If your task does not use the UVDAT subsystem, you need take no action.

If your task does use the UVDAT subsystem, you must call KeySpec.uvdat() while defining your keywords. When doing so, you specify processing options that will be passed to the UVDAT subsystem. See the documentation of uvdat() for more information.

mirtask.keys API Reference

This section presents a detailed API reference for the mirtask.keys module.

class mirtask.keys.KeySpec
Synopsis :Specifies the structure of keywords expected by a task.

A KeySpec object is used to specify the keywords accepted by a task and then retrieve their values given a set of command-line arguments. Its usage is outlined in the module documentation.

custom(name, handler)

Declare a custom-handled keyword.

Parameters:
  • name (str) – the name of the keyword
  • handler (callable) – a function that returns the keyword’s value
Return type:

KeySpec

Returns:

self

This function declares a keyword that will be specially handled. Upon keyword processing, the callable handler will be called with one argument, the name of the keyword. The keyword will take on whatever value is returned by handler.

The intended usage is for handler to manually invoke the lowlevel MIRIAD value-fetching routines found in mirtask._miriad_f, but you can obtain a value however you like.

This function returns self for convenience in chaining calls.

keymatch(name, nmax, allowed)

Declare a keyword with enumerated values.

Parameters:
  • name (str) – the name of the keyword
  • nmax (int) – the maximum number of values to process
  • allowed (an iterable of str) – the allowed values of the keyword
Return type:

KeySpec

Returns:

self

This function declares a keyword that can take on one or more enumerated, textual values. The user can abbreviate values to uniqueness when specifying the keyword, and these abbreviations will be expanded upon processing. If nmax is not None, at most nmax values will be returned; if the user specifies more, a warning will be issues about the keyword not being fully consumed.

For example:

ks = keys.KeySpec ()
ks.keymatch ('demo', 3, ['phase', 'amplitude', 'real', 'imaginary'])
opts = ks.process (['demo=am,re,ph,im'])
print opts.demo

yields:

['amplitude', 'real', phase']

and a warning about the keyword not being fully consumed.

This function returns self for convenience in chaining calls.

keyword(name, kind, default, format=None)

Declare a single-valued keyword.

Parameters:
  • name (str) – the name of the keyword
  • kind (a single character) – the kind of the keyword (see Keyword Types)
  • default (any) – the default value of the keyword
  • format (None or str) – an optional format specifying how the keyword should be parsed (see Keyword Formats)
Return type:

KeySpec

Returns:

self

This function declares a single-valued keyword. If the user doesn’t specify the keyword, it will take on the value default (after an attempt to coerce it to the correct type, which might raise an exception).

If the keyword kind is “t”, then the parse format format must be specified.

If the keyword kind is “a” (character string), the MIRIAD subsystems will consider the keyword to have multiple values if commas occur in the string outside of parentheses. These semantics are overridden by miriad-python such that such a string value appears to be a single string. Thus:

ks = keys.KeySpec ()
ks.keyword ('demo', 'a', 'default')
opts = ks.process (['demo=a(1,2),b,c,d'])
print opts.demo

yields 'a(1,2),b,c,d', whereas:

ks = keys.KeySpec ()
ks.mkeyword ('demo', 'a', 'default')
opts = ks.process (['demo=a(1,2),b,c,d'])
print opts.demo

yields ['a(1,2)', 'b', 'c', 'd'].

If the user specifies multiple values for the keyword on the command-line, the keyword will take on the first value specified, and a warning will be issued.

This function returns self for convenience in chaining calls.

mkeyword(name, kind, nmax, format=None)

Declare a multi-valued keyword.

Parameters:
  • name (str) – the name of the keyword
  • kind (a single character) – the kind of the keyword (see Keyword Types)
  • nmax (int or None) – the maximum number of different values that each keyword may take
  • format (None or str) – an optional format specifying how the keyword should be parsed (see Keyword Formats)
Return type:

KeySpec

Returns:

self

This function declares a multi-valued keyword. The value of the keyword is a list of the values provided by the user, or an empty list if the user doesn’t specify any. If nmax is not None, at most nmax values will be returned; if the user specifies more, a warning will be issued about the keyword not being fully consumed.

If the keyword kind is “t”, then the parse format format must be specified.

This function returns self for convenience in chaining calls.

option(*names)

Declare one or more options to be handled.

Parameters:names (tuple of str) – the names of the options to declare
Return type:KeySpec
Returns:self

This function declares one or more of options that will be handled. Each option takes on the value True if it is specified in the “options=” line by the user, and False otherwise. You can call this function multiple times.

This function returns self for convenience in chaining calls.

process(args=None)

Process arguments and return their values.

Parameters:args (iterable of str) – an optional array of argument values
Return type:KeyHolder
Returns:data structure containing keyword values

This function processes the command-line arguments and returns an object containing keyword and option values. If args is None, the command-line arguments contained in sys.argv are used; otherwise, args should be an array of str to be interpreted as the command-line arguments. The initial element of args should be the first command-line parameter, not the name of the executable. I.e., to pass sys.argv to this function manually, the correct code is:

ks.process (sys.argv[1:]) # correct but complicated
ks.process (None) # same semantics

The return value is a KeyHolder object with an attribute set for each declared keyword and option; the value of each attribute depends on the way in which it was declared. (See documentation of the associated functions.)

If KeySpec.uvdat() was called, the MIRIAD UVDAT subsystem is also (re)initialized upon a call to this function using the parameters set in the call to KeySpec.uvdat().

If an argument cannot be converted to its intended type, or the UVDAT subsytem encounters an error initializing, SystemExit will be raised. If there are unrecognized keywords or extra values specified for a given keyword, a warning, not an error, will be issued.

uvdat(flags, addCalOpts=True, viskey='vis')

Declare that this task will make use of the UVDAT subsystem.

Parameters:
  • flags (str) – see below
  • addCalOpts (bool) – whether the standard calibration options should be used
  • viskey (str) – the keyword from which to take input dataset names
Return type:

KeySpec

Returns:

self

Calling this functions indicates that the MIRIAD UVDAT subsystem should be initialized when command-line arguments are processed. If this is done, several keywords and options may be automatically processed by the UVDAT subsystem to set up the subsequent reading of UV data.

The flags argument is a character string that controls optional behavior of the UVDAT subsystem. Each feature in the subsystem is identified with a character; if that character is present in flags, the corresponding feature is enabled. Features that enable the processing of certain keywords are:

Character Feature behavior
d Input data should be filtered via the standard “select” keyword.
l Input spectral data should be processed via the standard “line” keyword.
s Input data should be polarization-processed via the standard “stokes” keyword.
r Input data should be divided by a reference via the standard “ref” keyword.

There are also features that control the format of the data returned by the UVDAT routines:

Character Feature behavior
p Planet rotation and scaling corrections should be applied.
w UVW coordinates should be returned in wavelength units, not nanoseconds. (Beware when writing these data to new UV datasets, as the output routines expect the values to be in nanoseconds.)
1 (The character is the number one.) Average the data down to one channel.
x The input data must be cross-correlations.
a The input data must be autocorrelations.
b The input must be exactly one UV dataset (not multiple).
3 The “preamble” returned while reading data will always have 5 elements and include the w coordinate.

If addCalOpts is True, three options will be enabled: the standard “nocal”, “nopass”, and “nopol”. These control which kinds of on-the-fly calibrations are applied to the data. (These options are implemented by additional flags that may be passed to the UVDAT initialization function, UVDATINP. See its documentation for more information.) If addCalOpts is False, no on-the-fly calibrations will be applied, even if all of the necessary information is present in the input data.

It is possible to specify which keyword is used to obtain the names of the UV datasets that UVDAT will read. By MIRIAD convention this keyword is “vis”. The argument viskey allows you to override this default, however.

Unless your task has unusual needs, it is recommended that you supply at least the flags “dlsr” and leave addCalOpts as True as well as viskey as “vis”.

class mirtask.keys.KeyHolder
Synopsis :Methodless object that holds keyword data

This class is merely an empty subclass of object. Instances of it are created in and returned by mirtask.keys.KeySpec.process() for holding values of keyword arguments to a task.