9 Adding new instruments

 9.1 Frames
 9.2 Groups
 9.3 Calibration
 9.4 Algorithm Engines
 9.5 Orac-dr
 9.6 Recipes

Adding a new instrument to orac-dr requires a number of steps, the complexity of which will depend on how close the instrument is to an instrument that is already supported by the pipeline.

This section describes the areas that must be modified to support a new instrument. It assumes knowledge of the following Perl concepts: writing object-oriented modules, lexical variables, Perl data structures and eval. Message system interfaces will also require a knowledge of Perl XS.

9.1 Frames

An ORAC::Frame class is responsible for filename conventions and handling of sub-frames. The most common methods that need to be sub-classed are:

new()

The object constructor should be modified to set the default behaviour for rawfixedpart(), (the part of the filename that does not change with UT date of observation number), rawsuffix(), (the file suffix of the raw data file), rawformat() (the input format of the data: FITS, NDF etc.) and format() (the data format required by the algorithm engines).

The base constructor (SUPER::new()) should be invoked to instantiate the object.

calc_orac_headers()

This method is used to translate instrument specific headers to those required by the pipeline. Currently this method must insert the following keywords into the frame header.

ORACUT

This should be the UT date of the observation in YYYYMMDD format.

ORACTIME

This should be the UT date and time of the observation in YYYYMMDD.frac format (i.e. UT date plus fraction of day). This is used by the calibration system to ensure that a guaranteed time stamp can be used for comparison in index files.

file_from_bits()

Given a UT date and an observation number, return the name of the raw data file. This is used by the pipeline to look for the file on disk.

flag_from_bits()

Given a UT date and an observation number, return the name of the flag file. This is used by the pipeline to search for a completion flag on disk associated with the current observation file. Only required if it is intended for the pipeline to be used in conjunction with the -loop flag option.

findgroup()

Translates the header values into a group name and updates the frame.

findrecipe()

Translates the header values into a recipe name and updates the frame.

template()

Modifies the current filename so that it matches the filename that you would have had at an earlier point in the reduction when the supplied template was valid. This is used for jumping to earlier steps in the reduction when performing group operations. Currently this method is generally implemented by replacing the suffix with the supplied value. It could also be implemented by accessing the list of prior file names with the intermediates() method.

inout()

Given a suffix and sub-frame number provide a recommended name for the output file. Does not update the frame object. In general, this can either simply append the suffix or replace the last suffix. The latter is normal practice.

In addition to those listed above, some methods need to know something about the file format and should be modified (most UKIRT and JCMT instruments inherit from the ORAC::Frame::NDF class rather than ORAC::Frame since that class knows how to read from NDF files). The automatic format conversion will have occurred before these methods need to be run (for example if the input format is FITS but the processing format is NDF, then the methods should be written assuming NDF files). These methods are as follows.

readhdr()

Reads the file header and stores the resulting hash reference in the object. Also forces the ORAC headers to be calculated.

erase()

A method to delete the file currently associated with the frame. This is effectively and unlink() but for NDF files the .sdf is appended. The base class implementation can be used in most cases.

file_exists()

Checks to see if the data file exists. There is a special case for NDF format since the .sdf extension is not present in the file name.

stripfname()

Strips the extension from the filename. The base class does nothing to the filename.

Finally, any extra methods not present in the base class but required by an instrument should also be added. These can cover translation of wavelengths to sub-frame filename, for example (used by the SCUBA class).

9.1.1 Frame headers

There are a number of internal headers that ORAC primitives rely on to correctly reduce data. These headers are retrieved from the files and translated to be used by oracdr. These headers can be used in recipes through the ORAC::Frame::uhdr() method and prepending ORAC_ to each header. For example, to refer to the INSTRUMENT header in a primitive, you would use

  
  my $Frm = new ORAC::Frame(’filename.sdf’);
  my $instrument = $Frm->uhdr(’ORAC_INSTRUMENT’);
  

New internal headers can always be created, if necessary, to define some ancillary data needed by a recipe, in an instrument-independent fashion.

The following headers currently exist. Note that not all headers are defined for each instrument or recipe.

AIRMASS_START

Airmass at start of the observation (for a mosaic) or integration (for a raw frame).

AIRMASS_END

Airmass at end of the observation (for a mosaic) or integration (for a raw frame).

CHOP_ANGLE

Position angle of the chop (in degrees).

CHOP_THROW

Throw of the chop with respect to the middle position (in arcseconds).

CONFIGURATION_INDEX

Configuration index. Increments when an instrument’s hardware configuration changes.

DEC_BASE

Declination (ORAC_EQUINOX equinox) at the reference position at zero offset (in degrees). The reference position is normally at the array centre, but may be displaced, for example, to avoid the intersections of abutted detector sub-arrays.

DEC_SCALE

Pixel increment along declination axis (in arcsec).

DEC_TELESCOPE_OFFSET

Telescope declination offset with respect to the base position given by DEC_BASE (in arcseconds).

DETECTOR_BIAS

Detector bias voltage (in volts)

DETECTOR_INDEX

Position number in detector scan.

DETECTOR_READ_TYPE

Observing mode, such as STARE, NDSTARE, CHOP.

EQUINOX

Equinox of object position (in years). It should be 2000.

EXPOSURE_TIME

Integration time per exposure (in seconds).

FILTER

Combined filter name.

GAIN

Detector gain (in electrons/ADU).

GRATING_DISPERSION

Grating dispersion (in microns/pixel).

GRATING_NAME

Grating name.

GRATING_ORDER

Grating order.

GRATING_WAVELENGTH

Grating wavelength (in microns).

INSTRUMENT

Instrument name.

NSCAN_POSITIONS

Number of scan positions in scan.

NUMBER_OF_EXPOSURES

Number of exposures in integration.

NUMBER_OF_OFFSETS

Number of jitter offset positions in an observation.

NUMBER_OF_READS

Number of reads per exposure.

OBJECT

Object name from telescope.

OBSERVATION_MODE

Camera mode, such as imaging or spectroscopy. Used for multi-mode instruments like Michelle.

OBSERVATION_NUMBER

Observation number. Observation numbers normally commence at 1 for each night.

OBSERVATION_TYPE

Observation type. Used to determine whether observation is of the OBJECT, DARK, or ARC, for example.

POLARIMETRY

Whether or not polarimetry observations are being done. True (1) if so, false (0) otherwise.

RA_BASE

Right Ascension (ORAC_EQUINOX equinox) at the reference position at zero offset (in degrees). See DEC_SCALE.

RA_SCALE

Pixel increment along right-ascension axis (in arcsec).

RA_TELESCOPE_OFFSET

Telescope right-ascension offset with respect to the base position given by RA_BASE (in arcseconds).

ROTATION

Angle of declination axis with respect to the second (y) axis, measured counterclockwise (in degrees).

SCAN_INCREMENT

Increment between scan positions (in pixels).

SLIT_ANGLE

Position angle of slit (in degrees)

SLIT_NAME

Name of slit.

SPEED_GAIN

Readout speed. The default is Normal.

STANDARD

Is the target a standard-star observation?

UTDATE

UTC date when the observation was made.

UTEND

End time of integration (for raw data) or the observation (for a mosaic).

UTSTART

Start time of integration (for raw data) or the observation (for a mosaic).

WAVEPLATE_ANGLE

Polarimeter waveplate position angle (in degrees).

X_DIM

Number of detectors in a readout column (in pixels).

Y_DIM

Number of detectors in a readout row (in pixels).

X_LOWER_BOUND

Start column of array readout.

X_UPPER_BOUND

End column of array readout.

Y_LOWER_BOUND

Start row of array readout.

Y_UPPER_BOUND

End row of array readout.

9.2 Groups

An ORAC::Group class is responsible for dealing with groups of frame objects and with an output group data file. The most common methods that need to be sub-classed are given below.

new()

The constructor must be overridden to specify the type fixed part and file suffix of the output group file. The base constructor should be used from the subclass to instantiate the object.

readhdr()/erase()/file_exists()/file_from_bits()

Similar to the frame implementations.

For specialized applications it may also be necessary to implement the coaddswrite()/coaddsread() methods. These will be used by the CGS4/MICHELLE instrument classes to allow coadds to be combined part way through a group without having to re-reduce earlier observations. Not all instruments require support for this.

9.3 Calibration

For a new instrument all that is required is to specify a new set of rules and work out what to do with the ‘best’ calibration that is returned. For UFTI this simply means that the name is returned to the primitive for use. For SCUBA more complex routines are required for sky opacity calibration since the number returned by the index file is sometimes modified for different filters before being returned to the user (the SCUBA calibration system never returns a file name).

For every type of calibration, the calibration object (ORAC::Calib and sub-classes) must provide the following methods:

(1)
A method for returning the current calibration observation that matches the criteria. This method should be an obvious name related directly to the calibration (e.g. ‘dark’, ‘skydip’).
(2)
A method for retrieving the ORAC::Index object associated with the relevant index file. The name of this method should be related to the name of the index file (e.g. skydipindex will access the file index.skydip).
(3)
A method to prevent the pipeline from overwriting the current calibration (used when the user is overriding a certain calibration from the command line). This will be called, for example, darknoupdate(). Orac-dr assumes that the method is of this form since this method will be called whenever a user makes use of the -calib switch,

9.4 Algorithm Engines

Each instrument requires its own implementation of an ORAC::Inst module. This module is responsible for implementing the commands for starting the messaging layer (if required) and launching external tasks ready for use by the pipeline. It may be possible for future releases to launch external tasks on demand the first time an obeyw is issued but this depends on the implementation of the messaging class and still requires that an object for each class is instantiated in the ORAC::Inst module at startup.

Currently, this module is not object-oriented. This may change in the future.

Another factor related to the algorithm engines is the implementation of the messaging interface. The current interface is to the ADAM messaging system used by Starlink. An additional interface is provided to run ADAM tasks via the Unix shell as a proof of concept. Interfaces to Glish and IRAF will be needed to talk to aips++ and Iraf tasks. A Perl-to-DRAMA interface exists and it should be fairly simple to write an orac-dr interface for DRAMA tasks. A shell interface should be used as a last resort and only if valid exit status can be returned to the pipeline.

9.5 Orac-dr

Once the instrument classes have been written, Orac-dr needs to be modified so that it can interpret a new value for ORAC_INSTRUMENT and configure the frame, group and calibration objects correctly.

In the future this configuration may be moved into an external data file so that the core Orac-dr routine need not be modified by people porting the system to a new instrument.

9.6 Recipes

Once orac-dr has been configured to recognise the new instrument, the final step is to write the recipes and associated primitives to deal with the new data and possibly new algorithm engines. At its simplest, for example for an infrared image, this may simply require copying pre-written primitives from an existing instrument11. At its most complex, completely new primitives will have to be written.

11Plans are ongoing to allow multiple search paths for recipes and primitives so that single copies can be used by multiple instruments without having to copy the files to separate locations