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.:
and not
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:
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.
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.
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.
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].
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.
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).
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
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:
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.
Used to write log files (see §5.1).
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).
Use to generate temporary files (see §5.2).
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