4 Primitives

orac-dr primitives contain information for the manipulation of data in a given state. They are written using object-oriented techniques, manipulating objects associated with the individual data frames as well as groups of observations. The steps that involve actual processing of data (as opposed to housekeeping etc. tasks) are done via a messaging request to an algorithm engine resident in memory.

Because primitives always manipulate objects associated with the pipeline, they are order-ignorant, i.e. no assumptions are made about the file number, file name, or filename convention. These behaviours are all handled by instrument-specific classes, thus allowing the possibility of changing these conventions for an instrument without changing code and of re-use of primitives elsewhere in different recipes for different instruments.

Additionally, it is possible for primitives to contain instructions to include other primitives. An arbritrary limit of 10 levels is imposed by the software to provide protection against recursion. This can easily be extended if required but currently no recipes include primitives at depths greater than 5. The recipe parser recognises primitive inclusion directives by matching the pattern ^\s*_ in non-pod sections, i.e. an underscore as the first blank character on a line. The primitive directive should look exactly as it would if found in a recipe, i.e.:

   _SOME_PRIMITIVE_ ARG=arg  ARG2=$a  ARG3=$b

and not

   _SOME_PRIMITIVE_(ARG=arg, ARG2=$a, ARG3=$b);

as would normally be expected for Perl. One difference from the recipe level3 is that Perl scalar variables can be used to pass values into the primitive rather than having to hard-code a specific value. The current recipe parser does not yet allow complex data structures (arrays, hashes, objects, references) to be passed into primitives. This is because of a desire to enforce simple interfaces to all primitives regardless of location rather than an inability of the parser to be modified to support it. If there is demand for it, this feature could easily be added.

The following variables are available to all primitives:

$Frm

Object of class ORAC::Frame (or a subclass thereof). This object contains information about the current frame being processed by the pipeline. Methods are provided for accessing the current filename and the header information.

$Grp

Object of class ORAC::Group (or a subclass thereof). This object contains information about the current group being processed by the pipeline. In orac-dr a group is thought of as an array of frame objects. Methods are provided for accessing the current filename and current group members. The current frame will be a member of the current group. The usual behaviour is that the group object will contain the frames processed so far that are part of the group, in which case the last member of the group is the current frame. Alternatively, it is possible for the group object to know about all members of the group regardless of which have been processed already, in which case the current frame may not necessarily be the last frame of the group. The latter behaviour is controlled by the -batch switch in Orac-dr and can be used by primitive writers to delay group processing until the current frame is the last member of the group (a group method is provided to determine this). This is only relevant for processing off-line but can significantly reduce run time of certain recipes. Currently, SCUBA is the only instrument that supports the batch option.

$Cal

This provides access to the instrument’s calibration system. This object can return information such as the dark and flats to use for infrared data or the current sky opacity for SCUBA. Extensive use is made of index files and some primitives and recipes must be responsible for filing calibration data with this object so that later recipes can access the correct information. The behaviour of this object is completely instrument specific, in general very few methods are inherited by subclasses.

$Display

An object of class ORAC::Display. Used by primitive writers to send data display commands to the display subsystem. Note that sending a display command does not necessarily result in anything being displayed. The display system itself is not discussed in this document [see the internals document].

%Mon

A hash containing ORAC::Msg objects. These objects are used to send messages to the algorithm engines. The hash keys will describe which algorithm engine is to be contacted. The instrument interface should describe which tasks are available to programmers. Methods are provided to send messages to algorithm engines (always waiting for the reply before continuing) and for retrieving parameter values.

$ORAC_PRIMITIVE

This is the name of the current primitive. Usually used for debug messages. Since this variable has a scope of the current primitive only, if other primitives are included from within a primitive a new variable will be defined in the scope of the included primitive. This will generate warnings if the -w switch is turned on since the current variable will mask the variable defined in the scope of the parent primitive (as desired).

%_PRIMITIVE_NAME_

Hash containing the arguments available to the current primitive. The name of the hash is the same as the name of the primitive (i.e. the hash is not named _PRIMITIVE_NAME_ explicitly).

All primitives (and in fact all of orac-dr) are written with the strict pragma turned on (see perldoc strict for more information) primarily to force a declared scope for all variables. All primitives are evaluated by the Perl interpreter as

  preamble added by the parser
  {
    preamble added by the parser in limited scope
    _PRIMITIVE_
  }

such that each primitive is in a different block to all other primitives4. The only global variables used by primitives should be those supplied by the pipeline, all other variables should be lexical (i.e. using the Perl my declaration) and will therefore be freed at the end of the primitive. Passing complex information between primitives must be achieved by other means and is discussed in §5.3.

All recipes are evaluated in the ORAC::Basic namespace. This fact should not be used by any primitives and it is not guaranteed that this namespace will be used in future releases of orac-dr. It can always be assumed that functions and methods from the following modules will be visible to all primitives:

ORAC::Print

Provides the orac_print, orac_err and orac_warn commands. These routines route messages to the correct output systems (an X-window, the screen, a log file etc) specified by the user. The standard perl functions print and warn should not be used for user messages except during development since the user has no control of where to send them.

ORAC::LogFile

Used to write log files (see §5.1).

ORAC::Constants

Provides access to the standard orac-dr constants. The most important are ORAC__OK and ORAC__ERROR (note that they are Perl constants, not variables).

ORAC::TempFile

Use to generate temporary files (see §5.2).

ORAC::General

Functions that are useful but are not necessarily a standard part of Perl. Examples are max(), min() and log10().

3purely because the recipe level does not contain code

4unless the primitive is nested inside another primitive