### 11 Compound Frames (CmpFrames)

11.1 Creating a CmpFrame
11.2 The Attributes of a CmpFrame

We now turn to a rather special form of Mapping, the CmpFrame. The Frames we have considered so far have been atomic, in the sense that they represent pre-defined elementary physical domains. A CmpFrame, however, is a compound Frame. In essence, it is a structure for containing other Frames and its purpose is to allow those Frames to work together in various combinations while appearing as a single Object. A CmpFrame’s behaviour is therefore not pre-defined, but is determined by the other Frames it contains (its “component” Frames).

As with compound Mappings, compound Frames can be nested within each other, forming arbitrarily complex Frames.

#### 11.1 Creating a CmpFrame

A very common use for a CmpFrame within astronomy is to represent a “spectral cube”. This is a 3-dimensional Frame in which one of the axes represents position within a spectrum, and the other two axes represent position on the sky (or some other spatial domain such as the focal plane of a telescope). As an example, we create such a CmpFrame in which axes 1 and 2 represent Right Ascension and Declination (ICRS), and axis 3 represents wavelength (these are the default coordinate Systems represented by a SkyFrame and a SpecFrame respectively):

AstSkyFrame *skyframe;
AstSpecFrame *specframe;
AstCmpFrame *cmpframe;
...
skyframe = astSkyFrame( "" );
specframe = astSpecFrame( "" );
cmpframe = astCmpFrame( skyframe, specframe, "" );

If it was desired to make RA and Dec correspond to axes 1 and 3, with axis 2 being the spectral axis, then the axes of the CmpFrame created above would need to be permuted as follows:

int perm[ 3 ];
...
perm[ 0 ] = 0;
perm[ 1 ] = 2;
perm[ 2 ] = 1;
astPermAxes( cmpframe, perm );

#### 11.2 The Attributes of a CmpFrame

A CmpFrame is a Frame and so has all the attributes of a Frame. The default value for the Domain attribute for a CmpFrame is formed by concatenating the Domains of the two component Frames, separated by a minus sign (“-”).21 The (fixed) value for its System attribute is “Compound”.22 A CmpFrame has no further attributes over and above those common to all Frames. However, attributes of the two component Frames can be accessed as if they were attributes of the CmpFrame, as described below.

Frame attributes which are specific to individual axes (such as Label(2), Format(1), etc) simply mirror the corresponding axes of the relevant component Frame. That is, if the “Label(2)” attribute of a CmpFrame is accessed, the CmpFrame will forward the access request to the component Frame which contains axis 2. Thus, default values for axis attributes will be the same as those provided by the component Frames.

An axis index can optionally be appended to the name of Frames attributes which do not normally have such an index (System, Domain, Epoch, Title, etc). If this is done, the access request is forwarded to the component Frame containing the indicated axis. For instance, if a CmpFrame contains a SpecFrame and a SkyFrame in that order, and the axes have not been permuted, then getting the value of attribute “System” will return “Compound” as mentioned above (that is, the System value of the CmpFrame as a whole), whereas getting the value of attribute “System(1)” will return “Spectral”(that is, the System value of the component Frame containing axis 1 — the SpecFrame).

This technique is not limited to attributes common to all Frames. For instance, the SkyFrame class defines an attribute called Equinox which is not held by other classes of Frames. To set a value for the Equinox attribute of the SkyFrame contained within the above CmpFrame, assign the value to the “Equinox(2)” attribute of the CmpFrame. Since the SkyFrame defines both axes 2 and 3 of the CmpFrame, we could equivalently have set a value for “Equinox(3)” since this would also result in the attribute access being forwarded to the SkyFrame.

Finally, if an attribute is not qualified by a axis index, attempts will be made to access it using each of the CmpFrame axes in turn. Using the above example of the spectral cube, if an attempt was made to get the value of attribute “Equinox” (with no axis index), each axis in turn would be used. Since axis 1 is contained within a SpecFrame, the first attempt would fail since the SpecFrame class does not have an Equinox attribute. However, the second attempt would succeed because axis 2 is contained within a SkyFrame which does have an Equinox attribute. Thus the returned attribute value would be that obtained from the SkyFrame containing axis 2. When getting or testing an attribute value, the returned value is determined by the first axis which recognises the attribute. When setting an attribute value, all axes which recognises the attribute have the attribute value set to the given value. Likewise, when clearing an attribute value, all axes which recognises the attribute have the attribute value cleared.

21If both component Frames have blank Domains, then the default Domain for the CmpFrame is the string “CMP”.

22Any attempt to change the System value of a CmpFrame is ignored.

Copyright (C) 2021 East Asian Observatory