summaryrefslogtreecommitdiffstats
path: root/ast/dsbspecframe.c
diff options
context:
space:
mode:
authorWilliam Joye <wjoye@cfa.harvard.edu>2018-01-09 19:06:55 (GMT)
committerWilliam Joye <wjoye@cfa.harvard.edu>2018-01-09 19:06:55 (GMT)
commit01e0ebfe59d9028b0246ec4a549bd7528ada94eb (patch)
treea6c5b54db03177a1c8f3e7fb531990dfbc7bae39 /ast/dsbspecframe.c
parentd64cf9c0bd23e752867b149be636d1bbd4501cf4 (diff)
downloadblt-01e0ebfe59d9028b0246ec4a549bd7528ada94eb.zip
blt-01e0ebfe59d9028b0246ec4a549bd7528ada94eb.tar.gz
blt-01e0ebfe59d9028b0246ec4a549bd7528ada94eb.tar.bz2
update ast 8.6.2
Diffstat (limited to 'ast/dsbspecframe.c')
-rw-r--r--ast/dsbspecframe.c3266
1 files changed, 3266 insertions, 0 deletions
diff --git a/ast/dsbspecframe.c b/ast/dsbspecframe.c
new file mode 100644
index 0000000..576f5b9
--- /dev/null
+++ b/ast/dsbspecframe.c
@@ -0,0 +1,3266 @@
+/*
+*class++
+* Name:
+* DSBSpecFrame
+
+* Purpose:
+* Dual sideband spectral coordinate system description.
+
+* Constructor Function:
+c astDSBSpecFrame
+f AST_DSBSPECFRAME
+
+* Description:
+* A DSBSpecFrame is a specialised form of SpecFrame which represents
+* positions in a spectrum obtained using a dual sideband instrument.
+* Such an instrument produces a spectrum in which each point contains
+* contributions from two distinctly different frequencies, one from
+* the "lower side band" (LSB) and one from the "upper side band" (USB).
+* Corresponding LSB and USB frequencies are connected by the fact
+* that they are an equal distance on either side of a fixed central
+* frequency known as the "Local Oscillator" (LO) frequency.
+*
+* When quoting a position within such a spectrum, it is necessary to
+* indicate whether the quoted position is the USB position or the
+* corresponding LSB position. The SideBand attribute provides this
+* indication. Another option that the SideBand attribute provides is
+* to represent a spectral position by its topocentric offset from the
+* LO frequency.
+*
+* In practice, the LO frequency is specified by giving the distance
+* from the LO frequency to some "central" spectral position. Typically
+* this central position is that of some interesting spectral feature.
+* The distance from this central position to the LO frequency is known
+* as the "intermediate frequency" (IF). The value supplied for IF can
+* be a signed value in order to indicate whether the LO frequency is
+* above or below the central position.
+
+* Inheritance:
+* The DSBSpecFrame class inherits from the SpecFrame class.
+
+* Attributes:
+* In addition to those attributes common to all SpecFrames, every
+* DSBSpecFrame also has the following attributes:
+*
+* - AlignSideBand: Should alignment occur between sidebands?
+* - DSBCentre: The central position of interest.
+* - IF: The intermediate frequency used to define the LO frequency.
+* - ImagFreq: The image sideband equivalent of the rest frequency.
+* - SideBand: Indicates which sideband the DSBSpecFrame represents.
+
+* Functions:
+c The DSBSpecFrame class does not define any new functions beyond those
+f The DSBSpecFrame class does not define any new routines beyond those
+* which are applicable to all SpecFrames.
+
+* Copyright:
+* Copyright (C) 1997-2006 Council for the Central Laboratory of the
+* Research Councils
+
+* Licence:
+* This program is free software: you can redistribute it and/or
+* modify it under the terms of the GNU Lesser General Public
+* License as published by the Free Software Foundation, either
+* version 3 of the License, or (at your option) any later
+* version.
+*
+* This program is distributed in the hope that it will be useful,
+* but WITHOUT ANY WARRANTY; without even the implied warranty of
+* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+* GNU Lesser General Public License for more details.
+*
+* You should have received a copy of the GNU Lesser General
+* License along with this program. If not, see
+* <http://www.gnu.org/licenses/>.
+
+* Authors:
+* DSB: David Berry (Starlink)
+
+* History:
+* 5-AUG-2004 (DSB):
+* Original version.
+* 7-OCT-2004 (DSB):
+* Fixed SetAttrib code which assigns values to SideBand. Previously
+* all supplied values were ignored, leaving SideBand unchanged.
+* 2-SEP-2005 (DSB):
+* Allow conversion in any Domain within TopoMap (sometimes
+* SpecFrames have a new Domain set which is not equal to SPECTRUM").
+* 12-SEP-2005 (DSB):
+* Set all attributes required to described the RestFreq value
+* before determining Mapping from RestFreq to ImagFreq in
+* GetImageFreq.
+* 2-DEC-2005 (DSB):
+* Change default Domain from SPECTRUM to DSBSPECTRUM
+* 3-APR-2006 (DSB):
+* Fix memory leak in astLoadDSBSpecFrame.
+* 6-OCT-2006 (DSB):
+* Guard against annulling null pointers in subFrame.
+* 27-OCT-2006 (DSB):
+* Added AlignSideBand attribute.
+* 31-OCT-2006 (DSB):
+* Use AlignSideBand attribute in SubFrame only if we are not
+* currently restoring a FrameSet's integrity.
+* 31-JAN-2007 (DSB):
+* Modified so that a DSBSpecFrame can be used as a template to find a
+* DSBSpecFrame (or SpecFrame) contained within a CmpFrame. This
+* involves changes in Match.
+* 1-MAY-2007 (DSB):
+* The default for AlignSideband has been changed from 1 to 0.
+* 8-MAY-2007 (DSB):
+* Correct initialisation of alignsideband in astInitDSBSpecFrame_.
+* 19-OCT-2007 (DSB):
+* Ignore SideBand alignment if the AlignSideBand attribute is zero
+* in either the target or the template.
+* 16-JAN-2007 (DSB):
+* Modify SubFrame so that DSBSpecFrames are aligned in the
+* observed sideband (LSB or USB) rather than always being aligned
+* in the USB.
+* 12-FEB-2010 (DSB):
+* Report an error if the local oscillator frequency looks silly
+* (specifically, if it less than the absolute intermediate frequency).
+* 29-APR-2011 (DSB):
+* Prevent astFindFrame from matching a subclass template against a
+* superclass target.
+*class--
+
+* Implementation Deficiencies:
+* - The default values for System and StdOfRest inherited from the
+* SpecFrame class are "Wave" and "Heliocentric". These are not
+* usually what is wanted for a DSB instrument. Defaults such as
+* "Freq" and "Topo" may be more appropriate. However, changing the
+* defaults inherited from SpecFrame may cause problems in the
+* astConvert algorithm. The astConvertX function in frame.c includes
+* the following implementation deficiency warning: "One likely
+* problem is with attributes which default in both the source and
+* destination Frames. This means they also default in the common
+* coordinate system. If these default values were to differ when
+* matching different target Frames, however, we would be in trouble,
+* because the common coordinate system would not then be remaining
+* constant. The longer-term solution to this is probably to provide
+* some mechanism to "fix" all attribute values for a Frame, by taking
+* any attributes that are un-set and explicitly setting a firm value
+* (equal to the default) so they cannot then change". So the defaults
+* should probably be left unchanged until this fix is made.
+
+*/
+
+/* Module Macros. */
+/* ============== */
+/* Set the name of the class we are implementing. This indicates to
+ the header files that define class interfaces that they should make
+ "protected" symbols available. */
+#define astCLASS DSBSpecFrame
+
+#define BADSB -9999
+#define FIRST_SB -1
+#define LSB -1
+#define LO 0
+#define USB 1
+#define LAST_SB 1
+
+/* Include files. */
+/* ============== */
+/* Interface definitions. */
+/* ---------------------- */
+
+#include "globals.h" /* Thread-safe global data access */
+#include "error.h" /* Error reporting facilities */
+#include "memory.h" /* Memory management facilities */
+#include "object.h" /* Base Object class */
+#include "channel.h" /* I/O channels */
+#include "specframe.h" /* Spectral frames (parent class) */
+#include "unit.h" /* Unit handling */
+#include "cmpmap.h" /* Compound Mappings */
+#include "unitmap.h" /* Unit Mappings */
+#include "winmap.h" /* Window Mappings */
+#include "dsbspecframe.h" /* Interface definition for this class */
+#include "globals.h" /* Thread-safe global data access */
+
+/* Error code definitions. */
+/* ----------------------- */
+#include "ast_err.h" /* AST error codes */
+
+/* C header files. */
+/* --------------- */
+#include <stdarg.h>
+#include <stddef.h>
+#include <stdio.h>
+#include <string.h>
+#include <ctype.h>
+
+/* Module Variables. */
+/* ================= */
+
+/* Address of this static variable is used as a unique identifier for
+ member of this class. */
+static int class_check;
+
+/* Pointers to parent class methods which are extended by this class. */
+static const char *(* parent_getattrib)( AstObject *, const char *, int * );
+static const char *(* parent_getlabel)( AstFrame *, int, int * );
+static int (* parent_match)( AstFrame *, AstFrame *, int, int **, int **, AstMapping **, AstFrame **, int * );
+static int (* parent_subframe)( AstFrame *, AstFrame *, int, const int *, const int *, AstMapping **, AstFrame **, int * );
+static int (* parent_testattrib)( AstObject *, const char *, int * );
+static void (* parent_clearattrib)( AstObject *, const char *, int * );
+static void (* parent_setattrib)( AstObject *, const char *, int * );
+static void (* parent_overlay)( AstFrame *, const int *, AstFrame *, int * );
+static const char *(* parent_getdomain)( AstFrame *, int * );
+
+/* Define macros for accessing each item of thread specific global data. */
+#ifdef THREAD_SAFE
+
+/* Define how to initialise thread-specific globals. */
+#define GLOBAL_inits \
+ globals->Class_Init = 0; \
+ globals->GetAttrib_Buff[ 0 ] = 0; \
+ globals->GetLabel_Buff[ 0 ] = 0; \
+
+/* Create the function that initialises global data for this module. */
+astMAKE_INITGLOBALS(DSBSpecFrame)
+
+/* Define macros for accessing each item of thread specific global data. */
+#define class_init astGLOBAL(DSBSpecFrame,Class_Init)
+#define class_vtab astGLOBAL(DSBSpecFrame,Class_Vtab)
+#define getattrib_buff astGLOBAL(DSBSpecFrame,GetAttrib_Buff)
+#define getlabel_buff astGLOBAL(DSBSpecFrame,GetLabel_Buff)
+
+
+
+/* If thread safety is not needed, declare and initialise globals at static
+ variables. */
+#else
+
+/* Define the thread-specific globals for this class. */
+
+/* Buffer returned by GetAttrib. */
+static char getattrib_buff[ 101 ];
+
+/* Default Label string buffer */
+static char getlabel_buff[ 101 ];
+
+
+/* Define the class virtual function table and its initialisation flag
+ as static variables. */
+static AstDSBSpecFrameVtab class_vtab; /* Virtual function table */
+static int class_init = 0; /* Virtual function table initialised? */
+
+#endif
+
+/* External Interface Function Prototypes. */
+/* ======================================= */
+/* The following functions have public prototypes only (i.e. no
+ protected prototypes), so we must provide local prototypes for use
+ within this module. */
+AstDSBSpecFrame *astDSBSpecFrameId_( const char *, ... );
+
+/* Prototypes for Private Member Functions. */
+/* ======================================== */
+
+static AstMapping *TopoMap( AstDSBSpecFrame *, int, const char *, int * );
+static AstMapping *ToLOMapping( AstDSBSpecFrame *, const char *, int * )__attribute__((unused));
+static AstMapping *ToLSBMapping( AstDSBSpecFrame *, const char *, int * );
+static AstMapping *ToUSBMapping( AstDSBSpecFrame *, const char *, int * );
+static const char *GetAttrib( AstObject *, const char *, int * );
+static const char *GetLabel( AstFrame *, int, int * );
+static double GetImagFreq( AstDSBSpecFrame *, int * );
+static double GetLO( AstDSBSpecFrame *, const char *, const char *, int * );
+static int Match( AstFrame *, AstFrame *, int, int **, int **, AstMapping **, AstFrame **, int * );
+static int SubFrame( AstFrame *, AstFrame *, int, const int *, const int *, AstMapping **, AstFrame **, int * );
+static int TestAttrib( AstObject *, const char *, int * );
+static void ClearAttrib( AstObject *, const char *, int * );
+static void Dump( AstObject *, AstChannel *, int * );
+static void Overlay( AstFrame *, const int *, AstFrame *, int * );
+static void SetAttrib( AstObject *, const char *, int * );
+static void VerifyAttrs( AstDSBSpecFrame *, const char *, const char *, const char *, int * );
+static const char *GetDomain( AstFrame *, int * );
+
+static double GetIF( AstDSBSpecFrame *, int * );
+static int TestIF( AstDSBSpecFrame *, int * );
+static void ClearIF( AstDSBSpecFrame *, int * );
+static void SetIF( AstDSBSpecFrame *, double, int * );
+
+static double GetDSBCentre( AstDSBSpecFrame *, int * );
+static int TestDSBCentre( AstDSBSpecFrame *, int * );
+static void ClearDSBCentre( AstDSBSpecFrame *, int * );
+static void SetDSBCentre( AstDSBSpecFrame *, double, int * );
+
+static int GetSideBand( AstDSBSpecFrame *, int * );
+static int TestSideBand( AstDSBSpecFrame *, int * );
+static void ClearSideBand( AstDSBSpecFrame *, int * );
+static void SetSideBand( AstDSBSpecFrame *, int, int * );
+
+static int GetAlignSideBand( AstDSBSpecFrame *, int * );
+static int TestAlignSideBand( AstDSBSpecFrame *, int * );
+static void ClearAlignSideBand( AstDSBSpecFrame *, int * );
+static void SetAlignSideBand( AstDSBSpecFrame *, int, int * );
+
+
+/* Member functions. */
+/* ================= */
+static void ClearAttrib( AstObject *this_object, const char *attrib, int *status ) {
+/*
+* Name:
+* ClearAttrib
+
+* Purpose:
+* Clear an attribute value for a DSBSpecFrame.
+
+* Type:
+* Private function.
+
+* Synopsis:
+* #include "dsbspecframe.h"
+* void ClearAttrib( AstObject *this, const char *attrib, int *status )
+
+* Class Membership:
+* DSBSpecFrame member function (over-rides the astClearAttrib protected
+* method inherited from the SpecFrame class).
+
+* Description:
+* This function clears the value of a specified attribute for a
+* DSBSpecFrame, so that the default value will subsequently be used.
+
+* Parameters:
+* this
+* Pointer to the DSBSpecFrame.
+* attrib
+* Pointer to a null-terminated string specifying the attribute
+* name. This should be in lower case with no surrounding white
+* space.
+* status
+* Pointer to the inherited status variable.
+*/
+
+/* Local Variables: */
+ AstDSBSpecFrame *this; /* Pointer to the DSBSpecFrame structure */
+
+/* Check the global error status. */
+ if ( !astOK ) return;
+
+/* Obtain a pointer to the DSBSpecFrame structure. */
+ this = (AstDSBSpecFrame *) this_object;
+
+/* Check the attribute name and clear the appropriate attribute. */
+
+/* DSBCentre. */
+/* ---------- */
+ if ( !strcmp( attrib, "dsbcentre" ) ) {
+ astClearDSBCentre( this );
+
+/* IF */
+/* -- */
+ } else if ( !strcmp( attrib, "if" ) ) {
+ astClearIF( this );
+
+/* SideBand */
+/* -------- */
+ } else if ( !strcmp( attrib, "sideband" ) ) {
+ astClearSideBand( this );
+
+/* AlignSideBand */
+/* ------------- */
+ } else if ( !strcmp( attrib, "alignsideband" ) ) {
+ astClearAlignSideBand( this );
+
+/* Read-only attributes. */
+/* --------------------- */
+/* Test if the attribute name matches any of the read-only attributes
+ of this class. If it does, then report an error. */
+ } else if ( !strcmp( attrib, "imagfreq" ) ) {
+ astError( AST__NOWRT, "astClear: Invalid attempt to clear the \"%s\" "
+ "value for a %s.", status, attrib, astGetClass( this ) );
+ astError( AST__NOWRT, "This is a read-only attribute." , status);
+
+/* If the attribute is not recognised, pass it on to the parent method
+ for further interpretation. */
+ } else {
+ (*parent_clearattrib)( this_object, attrib, status );
+ }
+}
+
+
+static const char *GetAttrib( AstObject *this_object, const char *attrib, int *status ) {
+/*
+* Name:
+* GetAttrib
+
+* Purpose:
+* Get the value of a specified attribute for a DSBSpecFrame.
+
+* Type:
+* Private function.
+
+* Synopsis:
+* #include "dsbspecframe.h"
+* const char *GetAttrib( AstObject *this, const char *attrib, int *status )
+
+* Class Membership:
+* DSBSpecFrame member function (over-rides the protected astGetAttrib
+* method inherited from the SpecFrame class).
+
+* Description:
+* This function returns a pointer to the value of a specified
+* attribute for a DSBSpecFrame, formatted as a character string.
+
+* Parameters:
+* this
+* Pointer to the DSBSpecFrame.
+* attrib
+* Pointer to a null-terminated string containing the name of
+* the attribute whose value is required. This name should be in
+* lower case, with all white space removed.
+* status
+* Pointer to the inherited status variable.
+
+* Returned Value:
+* - Pointer to a null-terminated string containing the attribute
+* value.
+
+* Notes:
+* - The returned string pointer may point at memory allocated
+* within the DSBSpecFrame, or at static memory. The contents of the
+* string may be over-written or the pointer may become invalid
+* following a further invocation of the same function or any
+* modification of the DSBSpecFrame. A copy of the string should
+* therefore be made if necessary.
+* - A NULL pointer will be returned if this function is invoked
+* with the global error status set, or if it should fail for any
+* reason.
+*/
+
+/* Local Variables: */
+ astDECLARE_GLOBALS /* Declare the thread specific global data */
+ AstDSBSpecFrame *this; /* Pointer to the DSBSpecFrame structure */
+ AstMapping *tmap; /* Ptr to Mapping from topofreq to this */
+ const char *result; /* Pointer value to return */
+ double dval; /* Attribute value */
+ double dtemp; /* Attribute value */
+ int ival; /* Attribute value */
+
+/* Initialise. */
+ result = NULL;
+
+/* Check the global error status. */
+ if ( !astOK ) return result;
+
+/* Get a pointer to the structure holding thread-specific global data. */
+ astGET_GLOBALS(this_object);
+
+/* Obtain a pointer to the SpecFrame structure. */
+ this = (AstDSBSpecFrame *) this_object;
+
+/* Compare "attrib" with each recognised attribute name in turn,
+ obtaining the value of the required attribute. If necessary, write
+ the value into "getattrib_buff" as a null-terminated string in an appropriate
+ format. Set "result" to point at the result string. */
+
+/* DSBCentre */
+/* --------- */
+ if ( !strcmp( attrib, "dsbcentre" ) ) {
+
+/* Get the value as topocentric frequency in Hz. */
+ dval = astGetDSBCentre( this );
+
+/* Find the Mapping from topocentric frequency in Hz to the spectral system
+ described by this SpecFrame. */
+ tmap = TopoMap( this, 0, "astGetAttrib", status );
+ if ( astOK ) {
+
+/* Transform the internal value from topocentric frequency into the required
+ system. */
+ astTran1( tmap, 1, &dval, 1, &dtemp );
+ if( dtemp == AST__BAD ) {
+ astError( AST__INTER, "astGetAttrib(%s): Cannot convert DSBCentre "
+ "value from topocentric frequency to the required "
+ "system.", status, astGetClass( this ) );
+ } else {
+
+/* Format it. */
+ (void) sprintf( getattrib_buff, "%.*g", AST__DBL_DIG, dtemp );
+ result = getattrib_buff;
+ }
+ tmap = astAnnul( tmap );
+ }
+
+/* IF */
+/* -- */
+ } else if ( !strcmp( attrib, "if" ) ) {
+ dval = astGetIF( this );
+ if ( astOK ) {
+ (void) sprintf( getattrib_buff, "%.*g", AST__DBL_DIG, dval*1.0E-9 );
+ result = getattrib_buff;
+ }
+
+/* ImagFreq */
+/* -------- */
+ } else if ( !strcmp( attrib, "imagfreq" ) ) {
+ dval = astGetImagFreq( this );
+ if ( astOK ) {
+ (void) sprintf( getattrib_buff, "%.*g", AST__DBL_DIG, dval*1.0E-9 );
+ result = getattrib_buff;
+ }
+
+/* SideBand */
+/* -------- */
+ } else if ( !strcmp( attrib, "sideband" ) ) {
+ ival = astGetSideBand( this );
+ if ( astOK ) {
+ result = ( ival == USB ) ? "USB" : (( ival == LO ) ? "LO" : "LSB" );
+ }
+
+/* AlignSideBand */
+/* ------------- */
+ } else if ( !strcmp( attrib, "alignsideband" ) ) {
+ ival = astGetAlignSideBand( this ) ? 1 : 0;
+ if ( astOK ) {
+ (void) sprintf( getattrib_buff, "%d", ival );
+ result = getattrib_buff;
+ }
+
+/* If the attribute name was not recognised, pass it on to the parent
+ method for further interpretation. */
+ } else {
+ result = (*parent_getattrib)( this_object, attrib, status );
+ }
+
+/* Return the result. */
+ return result;
+
+}
+
+static const char *GetDomain( AstFrame *this_frame, int *status ) {
+/*
+* Name:
+* GetDomain
+
+* Purpose:
+* Obtain a pointer to the Domain attribute string for a DSBSpecFrame.
+
+* Type:
+* Private function.
+
+* Synopsis:
+* #include "dsbspecframe.h"
+* const char *GetDomain( AstFrame *this, int *status )
+
+* Class Membership:
+* DSBSpecFrame member function (over-rides the astGetDomain protected
+* method inherited from the SpecFrame class).
+
+* Description:
+* This function returns a pointer to the Domain attribute string
+* for a DSBSpecFrame.
+
+* Parameters:
+* this
+* Pointer to the DSBSpecFrame.
+* status
+* Pointer to the inherited status variable.
+
+* Returned Value:
+* A pointer to a constant null-terminated string containing the
+* Domain value.
+
+* Notes:
+* - The returned pointer or the string it refers to may become
+* invalid following further invocation of this function or
+* modification of the DSBSpecFrame.
+* - A NULL pointer is returned if this function is invoked with
+* the global error status set or if it should fail for any reason.
+*/
+
+/* Local Variables: */
+ AstDSBSpecFrame *this; /* Pointer to DSBSpecFrame structure */
+ const char *result; /* Pointer value to return */
+
+/* Initialise. */
+ result = NULL;
+
+/* Check the global error status. */
+ if ( !astOK ) return result;
+
+/* Obtain a pointer to the DSBSpecFrame structure. */
+ this = (AstDSBSpecFrame *) this_frame;
+
+/* If a Domain attribute string has been set, invoke the parent method
+ to obtain a pointer to it. */
+ if ( astTestDomain( this ) ) {
+ result = (*parent_getdomain)( this_frame, status );
+
+/* Otherwise, provide a pointer to a suitable default string. */
+ } else {
+ result = "DSBSPECTRUM";
+ }
+
+/* Return the result. */
+ return result;
+}
+
+static double GetImagFreq( AstDSBSpecFrame *this, int *status ) {
+/*
+*+
+* Name:
+* astGetImagFreq
+
+* Purpose:
+* Get the value of the ImagFreq attribute.
+
+* Type:
+* Protected virtual function.
+
+* Synopsis:
+* #include "dsbspecframe.h"
+* double GetImagFreq( AstDSBSpecFrame *this )
+
+* Class Membership:
+* DSBSpecFrame method.
+
+* Description:
+* This function returns the image sideband frequency corresponding to
+* the rest frequency.
+
+* Parameters:
+* this
+* Pointer to the Frame.
+
+* Returned Value:
+* The required frequency, in Hz.
+
+* Notes:
+* - A value of AST__BAD will be returned if this function is invoked
+* with the global error status set, or if it should fail for any
+* reason.
+*-
+*/
+
+/* Local Variables: */
+ AstDSBSpecFrame *rf_frame;/* DSBSpecFrame describing the rest frequency */
+ AstMapping *map; /* Pointer to "Observed to Image" mapping */
+ double result; /* The returned frequency */
+ double rf; /* Rest frequency in observed sideband */
+ int sb; /* SideBand value */
+
+/* Check the global error status. */
+ if ( !astOK ) return AST__BAD;
+
+/* The RestFreq attribute is an observed sideband frequency in the
+ source's standard of rest, measured in Hz. Temporaily set attributes
+ to these values. Create a copy of the supplied DSBSpecFrame and set
+ its attributes to these values. */
+ rf_frame = astCopy( this );
+ astSetStdOfRest( rf_frame, AST__SCSOR );
+ astSetSystem( rf_frame, AST__FREQ );
+ astSetUnit( rf_frame, 0, "Hz" );
+ astSetC( rf_frame, "SideBand", "observed" );
+
+/* Create a Mapping which transforms positions from the observed to the
+ image sideband. */
+ sb = astGetSideBand( rf_frame );
+ if( sb == USB ) {
+ map = ToLSBMapping( rf_frame, "astGetImagFreq", status );
+
+ } else if( sb == LSB ) {
+ map = ToUSBMapping( rf_frame, "astGetImagFreq", status );
+
+ } else {
+ map = NULL;
+ astError( AST__INTER, "astGetImagFreq(%s): Illegal sideband value "
+ "(%d) encountered (internal AST programming error).", status,
+ astGetClass( this ), sb );
+ }
+
+/* Get the rest frequency in Hz, and transform it using the above Mapping. */
+ rf = astGetRestFreq( rf_frame );
+ astTran1( map, 1, &rf, 1, &result );
+
+/* Free resources */
+ map = astAnnul( map );
+ rf_frame = astAnnul( rf_frame );
+
+/* If an error has occurrred, return AST__BAD. */
+ if( !astOK ) result = AST__BAD;
+
+/* Return the result. */
+ return result;
+
+}
+
+static const char *GetLabel( AstFrame *this, int axis, int *status ) {
+/*
+* Name:
+* GetLabel
+
+* Purpose:
+* Access the Label string for a DSBSpecFrame axis.
+
+* Type:
+* Private function.
+
+* Synopsis:
+* #include "dsbspecframe.h"
+* const char *GetLabel( AstFrame *this, int axis, int *status )
+
+* Class Membership:
+* DSBSpecFrame member function (over-rides the astGetLabel method inherited
+* from the SpecFrame class).
+
+* Description:
+* This function returns a pointer to the Label string for a specified axis
+* of a DSBSpecFrame.
+
+* Parameters:
+* this
+* Pointer to the SpecFrame.
+* axis
+* Axis index (zero-based) identifying the axis for which information is
+* required.
+* status
+* Pointer to the inherited status variable.
+
+* Returned Value:
+* Pointer to a constant null-terminated character string containing the
+* requested information.
+
+* Notes:
+* - A NULL pointer will be returned if this function is invoked with the
+* global error status set, or if it should fail for any reason.
+*/
+
+/* Local Variables: */
+ astDECLARE_GLOBALS /* Declare the thread specific global data */
+ const char *result; /* Pointer to label string */
+
+/* Check the global error status. */
+ if ( !astOK ) return NULL;
+
+/* Get a pointer to the structure holding thread-specific global data. */
+ astGET_GLOBALS(this);
+
+/* Initialise. */
+ result = NULL;
+
+/* Validate the axis index. */
+ astValidateAxis( this, axis, 1, "astGetLabel" );
+
+/* Invoke the parent astGetLabel method to obtain a pointer to it. */
+ result = (*parent_getlabel)( this, axis, status );
+
+/* Check if this is a default value. If so, append a string indicating
+ the sideband. */
+ if ( !astTestLabel( this, axis ) ) {
+
+/* If OK, supply a pointer to a suitable default label string. */
+ sprintf( getlabel_buff, "%s (%s)", result, astGetAttrib( this, "sideband" ) );
+ result = getlabel_buff;
+ }
+
+/* Return the result. */
+ return result;
+
+}
+
+static double GetLO( AstDSBSpecFrame *this, const char *check_msg,
+ const char *method, int *status ) {
+/*
+* Name:
+* GetLO
+
+* Purpose:
+* Get the Local Oscillator frequency.
+
+* Type:
+* Private function.
+
+* Synopsis:
+* #include "dsbspecframe.h"
+* double GetLO( AstDSBSpecFrame *this, const char *check_msg,
+* const char *method, int *status )
+
+* Class Membership:
+* DSBSpecFrame method.
+
+* Description:
+* This function returns the local oscillator frequency in topocentric
+* frequency.
+
+* Parameters:
+* this
+* Pointer to the Frame.
+* check_msg
+* If not NULL, an error will be reported if either the DSBCentre
+* or IF attribute has not been set to an explicit value. In this
+* case, the error message will include the supplied text.
+* method
+* The name of the calling method - used in error messages.
+* status
+* Pointer to the inherited status value.
+
+* Returned Value:
+* The local oscillator frequency, in Hz.
+
+* Notes:
+* - An error is reported if the local oscillator frequency looks
+* un-physical (specifically, if it is less than the absolute value of
+* the intermediate frequency).
+* - A value of AST__BAD will be returned if this function is invoked
+* with the global error status set, or if it should fail for any
+* reason.
+*-
+*/
+
+/* Local Variables: */
+ double f_if; /* Intermediate frequency (topo,HZ) */
+ double result; /* The returned frequency */
+
+/* Check the global error status. */
+ if ( !astOK ) return AST__BAD;
+
+/* If required, check that explicit values have been assigned to the required
+ attributes (i.e. report an error if a default value would be used for
+ either attribute). */
+ if( check_msg ) VerifyAttrs( this, check_msg, "IF DSBCentre", method,
+ status );
+
+/* The local oscillator is the sum of the intermediate frequency and the
+ observation centre frequency. */
+ f_if = astGetIF( this );
+ result = astGetDSBCentre( this ) + f_if;
+
+/* Check the local oscillator frequency is no smaller than the absolute
+ intermediate frequency. */
+ if( result < fabs( f_if ) && astOK ) {
+ astError( AST__ATTIN, "%s(%s): The local oscillator frequency (%g Hz) "
+ "is too low (less than the intermediate frequency: %g Hz).",
+ status, method, astGetClass( this ), result, fabs( f_if ) );
+ astError( AST__ATTIN, " This could be caused by a bad value for"
+ " either the IF attribute (currently %g Hz) or the DSBCentre "
+ "attribute (currently %g Hz).", status, f_if,
+ astGetDSBCentre( this ) );
+ }
+
+/* If an error has occurrred, return AST__BAD. */
+ if( !astOK ) result = AST__BAD;
+
+/* Return the result. */
+ return result;
+}
+
+void astInitDSBSpecFrameVtab_( AstDSBSpecFrameVtab *vtab, const char *name, int *status ) {
+/*
+*+
+* Name:
+* astInitDSBSpecFrameVtab
+
+* Purpose:
+* Initialise a virtual function table for a DSBSpecFrame.
+
+* Type:
+* Protected function.
+
+* Synopsis:
+* #include "dsbspecframe.h"
+* void astInitDSBSpecFrameVtab( AstDSBSpecFrameVtab *vtab, const char *name )
+
+* Class Membership:
+* DSBSpecFrame vtab initialiser.
+
+* Description:
+* This function initialises the component of a virtual function
+* table which is used by the DSBSpecFrame class.
+
+* Parameters:
+* vtab
+* Pointer to the virtual function table. The components used by
+* all ancestral classes will be initialised if they have not already
+* been initialised.
+* name
+* Pointer to a constant null-terminated character string which contains
+* the name of the class to which the virtual function table belongs (it
+* is this pointer value that will subsequently be returned by the Object
+* astClass function).
+*-
+*/
+
+/* Local Variables: */
+ astDECLARE_GLOBALS /* Pointer to thread-specific global data */
+ AstObjectVtab *object; /* Pointer to Object component of Vtab */
+ AstFrameVtab *frame; /* Pointer to Frame component of Vtab */
+
+/* Check the local error status. */
+ if ( !astOK ) return;
+
+/* Get a pointer to the thread specific global data structure. */
+ astGET_GLOBALS(NULL);
+
+/* Initialize the component of the virtual function table used by the
+ parent class. */
+ astInitSpecFrameVtab( (AstSpecFrameVtab *) vtab, name );
+
+/* Store a unique "magic" value in the virtual function table. This
+ will be used (by astIsADSBSpecFrame) to determine if an object belongs
+ to this class. We can conveniently use the address of the (static)
+ class_check variable to generate this unique value. */
+ vtab->id.check = &class_check;
+ vtab->id.parent = &(((AstSpecFrameVtab *) vtab)->id);
+
+/* Initialise member function pointers. */
+/* ------------------------------------ */
+/* Store pointers to the member functions (implemented here) that provide
+ virtual methods for this class. */
+ vtab->ClearDSBCentre = ClearDSBCentre;
+ vtab->TestDSBCentre = TestDSBCentre;
+ vtab->GetDSBCentre = GetDSBCentre;
+ vtab->SetDSBCentre = SetDSBCentre;
+
+ vtab->ClearIF = ClearIF;
+ vtab->TestIF = TestIF;
+ vtab->GetIF = GetIF;
+ vtab->SetIF = SetIF;
+
+ vtab->ClearSideBand = ClearSideBand;
+ vtab->TestSideBand = TestSideBand;
+ vtab->GetSideBand = GetSideBand;
+ vtab->SetSideBand = SetSideBand;
+
+ vtab->ClearAlignSideBand = ClearAlignSideBand;
+ vtab->TestAlignSideBand = TestAlignSideBand;
+ vtab->GetAlignSideBand = GetAlignSideBand;
+ vtab->SetAlignSideBand = SetAlignSideBand;
+
+ vtab->GetImagFreq = GetImagFreq;
+
+/* Save the inherited pointers to methods that will be extended, and
+ replace them with pointers to the new member functions. */
+ object = (AstObjectVtab *) vtab;
+ frame = (AstFrameVtab *) vtab;
+
+ parent_clearattrib = object->ClearAttrib;
+ object->ClearAttrib = ClearAttrib;
+
+ parent_getattrib = object->GetAttrib;
+ object->GetAttrib = GetAttrib;
+
+ parent_setattrib = object->SetAttrib;
+ object->SetAttrib = SetAttrib;
+
+ parent_testattrib = object->TestAttrib;
+ object->TestAttrib = TestAttrib;
+
+ parent_getdomain = frame->GetDomain;
+ frame->GetDomain = GetDomain;
+
+ parent_overlay = frame->Overlay;
+ frame->Overlay = Overlay;
+
+ parent_match = frame->Match;
+ frame->Match = Match;
+
+ parent_subframe = frame->SubFrame;
+ frame->SubFrame = SubFrame;
+
+ parent_getlabel = frame->GetLabel;
+ frame->GetLabel = GetLabel;
+
+/* Declare the class delete function.*/
+ astSetDump( vtab, Dump, "DSBSpecFrame", "Dual sideband spectral axis" );
+
+/* If we have just initialised the vtab for the current class, indicate
+ that the vtab is now initialised, and store a pointer to the class
+ identifier in the base "object" level of the vtab. */
+ if( vtab == &class_vtab ) {
+ class_init = 1;
+ astSetVtabClassIdentifier( vtab, &(vtab->id) );
+ }
+}
+
+static int Match( AstFrame *template_frame, AstFrame *target, int matchsub,
+ int **template_axes, int **target_axes, AstMapping **map,
+ AstFrame **result, int *status ) {
+/*
+* Name:
+* Match
+
+* Purpose:
+* Determine if conversion is possible between two coordinate systems.
+
+* Type:
+* Private function.
+
+* Synopsis:
+* #include "dsbspecframe.h"
+* int Match( AstFrame *template, AstFrame *target, int matchsub,
+* int **template_axes, int **target_axes,
+* AstMapping **map, AstFrame **result, int *status )
+
+* Class Membership:
+* DSBSpecFrame member function (over-rides the protected astMatch method
+* inherited from the SpecFrame class).
+
+* Description:
+* This function matches a "template" DSBSpecFrame to a "target" Frame and
+* determines whether it is possible to convert coordinates between them.
+* If it is, a mapping that performs the transformation is returned along
+* with a new Frame that describes the coordinate system that results when
+* this mapping is applied to the "target" coordinate system. In addition,
+* information is returned to allow the axes in this "result" Frame to be
+* associated with the corresponding axes in the "target" and "template"
+* Frames from which they are derived.
+
+* Parameters:
+* template
+* Pointer to the template DSBSpecFrame. This describes the coordinate
+* system (or set of possible coordinate systems) into which we wish to
+* convert our coordinates.
+* target
+* Pointer to the target Frame. This describes the coordinate system in
+* which we already have coordinates.
+* matchsub
+* If zero then a match only occurs if the template is of the same
+* class as the target, or of a more specialised class. If non-zero
+* then a match can occur even if this is not the case.
+* template_axes
+* Address of a location where a pointer to int will be returned if the
+* requested coordinate conversion is possible. This pointer will point
+* at a dynamically allocated array of integers with one element for each
+* axis of the "result" Frame (see below). It must be freed by the caller
+* (using astFree) when no longer required.
+*
+* For each axis in the result Frame, the corresponding element of this
+* array will return the index of the template DSBSpecFrame axis from
+* which it is derived. If it is not derived from any template
+* DSBSpecFrame axis, a value of -1 will be returned instead.
+* target_axes
+* Address of a location where a pointer to int will be returned if the
+* requested coordinate conversion is possible. This pointer will point
+* at a dynamically allocated array of integers with one element for each
+* axis of the "result" Frame (see below). It must be freed by the caller
+* (using astFree) when no longer required.
+*
+* For each axis in the result Frame, the corresponding element of this
+* array will return the index of the target Frame axis from which it
+* is derived. If it is not derived from any target Frame axis, a value
+* of -1 will be returned instead.
+* map
+* Address of a location where a pointer to a new Mapping will be
+* returned if the requested coordinate conversion is possible. If
+* returned, the forward transformation of this Mapping may be used to
+* convert coordinates between the "target" Frame and the "result"
+* Frame (see below) and the inverse transformation will convert in the
+* opposite direction.
+* result
+* Address of a location where a pointer to a new Frame will be returned
+* if the requested coordinate conversion is possible. If returned, this
+* Frame describes the coordinate system that results from applying the
+* returned Mapping (above) to the "target" coordinate system. In
+* general, this Frame will combine attributes from (and will therefore
+* be more specific than) both the target and the template Frames. In
+* particular, when the template allows the possibility of transformaing
+* to any one of a set of alternative coordinate systems, the "result"
+* Frame will indicate which of the alternatives was used.
+* status
+* Pointer to the inherited status variable.
+
+* Returned Value:
+* A non-zero value is returned if the requested coordinate conversion is
+* possible. Otherwise zero is returned (this will not in itself result in
+* an error condition).
+
+* Notes:
+* - A value of zero will be returned if this function is invoked with the
+* global error status set, or if it should fail for any reason.
+
+* Implementation Notes:
+* This implementation addresses the matching of a DSBSpecFrame class
+* object to any other class of Frame. A DSBSpecFrame will match any class
+* of DSBSpecFrame (i.e. possibly from a derived class) but will not match
+* a less specialised class of Frame (except for a SpecFrame).
+*/
+
+/* Local Variables: */
+ AstDSBSpecFrame *template; /* Pointer to template DSBSpecFrame structure */
+ AstFrame *frame0; /* Pointer to Frame underlying axis 0 */
+ int iaxis0; /* Axis index underlying axis 0 */
+ int match; /* Coordinate conversion possible? */
+
+/* Initialise the returned values. */
+ *template_axes = NULL;
+ *target_axes = NULL;
+ *map = NULL;
+ *result = NULL;
+ match = 0;
+
+/* Check the global error status. */
+ if ( !astOK ) return match;
+
+/* Obtain a pointer to the template DSBSpecFrame structure. */
+ template = (AstDSBSpecFrame *) template_frame;
+
+/* The first criterion for a match is that the template matches as a
+ SpecFrame class object. This ensures that the number of axes (1) and
+ domain, class, etc. of the target Frame are suitable. Invoke the parent
+ "astMatch" method to verify this. */
+ match = (*parent_match)( template_frame, target, matchsub,
+ template_axes, target_axes, map, result, status );
+
+/* If a match was found, the target Frame must be (or contain) a SpecFrame,
+ but this target SpecFrame may be a simple SpecFrame rather than a
+ DSBSpecFrame. We use the returned objects directly if the target
+ SpecFrame is not a DSBSpecFrame. So if a DSBSpecFrame and a base
+ SpecFrame are aligned, this will result in the DSBSpecFrame behaving as
+ a normal SpecFrame. */
+ if ( astOK && match ) {
+
+/* Get the primary Frame associated with the matching target axis. */
+ astPrimaryFrame( target, (*target_axes)[ 0 ], &frame0, &iaxis0 );
+
+/* Skip this next section, thus retaining the values returned by the
+ parent Match method above, if the target axis is not a DSBSpecFrame. */
+ if( astIsADSBSpecFrame( frame0 ) ) {
+
+/* Annul the returned objects, which are not needed, but keep the axis
+ association arrays which already hold the correct values. */
+ *map = astAnnul( *map );
+ *result = astAnnul( *result );
+
+/* Use the target's "astSubFrame" method to create a new Frame (the
+ result Frame) with a copy of of the target axis. This process also
+ overlays the template attributes on to the target Frame and returns a
+ Mapping between the target and result Frames which effects the required
+ coordinate conversion. */
+ match = astSubFrame( target, template, 1, *target_axes, *template_axes,
+ map, result );
+ }
+
+/* Free resources. */
+ frame0 = astAnnul( frame0 );
+
+ }
+
+/* If an error occurred, or conversion to the result Frame's coordinate
+ system was not possible, then free all memory, annul the returned
+ objects, and reset the returned value. */
+ if ( !astOK || !match ) {
+ if( *template_axes ) *template_axes = astFree( *template_axes );
+ if( *target_axes ) *target_axes = astFree( *target_axes );
+ if( *map ) *map = astAnnul( *map );
+ if( *result ) *result = astAnnul( *result );
+ match = 0;
+ }
+
+/* Return the result. */
+ return match;
+}
+
+static void Overlay( AstFrame *template, const int *template_axes,
+ AstFrame *result, int *status ) {
+/*
+* Name:
+* Overlay
+
+* Purpose:
+* Overlay the attributes of a template DSBSpecFrame on to another Frame.
+
+* Type:
+* Private function.
+
+* Synopsis:
+* #include "specframe.h"
+* void Overlay( AstFrame *template, const int *template_axes,
+* AstFrame *result, int *status )
+
+* Class Membership:
+* DSBSpecFrame member function (over-rides the protected astOverlay method
+* inherited from the SpecFrame class).
+
+* Description:
+* This function overlays attributes of a DSBSpecFrame (the "template") on to
+* another Frame, so as to over-ride selected attributes of that second
+* Frame. Normally only those attributes which have been specifically set
+* in the template will be transferred. This implements a form of
+* defaulting, in which a Frame acquires attributes from the template, but
+* retains its original attributes (as the default) if new values have not
+* previously been explicitly set in the template.
+*
+* Note that if the result Frame is a DSBSpecFrame and a change of spectral
+* coordinate system occurs as a result of overlaying its System
+* attribute, then some of its original attribute values may no
+* longer be appropriate (e.g. the Title, or attributes describing
+* its axes). In this case, these will be cleared before overlaying
+* any new values.
+
+* Parameters:
+* template
+* Pointer to the template DSBSpecFrame, for which values should have been
+* explicitly set for any attribute which is to be transferred.
+* template_axes
+* Pointer to an array of int, with one element for each axis of the
+* "result" Frame (see below). For each axis in the result frame, the
+* corresponding element of this array should contain the (zero-based)
+* index of the template axis to which it corresponds. This array is used
+* to establish from which template axis any axis-dependent attributes
+* should be obtained.
+*
+* If any axis in the result Frame is not associated with a template
+* axis, the corresponding element of this array should be set to -1.
+*
+* If a NULL pointer is supplied, the template and result axis
+* indices are assumed to be identical.
+* result
+* Pointer to the Frame which is to receive the new attribute values.
+* status
+* Pointer to the inherited status variable.
+
+* Returned Value:
+* void
+
+* Notes:
+* - In general, if the result Frame is not from the same class as the
+* template DSBSpecFrame, or from a class derived from it, then attributes may
+* exist in the template DSBSpecFrame which do not exist in the result Frame.
+* In this case, these attributes will not be transferred.
+*/
+
+/* Check the global error status. */
+ if ( !astOK ) return;
+
+/* Invoke the parent class astOverlay method to transfer attributes inherited
+ from the parent class. */
+ (*parent_overlay)( template, template_axes, result, status );
+
+/* Check if the result Frame is a DSBSpecFrame or from a class derived from
+ DSBSpecFrame. If not, we cannot transfer DSBSpecFrame attributes to it as it is
+ insufficiently specialised. In this case simply omit these attributes. */
+ if( astIsADSBSpecFrame( result ) && astOK ) {
+
+/* Define macros that test whether an attribute is set in the template and,
+ if so, transfers its value to the result. */
+#define OVERLAY(attribute) \
+ if ( astTest##attribute( template ) ) { \
+ astSet##attribute( result, astGet##attribute( template ) ); \
+ }
+
+/* Use the macro to transfer each DSBSpecFrame attribute in turn. */
+ OVERLAY(DSBCentre)
+ OVERLAY(IF)
+ OVERLAY(SideBand)
+ OVERLAY(AlignSideBand)
+ }
+
+/* Undefine macros local to this function. */
+#undef OVERLAY
+}
+
+static void SetAttrib( AstObject *this_object, const char *setting, int *status ) {
+/*
+* Name:
+* SetAttrib
+
+* Purpose:
+* Set an attribute value for a DSBSpecFrame.
+
+* Type:
+* Private function.
+
+* Synopsis:
+* #include "dsbspecframe.h"
+* void SetAttrib( AstObject *this, const char *setting )
+
+* Class Membership:
+* DSBSpecFrame member function (over-rides the astSetAttrib protected
+* method inherited from the SpecFrame class).
+
+* Description:
+* This function assigns an attribute value for a DSBSpecFrame, the
+* attribute and its value being specified by means of a string of
+* the form:
+*
+* "attribute= value "
+*
+* Here, "attribute" specifies the attribute name and should be in
+* lower case with no white space present. The value to the right
+* of the "=" should be a suitable textual representation of the
+* value to be assigned and this will be interpreted according to
+* the attribute's data type. White space surrounding the value is
+* only significant for string attributes.
+
+* Parameters:
+* this
+* Pointer to the DSBSpecFrame.
+* setting
+* Pointer to a null-terminated string specifying the new attribute
+* value.
+*/
+
+/* Local Variables: */
+ AstDSBSpecFrame *this; /* Pointer to the DSBSpecFrame structure */
+ AstMapping *tmap; /* Ptr to Mapping from this to topofreq */
+ AstMapping *umap; /* Ptr to Mapping between units */
+ double dtemp; /* Attribute value */
+ double dval; /* Attribute value */
+ int ival; /* Attribute value */
+ int len; /* Length of setting string */
+ int nc; /* Used length */
+ int off; /* Offset to start of string */
+
+/* Check the global error status. */
+ if ( !astOK ) return;
+
+/* Obtain a pointer to the DSBSpecFrame structure. */
+ this = (AstDSBSpecFrame *) this_object;
+
+/* Obtain the length of the setting string. */
+ len = (int) strlen( setting );
+
+/* Test for each recognised attribute in turn, using "astSscanf" to parse the
+ setting string and extract the attribute value (or an offset to it in the
+ case of string values). In each case, use the value set in "nc" to check
+ that the entire string was matched. Once a value has been obtained, use the
+ appropriate method to set it. */
+
+/* DSBCentre */
+/* --------- */
+ if ( strstr( setting, "dsbcentre=" ) ) {
+
+/* Without any units indication - assume it is supplied in the system of
+ the DSBSpecFrame. */
+ int ok = 0;
+ if( nc = 0,
+ ( 1 == astSscanf( setting, "dsbcentre= %lg %n", &dval, &nc ) )
+ && ( nc >= len ) ) {
+ ok = 1;
+
+/* With units indication. Is there a Mapping from the supplied units to the
+ units used by the DSBSpecFrame? If so, use the Mapping to convert the
+ supplied value to the required units. */
+ } else if ( nc = 0,
+ ( 1 == astSscanf( setting, "dsbcentre= %lg %n%*s %n", &dval, &off, &nc ) )
+ && ( nc >= len ) ) {
+
+ if( ( umap = astUnitMapper( setting + off, astGetUnit( this, 0 ), NULL, NULL ) ) ) {
+ astTran1( umap, 1, &dval, 1, &dtemp );
+ dval = dtemp;
+ umap = astAnnul( umap );
+ if( astOK && dval != AST__BAD ) ok = 1;
+
+/* Otherwise report an error. */
+ } else if( astOK ) {
+ astError( AST__ATTIN, "astSetAttrib(%s): Value supplied for "
+ "attribute \"DSBCentre\" (%s) uses units which are "
+ "inappropriate for the current spectral system (%s).", status,
+ astGetClass( this ), setting + 10,
+ astGetTitle( this ) );
+ }
+ }
+
+/* Convert the value from the supplied system to topocentric frequency in
+ Hx, and store. */
+ if( ok ) {
+
+/* Find the Mapping from the spectral system described by this SpecFrame to
+ topocentric frequency in Hz. */
+ tmap = TopoMap( this, 1, "astSetAttrib", status );
+ if ( astOK ) {
+
+/* Transform the supplied value to topocentric frequency. */
+ astTran1( tmap, 1, &dval, 1, &dtemp );
+ if( dtemp == AST__BAD ) {
+ astError( AST__ATTIN, "astSetAttrib(%s): The setting \"%s\" is "
+ "invalid for a %s.", status, astGetClass( this ), setting,
+ astGetClass( this ) );
+ } else {
+
+/* Store it. */
+ astSetDSBCentre( this, dtemp );
+
+ }
+ tmap = astAnnul( tmap );
+ }
+
+ } else if( astOK ) {
+ astError( AST__ATTIN, "astSetAttrib(%s): The setting \"%s\" is "
+ "invalid for a %s.", status, astGetClass( this ), setting,
+ astGetClass( this ) );
+ }
+
+/* IF */
+/* -- */
+/* Without any units indication - assume GHz. Convert to Hz for storage. */
+ } else if ( nc = 0,
+ ( 1 == astSscanf( setting, "if= %lg %n", &dval, &nc ) )
+ && ( nc >= len ) ) {
+ astSetIF( this, dval*1.0E9 );
+
+/* With units indication. */
+ } else if ( nc = 0,
+ ( 1 == astSscanf( setting, "if= %lg %n%*s %n", &dval, &off, &nc ) )
+ && ( nc >= len ) ) {
+
+/* Is there a Mapping from the supplied units to Hz? If so, use the
+ Mapping to convert the supplied value to Hz. */
+ if( ( umap = astUnitMapper( setting + off, "Hz", NULL, NULL ) ) ) {
+ astTran1( umap, 1, &dval, 1, &dtemp );
+ umap = astAnnul( umap );
+
+/* Set the intermediate frequency. */
+ astSetIF( this, dtemp );
+
+/* Otherwise report an error. */
+ } else if( astOK ) {
+ astError( AST__ATTIN, "astSetAttrib(%s): Intermediate frequency given "
+ "in an inappropriate system of units \"%g %s\".", status,
+ astGetClass( this ), dval, setting + off );
+ }
+
+/* SideBand */
+/* -------- */
+ } else if ( nc = 0,
+ ( 0 == astSscanf( setting, "sideband= %n%*s %n", &ival, &nc ) )
+ && ( nc >= len ) ) {
+
+ if( astChrMatch( "usb", setting+ival ) ) {
+ astSetSideBand( this, USB );
+
+ } else if( astChrMatch( "lsb", setting+ival ) ) {
+ astSetSideBand( this, LSB );
+
+ } else if( astChrMatch( "lo", setting+ival ) ) {
+ astSetSideBand( this, LO );
+
+ } else if( astChrMatch( "observed", setting+ival ) ) {
+ astSetSideBand( this, ( astGetIF( this ) > 0 ) ? LSB : USB );
+
+ } else if( astChrMatch( "image", setting+ival ) ) {
+ astSetSideBand( this, ( astGetIF( this ) <= 0 ) ? LSB : USB );
+
+ } else {
+ astError( AST__ATTIN, "astSetAttrib(%s): The setting \"%s\" is "
+ "invalid for a %s.", status, astGetClass( this ), setting,
+ astGetClass( this ) );
+ }
+
+/* AlignSideBand */
+/* ------------- */
+ } else if ( nc = 0,
+ ( 1 == astSscanf( setting, "alignsideband= %d %n", &ival, &nc ) )
+ && ( nc >= len ) ) {
+ astSetAlignSideBand( this, ival );
+
+/* Read-only attributes. */
+/* --------------------- */
+/* Define a macro to see if the setting string matches any of the
+ read-only attributes of this class. */
+#define MATCH(attrib) \
+ ( nc = 0, ( 0 == astSscanf( setting, attrib "=%*[^\n]%n", &nc ) ) && \
+ ( nc >= len ) )
+
+/* Use this macro to report an error if a read-only attribute has been
+ specified. */
+ } else if ( MATCH( "imagfreq" ) ) {
+ astError( AST__NOWRT, "astSet: The setting \"%s\" is invalid for a %s.", status,
+ setting, astGetClass( this ) );
+ astError( AST__NOWRT, "This is a read-only attribute." , status);
+
+/* Pass any unrecognised setting to the parent method for further
+ interpretation. */
+ } else {
+ (*parent_setattrib)( this_object, setting, status );
+ }
+}
+
+static int SubFrame( AstFrame *target_frame, AstFrame *template,
+ int result_naxes, const int *target_axes,
+ const int *template_axes, AstMapping **map,
+ AstFrame **result, int *status ) {
+/*
+* Name:
+* SubFrame
+
+* Purpose:
+* Select axes from a DSBSpecFrame and convert to the new coordinate
+* system.
+
+* Type:
+* Private function.
+
+* Synopsis:
+* #include "dsbspecframe.h"
+* int SubFrame( AstFrame *target, AstFrame *template,
+* int result_naxes, const int *target_axes,
+* const int *template_axes, AstMapping **map,
+* AstFrame **result, int *status )
+
+* Class Membership:
+* DSBSpecFrame member function (over-rides the protected astSubFrame
+* method inherited from the SpecFrame class).
+
+* Description:
+* This function selects a requested sub-set (or super-set) of the axes
+* from a "target" DSBSpecFrame and creates a new Frame with copies of
+* the selected axes assembled in the requested order. It then
+* optionally overlays the attributes of a "template" Frame on to the
+* result. It returns both the resulting Frame and a Mapping that
+* describes how to convert between the coordinate systems described by
+* the target and result Frames. If necessary, this Mapping takes
+* account of any differences in the Frames' attributes due to the
+* influence of the template.
+
+* Parameters:
+* target
+* Pointer to the target DSBSpecFrame, from which axes are to be
+* selected.
+* template
+* Pointer to the template Frame, from which new attributes for the
+* result Frame are to be obtained. Optionally, this may be NULL, in
+* which case no overlaying of template attributes will be performed.
+* result_naxes
+* Number of axes to be selected from the target Frame. This number may
+* be greater than or less than the number of axes in this Frame (or
+* equal).
+* target_axes
+* Pointer to an array of int with result_naxes elements, giving a list
+* of the (zero-based) axis indices of the axes to be selected from the
+* target DSBSpecFrame. The order in which these are given determines
+* the order in which the axes appear in the result Frame. If any of the
+* values in this array is set to -1, the corresponding result axis will
+* not be derived from the target Frame, but will be assigned default
+* attributes instead.
+* template_axes
+* Pointer to an array of int with result_naxes elements. This should
+* contain a list of the template axes (given as zero-based axis indices)
+* with which the axes of the result Frame are to be associated. This
+* array determines which axes are used when overlaying axis-dependent
+* attributes of the template on to the result. If any element of this
+* array is set to -1, the corresponding result axis will not receive any
+* template attributes.
+*
+* If the template argument is given as NULL, this array is not used and
+* a NULL pointer may also be supplied here.
+* map
+* Address of a location to receive a pointer to the returned Mapping.
+* The forward transformation of this Mapping will describe how to
+* convert coordinates from the coordinate system described by the target
+* DSBSpecFrame to that described by the result Frame. The inverse
+* transformation will convert in the opposite direction.
+* result
+* Address of a location to receive a pointer to the result Frame.
+* status
+* Pointer to the inherited status variable.
+
+* Returned Value:
+* A non-zero value is returned if coordinate conversion is possible
+* between the target and the result Frame. Otherwise zero is returned and
+* *map and *result are returned as NULL (but this will not in itself
+* result in an error condition). In general, coordinate conversion should
+* always be possible if no template Frame is supplied but may not always
+* be possible otherwise.
+
+* Notes:
+* - A value of zero will be returned if this function is invoked with the
+* global error status set, or if it should fail for any reason.
+
+* Implementation Notes:
+* - This implementation addresses the selection of axes from a
+* DSBSpecFrame object. This results in another object of the same class
+* only if the single DSBSpecFrame axis is selected exactly once.
+* Otherwise, the result is a Frame class object which inherits the
+* DSBSpecFrame's axis information (if appropriate) but none of the other
+* properties of a DSBSpecFrame.
+* - In the event that a DSBSpecFrame results, the returned Mapping will
+* take proper account of the relationship between the target and result
+* coordinate systems.
+* - In the event that a Frame class object results, the returned Mapping
+* will only represent a selection/permutation of axes.
+
+* Implementation Deficiencies:
+* - Any axis selection is currently permitted. Probably this should be
+* restricted so that each axis can only be selected once. The
+* astValidateAxisSelection method will do this but currently there are bugs
+* in the CmpFrame class that cause axis selections which will not pass this
+* test. Install the validation when these are fixed.
+*/
+
+/* Local Variables: */
+ AstDSBSpecFrame *dsbresult;/* Pointer to the DSBSpecFrame result Frame */
+ AstDSBSpecFrame *dsbtarget;/* Pointer to the DSBSpecFrame target Frame */
+ AstMapping *map1; /* Intermediate Mapping */
+ AstMapping *map2; /* Intermediate Mapping */
+ AstMapping *map3; /* Intermediate Mapping */
+ int alignsb; /* Use sidebands to align the Frames? */
+ int match; /* Coordinate conversion is possible? */
+ int obs_sb; /* The observed sideband value */
+ int old_sb; /* The original Sideband value */
+
+/* Initialise the returned values. */
+ *map = NULL;
+ *result = NULL;
+ match = 0;
+
+/* Check the global error status. */
+ if ( !astOK ) return match;
+
+/* Invoke the astSubFrame method inherited from the parent SpecFrame
+ class. This will (if possible) create a result Frame which is a
+ DSBSpecFrame (since the supplied target Frame is a DSBSpecFrame).
+ However, the Mapping from target to result Frame will take no account
+ of any differences in the values of the attributes specific to the
+ DSBSpecFrame class. */
+ match = (*parent_subframe)( target_frame, template, result_naxes,
+ target_axes, template_axes, map, result, status );
+
+/* If a match occurred, and the result and template Frames are both
+ DSBSpecFrames, we now modify the Mapping to take account of
+ DSBSpecFrame-specific attributes. */
+ if( match && template && astIsADSBSpecFrame( template ) &&
+ astIsADSBSpecFrame( *result ) ) {
+
+/* Get pointers to the two DSBSpecFrames */
+ dsbtarget = (AstDSBSpecFrame *) target_frame;
+
+/* See whether alignment occurs between sidebands. If the current call to
+ this function is part of the process of restoring a FrameSet's integrity
+ following changes to the FrameSet's current Frame, then we ignore the
+ setting of the AlignSideBand attributes and use 1. This ensures that
+ when the SideBand attribute (for instance) is changed via a FrameSet
+ pointer, the Mappings within the FrameSet are modified to produce
+ frequencies in the new SideBand. In most other cases, astronomers
+ usually want to align the DSBSpecFrames as if they were basic SpecFrames
+ (that is, ignoring the setting of the SideBand attribute). */
+ if( astGetFrameFlags( target_frame ) & AST__INTFLAG ) {
+ alignsb = 1;
+ } else {
+ alignsb = astGetAlignSideBand( dsbtarget ) &&
+ astGetAlignSideBand( (AstDSBSpecFrame *) template );
+ }
+
+/* If we are aligning the sidebands we need to modify the Mapping
+ returned above by the parent SubFrame method. The existing Mapping
+ will convert between the spectral systems represented by the two
+ DSBSpecFrames but will not take account of any difference in
+ sidebands. */
+ if( alignsb ) {
+
+/* We assume that alignment occurs in the observed sideband. Determine
+ which side band is the observed sideband in the target. */
+ old_sb = astGetSideBand( dsbtarget );
+ astSetC( dsbtarget, "SideBand", "observed" );
+ obs_sb = astGetSideBand( dsbtarget );
+ astSetSideBand( dsbtarget, old_sb );
+
+/* Create a Mapping which transforms positions from the target to an exact
+ copy of the target in which the SideBand attribute is set to the
+ observed (USB or LSB) sideband. This will be a UnitMap if the target
+ already represents the observed sideband. */
+ if( obs_sb == USB ) {
+ map1 = ToUSBMapping( dsbtarget, "astSubFrame", status );
+
+ } else if( obs_sb == LSB ) {
+ map1 = ToLSBMapping( dsbtarget, "astSubFrame", status );
+
+ } else {
+ map1 = NULL;
+ astError( AST__INTER, "astGetImagFreq(%s): Illegal sideband value "
+ "(%d) encountered (internal AST programming error).", status,
+ astGetClass( target_frame ), obs_sb );
+ }
+
+/* Determine which side band is the observed sideband in the result. */
+ dsbresult = (AstDSBSpecFrame *) *result;
+ old_sb = astGetSideBand( dsbresult );
+ astSetC( dsbresult, "SideBand", "observed" );
+ obs_sb = astGetSideBand( dsbresult );
+ astSetSideBand( dsbresult, old_sb );
+
+/* Create a Mapping which transforms positions from the result to an exact
+ copy of the result in which the SideBand attribute is set to the
+ obserfed sideband. This will be a UnitMap if the target already represents
+ the observed sideband. */
+ if( obs_sb == USB ) {
+ map2 = ToUSBMapping( dsbresult, "astSubFrame", status );
+
+ } else if( obs_sb == LSB ) {
+ map2 = ToLSBMapping( dsbresult, "astSubFrame", status );
+
+ } else {
+ map2 = NULL;
+ astError( AST__INTER, "astGetImagFreq(%s): Illegal sideband value "
+ "(%d) encountered (internal AST programming error).", status,
+ astGetClass( target_frame ), obs_sb );
+ }
+
+/* Invert it to get the mapping from the observed sideband to the result. */
+ astInvert( map2 );
+
+/* Form a Mapping which first maps target values to the observed sideband,
+ then applies the Mapping returned by the parent SubFrame method in
+ order to convert between spectral systems, and then converts from the
+ observed sideband to the SideBand of the result. */
+ map3 = (AstMapping *) astCmpMap( map1, *map, 1, "", status );
+ map1 = astAnnul( map1 );
+ *map = astAnnul( *map );
+ map1 = (AstMapping *) astCmpMap( map3, map2, 1, "", status );
+ map3 = astAnnul( map3 );
+ map2 = astAnnul( map2 );
+
+/* Returned the simplified Mapping. */
+ *map = astSimplify( map1 );
+ map1 = astAnnul( map1 );
+ }
+ }
+
+/* If an error occurred or no match was found, annul the returned
+ objects and reset the returned result. */
+ if ( !astOK || !match ) {
+ if( *map ) *map = astAnnul( *map );
+ if( *result ) *result = astAnnul( *result );
+ match = 0;
+ }
+
+/* Return the result. */
+ return match;
+
+}
+
+static int TestAttrib( AstObject *this_object, const char *attrib, int *status ) {
+/*
+* Name:
+* TestAttrib
+
+* Purpose:
+* Test if a specified attribute value is set for a DSBSpecFrame.
+
+* Type:
+* Private function.
+
+* Synopsis:
+* #include "dsbspecframe.h"
+* int TestAttrib( AstObject *this, const char *attrib, int *status )
+
+* Class Membership:
+* DSBSpecFrame member function (over-rides the astTestAttrib protected
+* method inherited from the SpecFrame class).
+
+* Description:
+* This function returns a boolean result (0 or 1) to indicate whether
+* a value has been set for one of a DSBSpecFrame's attributes.
+
+* Parameters:
+* this
+* Pointer to the DSBSpecFrame.
+* attrib
+* Pointer to a null-terminated string specifying the attribute
+* name. This should be in lower case with no surrounding white
+* space.
+* status
+* Pointer to the inherited status variable.
+
+* Returned Value:
+* One if a value has been set, otherwise zero.
+
+* Notes:
+* - A value of zero will be returned if this function is invoked
+* with the global status set, or if it should fail for any reason.
+*/
+
+/* Local Variables: */
+ AstDSBSpecFrame *this; /* Pointer to the DSBSpecFrame structure */
+ int result; /* Result value to return */
+
+/* Initialise. */
+ result = 0;
+
+/* Check the global error status. */
+ if ( !astOK ) return result;
+
+/* Obtain a pointer to the DSBSpecFrame structure. */
+ this = (AstDSBSpecFrame *) this_object;
+
+/* Check the attribute name and test the appropriate attribute. */
+
+/* DSBCentre */
+/* --------- */
+ if ( !strcmp( attrib, "dsbcentre" ) ) {
+ result = astTestDSBCentre( this );
+
+/* IF */
+/* -- */
+ } else if ( !strcmp( attrib, "if" ) ) {
+ result = astTestIF( this );
+
+/* SideBand */
+/* -------- */
+ } else if ( !strcmp( attrib, "sideband" ) ) {
+ result = astTestSideBand( this );
+
+/* AlignSideBand */
+/* ------------- */
+ } else if ( !strcmp( attrib, "alignsideband" ) ) {
+ result = astTestAlignSideBand( this );
+
+/* Read-only attributes. */
+/* --------------------- */
+/* Test if the attribute name matches any of the read-only attributes
+ of this class. If it does, then return zero. */
+ } else if ( !strcmp( attrib, "imagfreq" ) ) {
+ result = 0;
+
+/* If the attribute is not recognised, pass it on to the parent method
+ for further interpretation. */
+ } else {
+ result = (*parent_testattrib)( this_object, attrib, status );
+ }
+
+/* Return the result, */
+ return result;
+}
+
+static AstMapping *ToLOMapping( AstDSBSpecFrame *this, const char *method, int *status ){
+/*
+* Name:
+* ToLOMapping
+
+* Purpose:
+* Create a Mapping which transforms a DSBSpecFrame to offset from the
+* local oscillator frequency.
+
+* Type:
+* Private function.
+
+* Synopsis:
+* #include "dsbspecframe.h"
+* AstMapping *ToLOMapping( AstDSBSpecFrame *this, const char *method, int *status )
+
+* Class Membership:
+* DSBSpecFrame member function
+
+* Description:
+* This function returns a pointer to a new Mapping which transforms
+* positions in the supplied DSBSpecFrame into an offset from the local
+* oscillator frequency. This will be a UnitMap if the DSBSpecFrame
+* already represents offset from the local oscillator frequency.
+
+* Parameters:
+* this
+* Pointer to the DSBSpecFrame.
+* method
+* Pointer to a null-terminated string containing the name of the
+* public invoking method. This is only used in the construction of
+* error messages.
+* status
+* Pointer to the inherited status variable.
+
+* Returned Value:
+* Pointer to a new Mapping.
+
+* Notes:
+* - A NULL pointer will be returned if this function is invoked
+* with the global error status set, or if it should fail for any
+* reason.
+*/
+
+/* Local Variables: */
+ AstMapping *fmap; /* LSB to USB (topo freq) */
+ AstMapping *map1; /* This to USB (topo freq) */
+ AstMapping *map2; /* This (LSB) to This (USB) */
+ AstMapping *result; /* Pointer to the returned Mapping */
+ AstMapping *tmap; /* This to topocentric freq */
+ double f_lo; /* Local oscillator freq (topo Hz) */
+ double f_in_a; /* First LSB or USB freq */
+ double f_in_b; /* Second LSB or USB freq */
+ double f_out_a; /* First LO freq */
+ double f_out_b; /* Second LO freq */
+ int sb; /* SideBand value */
+
+/* Initialise. */
+ result = NULL;
+
+/* Check the global error status. */
+ if ( !astOK ) return result;
+
+/* If the DSBSpecFrame already represents LO offset, return a UnitMap.*/
+ sb = astGetSideBand( this );
+ if( sb == LO ) {
+ result = (AstMapping *) astUnitMap( 1, "", status );
+
+/* If the DSBSpecFrame represents the USB or LSB, create a suitable WinMap. */
+ } else {
+
+/* Find the Mapping from the spectral system described by this SpecFrame to
+ topocentric frequency in Hz. */
+ tmap = TopoMap( this, 1, method, status );
+
+/* Calculate the local oscillator frequency (topocentric in Hertz). */
+ f_lo = GetLO( this, "create a Mapping to upper sideband",
+ "astGetImagFreq", status );
+
+/* Create a 1D WinMap which converts f_in to f_out. */
+ if( sb == LSB ) {
+ f_in_a = 0.0;
+ f_in_b = f_lo;
+ f_out_a = f_lo;
+ f_out_b = 0.0;
+ } else {
+ f_in_a = 0.0;
+ f_in_b = -f_lo;
+ f_out_a = f_lo;
+ f_out_b = 0.0;
+ }
+
+ fmap = (AstMapping *) astWinMap( 1, &f_in_a, &f_in_b, &f_out_a, &f_out_b, "", status );
+
+/* Construct the Mapping: input to f_in, f_in to f_out, f_out to input */
+ map1 = (AstMapping *) astCmpMap( tmap, fmap, 1, "", status );
+ astInvert( tmap );
+ map2 = (AstMapping *) astCmpMap( map1, tmap, 1, "", status );
+
+/* Simplify */
+ result = astSimplify( map2 );
+
+/* Free resources */
+ tmap = astAnnul( tmap );
+ fmap = astAnnul( fmap );
+ map1 = astAnnul( map1 );
+ map2 = astAnnul( map2 );
+ }
+
+/* Return NULL if an error has occurred. */
+ if( !astOK ) result = astAnnul( result );
+
+/* Return the result. */
+ return result;
+
+}
+
+static AstMapping *ToLSBMapping( AstDSBSpecFrame *this, const char *method, int *status ){
+/*
+* Name:
+* ToLSBMapping
+
+* Purpose:
+* Create a Mapping which transforms a DSBSpecFrame to the lower
+* sideband.
+
+* Type:
+* Private function.
+
+* Synopsis:
+* #include "dsbspecframe.h"
+* AstMapping *ToLSBMapping( AstDSBSpecFrame *this, const char *method, int *status )
+
+* Class Membership:
+* DSBSpecFrame member function
+
+* Description:
+* This function returns a pointer to a new Mapping which transforms
+* positions in the supplied DSBSpecFrame to the lower sideband. This
+* will be a UnitMap if the DSBSpecFrame already represents the lower
+* sideband.
+
+* Parameters:
+* this
+* Pointer to the DSBSpecFrame.
+* method
+* Pointer to a null-terminated string containing the name of the
+* public invoking method. This is only used in the construction of
+* error messages.
+* status
+* Pointer to the inherited status variable.
+
+* Returned Value:
+* Pointer to a new Mapping.
+
+* Notes:
+* - A NULL pointer will be returned if this function is invoked
+* with the global error status set, or if it should fail for any
+* reason.
+*/
+
+/* Local Variables: */
+ AstMapping *fmap; /* LSB to USB (topo freq) */
+ AstMapping *map1; /* This to USB (topo freq) */
+ AstMapping *map2; /* This (LSB) to This (USB) */
+ AstMapping *result; /* Pointer to the returned Mapping */
+ AstMapping *tmap; /* This to topocentric freq */
+ double f_lo; /* Local oscillator freq (topo Hz) */
+ double f_out_a; /* First LSB freq */
+ double f_out_b; /* Second LSB freq */
+ double f_in_a; /* First USB or LO freq */
+ double f_in_b; /* Second USB or LO freq */
+ int sb; /* SideBand value */
+
+/* Initialise. */
+ result = NULL;
+
+/* Check the global error status. */
+ if ( !astOK ) return result;
+
+/* If the DSBSpecFrame already represents the LSB, return a UnitMap.*/
+ sb = astGetSideBand( this );
+ if( sb == LSB ) {
+ result = (AstMapping *) astUnitMap( 1, "", status );
+
+/* If the DSBSpecFrame represents the USB or LO offset, create a suitable
+ WinMap. */
+ } else {
+
+/* Find the Mapping from the spectral system described by this SpecFrame to
+ topocentric frequency in Hz. */
+ tmap = TopoMap( this, 1, method, status );
+
+/* Calculate the local oscillator frequency (topocentric in Hertz). */
+ f_lo = GetLO( this, "create a Mapping to lower sideband",
+ "astGetImagFreq", status );
+
+/* Create a 1D WinMap which converts USB or LO to LSB. */
+ if( sb == USB ) {
+ f_in_a = 0.0;
+ f_in_b = 2*f_lo;
+ f_out_a = 2*f_lo;
+ f_out_b = 0.0;
+ } else {
+ f_in_a = 0.0;
+ f_in_b = f_lo;
+ f_out_a = f_lo;
+ f_out_b = 0.0;
+ }
+
+ fmap = (AstMapping *) astWinMap( 1, &f_in_a, &f_in_b, &f_out_a, &f_out_b, "", status );
+
+/* Construct the Mapping: input to f_in, f_in to f_out, f_out to input */
+ map1 = (AstMapping *) astCmpMap( tmap, fmap, 1, "", status );
+ astInvert( tmap );
+ map2 = (AstMapping *) astCmpMap( map1, tmap, 1, "", status );
+
+/* Simplify */
+ result = astSimplify( map2 );
+
+/* Free resources */
+ tmap = astAnnul( tmap );
+ fmap = astAnnul( fmap );
+ map1 = astAnnul( map1 );
+ map2 = astAnnul( map2 );
+ }
+
+/* Return NULL if an error has occurred. */
+ if( !astOK ) result = astAnnul( result );
+
+/* Return the result. */
+ return result;
+
+}
+
+static AstMapping *TopoMap( AstDSBSpecFrame *this, int forward,
+ const char *method, int *status ){
+/*
+* Name:
+* TopoMap
+
+* Purpose:
+* Create a Mapping which transforms a DSBSpecFrame to topocentric
+* frequency.
+
+* Type:
+* Private function.
+
+* Synopsis:
+* #include "dsbspecframe.h"
+* AstMapping *TopoMap( AstDSBSpecFrame *this, int forward,
+* const char *method, int *status )
+
+* Class Membership:
+* DSBSpecFrame member function
+
+* Description:
+* This function returns a pointer to a new Mapping which transforms
+* positions in the supplied DSBSpecFrame to the corresponding
+* topocentric frequency values in Hz (or the inverse of this).
+
+* Parameters:
+* this
+* Pointer to the DSBSpecFrame.
+* forward
+* If zero, the calcuated Mapping is inverted before being returned.
+* method
+* Pointer to a null-terminated string containing the name of the
+* public invoking method. This is only used in the construction of
+* error messages.
+* status
+* Pointer to the inherited status variable.
+
+* Returned Value:
+* Pointer to a new Mapping.
+
+* Notes:
+* - A NULL pointer will be returned if this function is invoked
+* with the global error status set, or if it should fail for any
+* reason.
+*/
+
+/* Local Variables: */
+ AstMapping *result; /* The returned Mapping */
+ AstFrameSet *fs; /* FrameSet connecting tf1 and tf2 */
+ AstSpecFrame *tf1; /* SpecFrame corresponding to this DSBSpecFrame */
+ AstSpecFrame *tf2; /* Topocentric frequency SpecFrame */
+ int template_axis; /* The axis to overlay */
+
+/* Initialise. */
+ result = NULL;
+
+/* Check the global error status. */
+ if ( !astOK ) return result;
+
+/* Make a SpecFrame and then overlay the SpecFrame attributes of this
+ DSBSpecFrame onto the new SpecFrame. This means it inherits the current
+ values of things like ObsLon and ObsLat. */
+ tf1 = astSpecFrame( "", status );
+ template_axis = 0;
+ (*parent_overlay)( (AstFrame *) this, &template_axis, (AstFrame *) tf1, status );
+
+/* Copy this new SpecFrame and set its attributes to describe topocentric
+ frequency in Hz. Ensure that alignment occurs in the topocentric Frame. */
+ astSetAlignStdOfRest( tf1, AST__TPSOR);
+ tf2 = astCopy( tf1 );
+ astSetSystem( tf2, AST__FREQ );
+ astSetStdOfRest( tf2, AST__TPSOR );
+ astSetUnit( tf2, 0, "Hz" );
+
+/* Find the Mapping from the spectral system described by this SpecFrame to
+ topocentric frequency in Hz. */
+ fs = astConvert( tf1, tf2, "" );
+ if ( astOK ) {
+ if( !fs ) {
+ astError( AST__INTER, "%s(%s): Cannot convert DSBCentre "
+ "value from the supplied system to topocentric frequency "
+ "(internal AST programming error).", status, method,
+ astGetClass( this ) );
+ } else {
+ result = astGetMapping( fs, AST__BASE, AST__CURRENT );
+ if( !forward ) astInvert( result );
+ }
+ fs = astAnnul( fs );
+ }
+
+/* Free resources */
+ tf1 = astAnnul( tf1 );
+ tf2 = astAnnul( tf2 );
+
+/* Annul the result if an error has occurred. */
+ if( !astOK ) result = astAnnul( result );
+
+/* Return the result. */
+ return result;
+
+}
+
+static AstMapping *ToUSBMapping( AstDSBSpecFrame *this, const char *method, int *status ){
+/*
+* Name:
+* ToUSBMapping
+
+* Purpose:
+* Create a Mapping which transforms a DSBSpecFrame to the upper
+* sideband.
+
+* Type:
+* Private function.
+
+* Synopsis:
+* #include "dsbspecframe.h"
+* AstMapping *ToUSBMapping( AstDSBSpecFrame *this, const char *method, int *status )
+
+* Class Membership:
+* DSBSpecFrame member function
+
+* Description:
+* This function returns a pointer to a new Mapping which transforms
+* positions in the supplied DSBSpecFrame to the upper sideband. This
+* will be a UnitMap if the DSBSpecFrame already represents the upper
+* sideband.
+
+* Parameters:
+* this
+* Pointer to the DSBSpecFrame.
+* method
+* Pointer to a null-terminated string containing the name of the
+* public invoking method. This is only used in the construction of
+* error messages.
+* status
+* Pointer to the inherited status variable.
+
+* Returned Value:
+* Pointer to a new Mapping.
+
+* Notes:
+* - A NULL pointer will be returned if this function is invoked
+* with the global error status set, or if it should fail for any
+* reason.
+*/
+
+/* Local Variables: */
+ AstMapping *fmap; /* LSB to USB (topo freq) */
+ AstMapping *map1; /* This to USB (topo freq) */
+ AstMapping *map2; /* This (LSB) to This (USB) */
+ AstMapping *result; /* Pointer to the returned Mapping */
+ AstMapping *tmap; /* This to topocentric freq */
+ double f_lo; /* Local oscillator freq (topo Hz) */
+ double f_in_a; /* First LSB or LO freq */
+ double f_in_b; /* Second LSB or LO freq */
+ double f_out_a; /* First USB freq */
+ double f_out_b; /* Second USB freq */
+ int sb; /* SideBand value */
+
+/* Initialise. */
+ result = NULL;
+
+/* Check the global error status. */
+ if ( !astOK ) return result;
+
+/* If the DSBSpecFrame already represents the USB, return a UnitMap.*/
+ sb = astGetSideBand( this );
+ if( sb == USB ) {
+ result = (AstMapping *) astUnitMap( 1, "", status );
+
+/* If the DSBSpecFrame represents the LSB, or LO offset, create a suitable
+ WinMap. */
+ } else {
+
+/* Find the Mapping from the spectral system described by this SpecFrame to
+ topocentric frequency in Hz. */
+ tmap = TopoMap( this, 1, method, status );
+
+/* Calculate the local oscillator frequency (topocentric in Hertz). */
+ f_lo = GetLO( this, "create a Mapping to upper sideband",
+ "astGetImagFreq", status );
+
+/* Create a 1D WinMap which converts f_in to f_out. */
+ if( sb == LSB ) {
+ f_in_a = 0.0;
+ f_in_b = 2*f_lo;
+ f_out_a = 2*f_lo;
+ f_out_b = 0.0;
+ } else {
+ f_in_a = 0.0;
+ f_in_b = -f_lo;
+ f_out_a = f_lo;
+ f_out_b = 0.0;
+ }
+
+ fmap = (AstMapping *) astWinMap( 1, &f_in_a, &f_in_b, &f_out_a, &f_out_b, "", status );
+
+/* Construct the Mapping: input to f_in, f_in to f_out, f_out to input */
+ map1 = (AstMapping *) astCmpMap( tmap, fmap, 1, "", status );
+ astInvert( tmap );
+ map2 = (AstMapping *) astCmpMap( map1, tmap, 1, "", status );
+
+/* Simplify */
+ result = astSimplify( map2 );
+
+/* Free resources */
+ tmap = astAnnul( tmap );
+ fmap = astAnnul( fmap );
+ map1 = astAnnul( map1 );
+ map2 = astAnnul( map2 );
+ }
+
+/* Return NULL if an error has occurred. */
+ if( !astOK ) result = astAnnul( result );
+
+/* Return the result. */
+ return result;
+
+}
+
+static void VerifyAttrs( AstDSBSpecFrame *this, const char *purp,
+ const char *attrs, const char *method, int *status ) {
+/*
+* Name:
+* VerifyAttrs
+
+* Purpose:
+* Verify that usable attribute values are available.
+
+* Type:
+* Private function.
+
+* Synopsis:
+* #include "dsbspecframe.h"
+* void VerifyAttrs( AstDSBSpecFrame *this, const char *purp,
+* const char *attrs, const char *method, int *status )
+
+* Class Membership:
+* DSBSpecFrame member function
+
+* Description:
+* This function tests each attribute listed in "attrs". It returns
+* without action if 1) an explicit value has been set for each attribute
+* or 2) the UseDefs attribute of the supplied DSBSpecFrame is non-zero.
+*
+* If UseDefs is zero (indicating that default values should not be
+* used for attributes), and any of the named attributes does not have
+* an explicitly set value, then an error is reported.
+
+* Parameters:
+* this
+* Pointer to the DSBSpecFrame.
+* purp
+* Pointer to a text string containing a message which will be
+* included in any error report. This shouldindicate the purpose
+* for which the attribute value is required.
+* attrs
+* A string holding a space separated list of attribute names.
+* method
+* A string holding the name of the calling method for use in error
+* messages.
+* status
+* Pointer to the inherited status variable.
+
+*/
+
+/* Local Variables: */
+ const char *a;
+ const char *desc;
+ const char *p;
+ int len;
+ int set;
+ int state;
+
+/* Check inherited status */
+ if( !astOK ) return;
+
+/* If the DSBSpecFrame has a non-zero value for its UseDefs attribute, then
+ all attributes are assumed to have usable values, since the defaults
+ will be used if no explicit value has been set. So we only need to do
+ any checks if UseDefs is zero. */
+ if( !astGetUseDefs( this ) ) {
+
+/* Initialise variables to avoid compiler warnings. */
+ a = NULL;
+ desc = NULL;
+ len = 0;
+ set = 0;
+
+/* Loop round the "attrs" string identifying the start and length of each
+ non-blank word in the string. */
+ state = 0;
+ p = attrs;
+ while( 1 ) {
+ if( state == 0 ) {
+ if( !isspace( *p ) ) {
+ a = p;
+ len = 1;
+ state = 1;
+ }
+ } else {
+ if( isspace( *p ) || !*p ) {
+
+/* The end of a word has just been reached. Compare it to each known
+ attribute value. Get a flag indicating if the attribute has a set
+ value, and a string describing the attribute.*/
+ if( len > 0 ) {
+
+ if( !strncmp( "DSBCentre", a, len ) ) {
+ set = astTestDSBCentre( this );
+ desc = "central position of interest";
+
+ } else if( !strncmp( "IF", a, len ) ) {
+ set = astTestIF( this );
+ desc = "intermediate frequency";
+
+ } else {
+ astError( AST__INTER, "VerifyAttrs(DSBSpecFrame): "
+ "Unknown attribute name \"%.*s\" supplied (AST "
+ "internal programming error).", status, len, a );
+ }
+
+/* If the attribute does not have a set value, report an error. */
+ if( !set && astOK ) {
+ astError( AST__NOVAL, "%s(%s): Cannot %s.", status, method,
+ astGetClass( this ), purp );
+ astError( AST__NOVAL, "No value has been set for "
+ "the AST \"%.*s\" attribute (%s).", status, len, a,
+ desc );
+ }
+
+/* Continue the word search algorithm. */
+ }
+ len = 0;
+ state = 0;
+ } else {
+ len++;
+ }
+ }
+ if( !*(p++) ) break;
+ }
+ }
+}
+
+
+/* Functions which access class attributes. */
+/* ---------------------------------------- */
+/* Implement member functions to access the attributes associated with
+ this class using the macros defined for this purpose in the
+ "object.h" file. For a description of each attribute, see the class
+ interface (in the associated .h file). */
+
+/*
+*att++
+* Name:
+* ImagFreq
+
+* Purpose:
+* The image sideband equivalent of the rest frequency.
+
+* Type:
+* Public attribute.
+
+* Synopsis:
+* Floating point, read-only.
+
+* Description:
+* This is a read-only attribute giving the frequency which
+* corresponds to the rest frequency but is in the opposite sideband.
+
+* The value is calculated by first transforming the rest frequency
+* (given by the RestFreq attribute) from the standard of rest of the
+* source (given by the SourceVel and SourceVRF attributes) to the
+* standard of rest of the observer (i.e. the topocentric standard of
+* rest). The resulting topocentric frequency is assumed to be in the
+* same sideband as the value given for the DSBCentre attribute (the
+* "observed" sideband), and is transformed to the other sideband (the
+* "image" sideband). The new frequency is converted back to the standard
+* of rest of the source, and the resulting value is returned as the
+* attribute value, in units of GHz.
+
+* Applicability:
+* DSBSpecFrame
+* All DSBSpecFrames have this attribute.
+
+*att--
+*/
+
+
+/*
+*att++
+* Name:
+* DSBCentre
+
+* Purpose:
+* The central position of interest in a dual sideband spectrum.
+
+* Type:
+* Public attribute.
+
+* Synopsis:
+* Floating point.
+
+* Description:
+* This attribute specifies the central position of interest in a dual
+* sideband spectrum. Its sole use is to determine the local oscillator
+* frequency (the frequency which marks the boundary between the lower
+* and upper sidebands). See the description of the IF (intermediate
+* frequency) attribute for details of how the local oscillator frequency
+* is calculated. The sideband containing this central position is
+* referred to as the "observed" sideband, and the other sideband as
+* the "image" sideband.
+*
+* The value is accessed as a position in the spectral system
+* represented by the SpecFrame attributes inherited by this class, but
+* is stored internally as topocentric frequency. Thus, if the System
+* attribute of the DSBSpecFrame is set to "VRAD", the Unit attribute
+* set to "m/s" and the StdOfRest attribute set to "LSRK", then values
+* for the DSBCentre attribute should be supplied as radio velocity in
+* units of "m/s" relative to the kinematic LSR (alternative units may
+* be used by appending a suitable units string to the end of the value).
+* This value is then converted to topocentric frequency and stored. If
+* (say) the Unit attribute is subsequently changed to "km/s" before
+* retrieving the current value of the DSBCentre attribute, the stored
+* topocentric frequency will be converted back to LSRK radio velocity,
+* this time in units of "km/s", before being returned.
+*
+* The default value for this attribute is 30 GHz.
+
+* Applicability:
+* DSBSpecFrame
+* All DSBSpecFrames have this attribute.
+
+* Note:
+* - The attributes which define the transformation to or from topocentric
+* frequency should be assigned their correct values before accessing
+* this attribute. These potentially include System, Unit, StdOfRest,
+* ObsLon, ObsLat, ObsAlt, Epoch, RefRA, RefDec and RestFreq.
+
+*att--
+*/
+/* The central frequency (topocentric frequency in Hz). */
+astMAKE_CLEAR(DSBSpecFrame,DSBCentre,dsbcentre,AST__BAD)
+astMAKE_GET(DSBSpecFrame,DSBCentre,double,3.0E10,((this->dsbcentre!=AST__BAD)?this->dsbcentre:3.0E10))
+astMAKE_SET(DSBSpecFrame,DSBCentre,double,dsbcentre,value)
+astMAKE_TEST(DSBSpecFrame,DSBCentre,( this->dsbcentre != AST__BAD ))
+
+
+/*
+*att++
+* Name:
+* IF
+
+* Purpose:
+* The intermediate frequency in a dual sideband spectrum.
+
+* Type:
+* Public attribute.
+
+* Synopsis:
+* Floating point.
+
+* Description:
+* This attribute specifies the (topocentric) intermediate frequency in
+* a dual sideband spectrum. Its sole use is to determine the local
+* oscillator (LO) frequency (the frequency which marks the boundary
+* between the lower and upper sidebands). The LO frequency is
+* equal to the sum of the centre frequency and the intermediate
+* frequency. Here, the "centre frequency" is the topocentric
+* frequency in Hz corresponding to the current value of the DSBCentre
+* attribute. The value of the IF attribute may be positive or
+* negative: a positive value results in the LO frequency being above
+* the central frequency, whilst a negative IF value results in the LO
+* frequency being below the central frequency. The sign of the IF
+* attribute value determines the default value for the SideBand
+* attribute.
+*
+* When setting a new value for this attribute, the units in which the
+* frequency value is supplied may be indicated by appending a suitable
+* string to the end of the formatted value. If the units are not
+* specified, then the supplied value is assumed to be in units of GHz.
+* For instance, the following strings all result in an IF of 4 GHz being
+* used: "4.0", "4.0 GHz", "4.0E9 Hz", etc.
+*
+* When getting the value of this attribute, the returned value is
+* always in units of GHz. The default value for this attribute is 4 GHz.
+
+* Applicability:
+* DSBSpecFrame
+* All DSBSpecFrames have this attribute.
+
+*att--
+*/
+/* The intermediate frequency (topocentric in Hz). */
+astMAKE_CLEAR(DSBSpecFrame,IF,ifr,AST__BAD)
+astMAKE_GET(DSBSpecFrame,IF,double,4.0E9,((this->ifr!=AST__BAD)?this->ifr:4.0E9))
+astMAKE_SET(DSBSpecFrame,IF,double,ifr,value)
+astMAKE_TEST(DSBSpecFrame,IF,( this->ifr != AST__BAD ))
+
+/*
+*att++
+* Name:
+* SideBand
+
+* Purpose:
+* Indicates which sideband a dual sideband spectrum represents.
+
+* Type:
+* Public attribute.
+
+* Synopsis:
+* String.
+
+* Description:
+* This attribute indicates whether the DSBSpecFrame currently
+* represents its lower or upper sideband, or an offset from the local
+* oscillator frequency. When querying the current value, the returned
+* string is always one of "usb" (for upper sideband), "lsb" (for lower
+* sideband), or "lo" (for offset from the local oscillator frequency).
+* When setting a new value, any of the strings "lsb", "usb", "observed",
+* "image" or "lo" may be supplied (case insensitive). The "observed"
+* sideband is which ever sideband (upper or lower) contains the central
+* spectral position given by attribute DSBCentre, and the "image"
+* sideband is the other sideband. It is the sign of the IF attribute
+* which determines if the observed sideband is the upper or lower
+* sideband. The default value for SideBand is the observed sideband.
+
+* Applicability:
+* DSBSpecFrame
+* All DSBSpecFrames have this attribute.
+
+*att--
+*/
+/* Protected access to the SideBand attribute uses BADSB to indicate
+ "unset". Other negative values mean "LSB", zero means "LO" and
+ positive values mean "USB". */
+astMAKE_CLEAR(DSBSpecFrame,SideBand,sideband,BADSB)
+astMAKE_SET(DSBSpecFrame,SideBand,int,sideband,((value<0)?LSB:((value==0)?LO:USB)))
+astMAKE_TEST(DSBSpecFrame,SideBand,( this->sideband != BADSB ))
+astMAKE_GET(DSBSpecFrame,SideBand,int,USB,(this->sideband == BADSB ? ((astGetIF( this )>0)?LSB:USB):this->sideband))
+
+/*
+*att++
+* Name:
+* AlignSideBand
+
+* Purpose:
+* Should the SideBand attribute be taken into account when aligning
+* this DSBSpecFrame with another DSBSpecFrame?
+
+* Type:
+* Public attribute.
+
+* Synopsis:
+* Integer (boolean).
+
+* Description:
+* This attribute controls how a DSBSpecFrame behaves when an attempt
+* is made to align it with another DSBSpecFrame using
+c astFindFrame or astConvert.
+f AST_FINDFRAME or AST_CONVERT.
+* If both DSBSpecFrames have a non-zero value for AlignSideBand, the
+* value of the SideBand attribute in each DSBSpecFrame is used so that
+* alignment occurs between sidebands. That is, if one DSBSpecFrame
+* represents USB and the other represents LSB then
+c astFindFrame and astConvert
+f AST_FINDFRAME and AST_CONVERT
+* will recognise that the DSBSpecFrames represent different sidebands
+* and will take this into account when constructing the Mapping that
+* maps positions in one DSBSpecFrame into the other. If AlignSideBand
+* in either DSBSpecFrame is set to zero, then the values of the SideBand
+* attributes are ignored. In the above example, this would result in a
+* frequency in the first DSBSpecFrame being mapped onto the same
+* frequency in the second DSBSpecFrame, even though those frequencies
+* refer to different sidebands. In other words, if either AlignSideBand
+* attribute is zero, then the two DSBSpecFrames aligns like basic
+* SpecFrames. The default value for AlignSideBand is zero.
+*
+c When astFindFrame or astConvert
+f When AST_FINDFRAME or AST_CONVERT
+* is used on two DSBSpecFrames (potentially describing different spectral
+* coordinate systems and/or sidebands), it returns a Mapping which can be
+* used to transform a position in one DSBSpecFrame into the corresponding
+* position in the other. The Mapping is made up of the following steps in
+* the indicated order:
+*
+* - If both DSBSpecFrames have a value of 1 for the AlignSideBand
+* attribute, map values from the target's current sideband (given by its
+* SideBand attribute) to the observed sideband (whether USB or LSB). If
+* the target already represents the observed sideband, this step will
+* leave the values unchanged. If either of the two DSBSpecFrames have a
+* value of zero for its AlignSideBand attribute, then this step is omitted.
+*
+* - Map the values from the spectral system of the target to the spectral
+* system of the template. This Mapping takes into account all the
+* inherited SpecFrame attributes such as System, StdOfRest, Unit, etc.
+*
+* - If both DSBSpecFrames have a value of 1 for the AlignSideBand
+* attribute, map values from the result's observed sideband to the
+* result's current sideband (given by its SideBand attribute). If the
+* result already represents the observed sideband, this step will leave
+* the values unchanged. If either of the two DSBSpecFrames have a value
+* of zero for its AlignSideBand attribute, then this step is omitted.
+
+* Applicability:
+* DSBSpecFrame
+* All DSBSpecFrames have this attribute.
+
+*att--
+*/
+/* The AlignSideBand value has a value of -1 when not set yielding a
+ default of 0. */
+astMAKE_TEST(DSBSpecFrame,AlignSideBand,( this->alignsideband != -1 ))
+astMAKE_CLEAR(DSBSpecFrame,AlignSideBand,alignsideband,-1)
+astMAKE_GET(DSBSpecFrame,AlignSideBand,int,-1,((this->alignsideband==-1)?0:this->alignsideband) )
+astMAKE_SET(DSBSpecFrame,AlignSideBand,int,alignsideband,(value?1:0))
+
+/* Copy constructor. */
+/* ----------------- */
+/* None needed */
+
+/* Destructor. */
+/* ----------- */
+/* None needed */
+
+/* Dump function. */
+/* -------------- */
+static void Dump( AstObject *this_object, AstChannel *channel, int *status ) {
+/*
+* Name:
+* Dump
+
+* Purpose:
+* Dump function for DSBSpecFrame objects.
+
+* Type:
+* Private function.
+
+* Synopsis:
+* void Dump( AstObject *this, AstChannel *channel, int *status )
+
+* Description:
+* This function implements the Dump function which writes out data
+* for the DSBSpecFrame class to an output Channel.
+
+* Parameters:
+* this
+* Pointer to the DSBSpecFrame whose data are being written.
+* channel
+* Pointer to the Channel to which the data are being written.
+* status
+* Pointer to the inherited status variable.
+*/
+
+/* Local Variables: */
+ AstDSBSpecFrame *this; /* Pointer to the DSBSpecFrame structure */
+ const char *cval; /* Attribute value */
+ const char *comm; /* Attribute comment */
+ double dval; /* Attribute value */
+ int ival; /* Attribute value */
+ int set; /* Is attribute set? */
+
+/* Check the global error status. */
+ if ( !astOK ) return;
+
+/* Obtain a pointer to the DSBSpecFrame structure. */
+ this = (AstDSBSpecFrame *) this_object;
+
+/* In the case of attributes, we first use the appropriate (private)
+ Test... member function to see if they are set. If so, we then use
+ the (private) Get... function to obtain the value to be written
+ out.
+
+ For attributes which are not set, we use the astGet... method to
+ obtain the value instead. This will supply a default value
+ (possibly provided by a derived class which over-rides this method)
+ which is more useful to a human reader as it corresponds to the
+ actual default attribute value. Since "set" will be zero, these
+ values are for information only and will not be read back. */
+
+/* DSBCentre */
+/* --------- */
+ set = TestDSBCentre( this, status );
+ dval = set ? GetDSBCentre( this, status ) : astGetDSBCentre( this );
+ astWriteDouble( channel, "DSBCen", set, 1, dval, "Central frequency (Hz topo)" );
+
+/* IF */
+/* -- */
+ set = TestIF( this, status );
+ dval = set ? GetIF( this, status ) : astGetIF( this );
+ astWriteDouble( channel, "IF", set, 1, dval, "Intermediate frequency (Hz)" );
+
+/* SideBand */
+/* -------- */
+ set = TestSideBand( this, status );
+ ival = set ? GetSideBand( this, status ) : astGetSideBand( this );
+ if( ival == LSB ) {
+ cval = "LSB";
+ comm = "Represents lower sideband";
+
+ } else if( ival == LO ) {
+ cval = "LO";
+ comm = "Represents offset from LO frequency";
+
+ } else {
+ cval = "USB";
+ comm = "Represents upper sideband";
+ }
+ astWriteString( channel, "SideBn", set, 1, cval, comm );
+
+/* AlignSideBand */
+/* ------------- */
+ set = TestAlignSideBand( this, status );
+ ival = set ? GetAlignSideBand( this, status ) : astGetAlignSideBand( this );
+ astWriteInt( channel, "AlSdBn", set, 1, ival, "Align sidebands?" );
+}
+
+/* Standard class functions. */
+/* ========================= */
+/* Implement the astIsADSBSpecFrame and astCheckDSBSpecFrame functions using the macros
+ defined for this purpose in the "object.h" header file. */
+astMAKE_ISA(DSBSpecFrame,SpecFrame)
+astMAKE_CHECK(DSBSpecFrame)
+
+AstDSBSpecFrame *astDSBSpecFrame_( const char *options, int *status, ...) {
+/*
+*++
+* Name:
+c astDSBSpecFrame
+f AST_DSBSPECFRAME
+
+* Purpose:
+* Create a DSBSpecFrame.
+
+* Type:
+* Public function.
+
+* Synopsis:
+c #include "dsbspecframe.h"
+c AstDSBSpecFrame *astDSBSpecFrame( const char *options, ... )
+f RESULT = AST_DSBSPECFRAME( OPTIONS, STATUS )
+
+* Class Membership:
+* DSBSpecFrame constructor.
+
+* Description:
+* This function creates a new DSBSpecFrame and optionally initialises its
+* attributes.
+*
+* A DSBSpecFrame is a specialised form of SpecFrame which represents
+* positions in a spectrum obtained using a dual sideband instrument.
+* Such an instrument produces a spectrum in which each point contains
+* contributions from two distinctly different frequencies, one from
+* the "lower side band" (LSB) and one from the "upper side band" (USB).
+* Corresponding LSB and USB frequencies are connected by the fact
+* that they are an equal distance on either side of a fixed central
+* frequency known as the "Local Oscillator" (LO) frequency.
+*
+* When quoting a position within such a spectrum, it is necessary to
+* indicate whether the quoted position is the USB position or the
+* corresponding LSB position. The SideBand attribute provides this
+* indication. Another option that the SideBand attribute provides is
+* to represent a spectral position by its topocentric offset from the
+* LO frequency.
+*
+* In practice, the LO frequency is specified by giving the distance
+* from the LO frequency to some "central" spectral position. Typically
+* this central position is that of some interesting spectral feature.
+* The distance from this central position to the LO frequency is known
+* as the "intermediate frequency" (IF). The value supplied for IF can
+* be a signed value in order to indicate whether the LO frequency is
+* above or below the central position.
+
+* Parameters:
+c options
+f OPTIONS = CHARACTER * ( * ) (Given)
+c Pointer to a null-terminated string containing an optional
+c comma-separated list of attribute assignments to be used for
+c initialising the new DSBSpecFrame. The syntax used is identical to
+c that for the astSet function and may include "printf" format
+c specifiers identified by "%" symbols in the normal way.
+f A character string containing an optional comma-separated
+f list of attribute assignments to be used for initialising the
+f new DSBSpecFrame. The syntax used is identical to that for the
+f AST_SET routine.
+c ...
+c If the "options" string contains "%" format specifiers, then
+c an optional list of additional arguments may follow it in
+c order to supply values to be substituted for these
+c specifiers. The rules for supplying these are identical to
+c those for the astSet function (and for the C "printf"
+c function).
+f STATUS = INTEGER (Given and Returned)
+f The global status.
+
+* Returned Value:
+c astDSBSpecFrame()
+f AST_DSBSPECFRAME = INTEGER
+* A pointer to the new DSBSpecFrame.
+
+* Notes:
+* - A null Object pointer (AST__NULL) will be returned if this
+c function is invoked with the AST error status set, or if it
+f function is invoked with STATUS set to an error value, or if it
+* should fail for any reason.
+*--
+*/
+
+/* Local Variables: */
+ astDECLARE_GLOBALS /* Pointer to thread-specific global data */
+ AstDSBSpecFrame *new; /* Pointer to new DSBSpecFrame */
+ va_list args; /* Variable argument list */
+
+/* Get a pointer to the thread specific global data structure. */
+ astGET_GLOBALS(NULL);
+
+/* Check the global status. */
+ if ( !astOK ) return NULL;
+
+/* Initialise the DSBSpecFrame, allocating memory and initialising the
+ virtual function table as well if necessary. */
+ new = astInitDSBSpecFrame( NULL, sizeof( AstDSBSpecFrame ), !class_init, &class_vtab,
+ "DSBSpecFrame" );
+
+/* If successful, note that the virtual function table has been
+ initialised. */
+ if ( astOK ) {
+ class_init = 1;
+
+/* Obtain the variable argument list and pass it along with the options string
+ to the astVSet method to initialise the new DSBSpecFrame's attributes. */
+ va_start( args, status );
+ astVSet( new, options, NULL, args );
+ va_end( args );
+
+/* If an error occurred, clean up by deleting the new object. */
+ if ( !astOK ) new = astDelete( new );
+ }
+
+/* Return a pointer to the new DSBSpecFrame. */
+ return new;
+}
+
+AstDSBSpecFrame *astDSBSpecFrameId_( const char *options, ... ) {
+/*
+* Name:
+* astDSBSpecFrameId_
+
+* Purpose:
+* Create a DSBSpecFrame.
+
+* Type:
+* Private function.
+
+* Synopsis:
+* #include "dsbspecframe.h"
+* AstDSBSpecFrame *astDSBSpecFrameId_( const char *options, ... )
+
+* Class Membership:
+* DSBSpecFrame constructor.
+
+* Description:
+* This function implements the external (public) interface to the
+* astDSBSpecFrame constructor function. It returns an ID value (instead
+* of a true C pointer) to external users, and must be provided
+* because astDSBSpecFrame_ has a variable argument list which cannot be
+* encapsulated in a macro (where this conversion would otherwise
+* occur).
+*
+* The variable argument list also prevents this function from
+* invoking astDSBSpecFrame_ directly, so it must be a re-implementation
+* of it in all respects, except for the final conversion of the
+* result to an ID value.
+
+* Parameters:
+* As for astDSBSpecFrame_.
+
+* Returned Value:
+* The ID value associated with the new DSBSpecFrame.
+*/
+
+/* Local Variables: */
+ astDECLARE_GLOBALS /* Pointer to thread-specific global data */
+ AstDSBSpecFrame *new; /* Pointer to new DSBSpecFrame */
+ va_list args; /* Variable argument list */
+
+ int *status; /* Pointer to inherited status value */
+
+/* Get a pointer to the inherited status value. */
+ status = astGetStatusPtr;
+
+/* Get a pointer to the thread specific global data structure. */
+ astGET_GLOBALS(NULL);
+
+/* Check the global status. */
+ if ( !astOK ) return NULL;
+
+/* Initialise the DSBSpecFrame, allocating memory and initialising the
+ virtual function table as well if necessary. */
+ new = astInitDSBSpecFrame( NULL, sizeof( AstDSBSpecFrame ), !class_init, &class_vtab,
+ "DSBSpecFrame" );
+
+/* If successful, note that the virtual function table has been
+ initialised. */
+ if ( astOK ) {
+ class_init = 1;
+
+/* Obtain the variable argument list and pass it along with the options string
+ to the astVSet method to initialise the new DSBSpecFrame's attributes. */
+ va_start( args, options );
+ astVSet( new, options, NULL, args );
+ va_end( args );
+
+/* If an error occurred, clean up by deleting the new object. */
+ if ( !astOK ) new = astDelete( new );
+ }
+
+/* Return an ID value for the new DSBSpecFrame. */
+ return astMakeId( new );
+}
+
+AstDSBSpecFrame *astInitDSBSpecFrame_( void *mem, size_t size, int init,
+ AstDSBSpecFrameVtab *vtab, const char *name, int *status ) {
+/*
+*+
+* Name:
+* astInitDSBSpecFrame
+
+* Purpose:
+* Initialise a DSBSpecFrame.
+
+* Type:
+* Protected function.
+
+* Synopsis:
+* #include "dsbspecframe.h"
+* AstDSBSpecFrame *astInitDSBSpecFrame( void *mem, size_t size, int init,
+* AstDSBSpecFrameVtab *vtab, const char *name )
+
+* Class Membership:
+* DSBSpecFrame initialiser.
+
+* Description:
+* This function is provided for use by class implementations to initialise
+* a new DSBSpecFrame object. It allocates memory (if necessary) to accommodate
+* the DSBSpecFrame plus any additional data associated with the derived class.
+* It then initialises a DSBSpecFrame structure at the start of this memory. If
+* the "init" flag is set, it also initialises the contents of a virtual
+* function table for a DSBSpecFrame at the start of the memory passed via the
+* "vtab" parameter.
+
+* Parameters:
+* mem
+* A pointer to the memory in which the DSBSpecFrame is to be initialised.
+* This must be of sufficient size to accommodate the DSBSpecFrame data
+* (sizeof(DSBSpecFrame)) plus any data used by the derived class. If a value
+* of NULL is given, this function will allocate the memory itself using
+* the "size" parameter to determine its size.
+* size
+* The amount of memory used by the DSBSpecFrame (plus derived class data).
+* This will be used to allocate memory if a value of NULL is given for
+* the "mem" parameter. This value is also stored in the DSBSpecFrame
+* structure, so a valid value must be supplied even if not required for
+* allocating memory.
+* init
+* A logical flag indicating if the DSBSpecFrame's virtual function table is
+* to be initialised. If this value is non-zero, the virtual function
+* table will be initialised by this function.
+* vtab
+* Pointer to the start of the virtual function table to be associated
+* with the new DSBSpecFrame.
+* name
+* Pointer to a constant null-terminated character string which contains
+* the name of the class to which the new object belongs (it is this
+* pointer value that will subsequently be returned by the astGetClass
+* method).
+
+* Returned Value:
+* A pointer to the new DSBSpecFrame.
+
+* Notes:
+* - A null pointer will be returned if this function is invoked with the
+* global error status set, or if it should fail for any reason.
+*-
+*/
+
+/* Local Variables: */
+ AstDSBSpecFrame *new; /* Pointer to new DSBSpecFrame */
+
+/* Check the global status. */
+ if ( !astOK ) return NULL;
+
+/* If necessary, initialise the virtual function table. */
+ if ( init ) astInitDSBSpecFrameVtab( vtab, name );
+
+/* Initialise. */
+ new = NULL;
+
+/* Initialise a SpecFrame structure (the parent class) as the first component
+ within the DSBSpecFrame structure, allocating memory if necessary. Specify that
+ the SpecFrame should be defined in both the forward and inverse directions. */
+ new = (AstDSBSpecFrame *) astInitSpecFrame( mem, size, 0,
+ (AstSpecFrameVtab *) vtab, name );
+ if ( astOK ) {
+
+/* Initialise the DSBSpecFrame data. */
+/* --------------------------------- */
+ new->dsbcentre = AST__BAD;
+ new->ifr = AST__BAD;
+ new->sideband = BADSB;
+ new->alignsideband = -1;
+
+/* If an error occurred, clean up by deleting the new DSBSpecFrame. */
+ if ( !astOK ) new = astDelete( new );
+ }
+
+/* Return a pointer to the new DSBSpecFrame. */
+ return new;
+}
+
+AstDSBSpecFrame *astLoadDSBSpecFrame_( void *mem, size_t size,
+ AstDSBSpecFrameVtab *vtab, const char *name,
+ AstChannel *channel, int *status ) {
+/*
+*+
+* Name:
+* astLoadDSBSpecFrame
+
+* Purpose:
+* Load a DSBSpecFrame.
+
+* Type:
+* Protected function.
+
+* Synopsis:
+* #include "dsbspecframe.h"
+* AstDSBSpecFrame *astLoadDSBSpecFrame( void *mem, size_t size,
+* AstDSBSpecFrameVtab *vtab, const char *name,
+* AstChannel *channel )
+
+* Class Membership:
+* DSBSpecFrame loader.
+
+* Description:
+* This function is provided to load a new DSBSpecFrame using data read
+* from a Channel. It first loads the data used by the parent class
+* (which allocates memory if necessary) and then initialises a
+* DSBSpecFrame structure in this memory, using data read from the input
+* Channel.
+*
+* If the "init" flag is set, it also initialises the contents of a
+* virtual function table for a DSBSpecFrame at the start of the memory
+* passed via the "vtab" parameter.
+
+
+* Parameters:
+* mem
+* A pointer to the memory into which the DSBSpecFrame is to be
+* loaded. This must be of sufficient size to accommodate the
+* DSBSpecFrame data (sizeof(DSBSpecFrame)) plus any data used by derived
+* classes. If a value of NULL is given, this function will
+* allocate the memory itself using the "size" parameter to
+* determine its size.
+* size
+* The amount of memory used by the DSBSpecFrame (plus derived class
+* data). This will be used to allocate memory if a value of
+* NULL is given for the "mem" parameter. This value is also
+* stored in the DSBSpecFrame structure, so a valid value must be
+* supplied even if not required for allocating memory.
+*
+* If the "vtab" parameter is NULL, the "size" value is ignored
+* and sizeof(AstDSBSpecFrame) is used instead.
+* vtab
+* Pointer to the start of the virtual function table to be
+* associated with the new DSBSpecFrame. If this is NULL, a pointer
+* to the (static) virtual function table for the DSBSpecFrame class
+* is used instead.
+* name
+* Pointer to a constant null-terminated character string which
+* contains the name of the class to which the new object
+* belongs (it is this pointer value that will subsequently be
+* returned by the astGetClass method).
+*
+* If the "vtab" parameter is NULL, the "name" value is ignored
+* and a pointer to the string "DSBSpecFrame" is used instead.
+
+* Returned Value:
+* A pointer to the new DSBSpecFrame.
+
+* Notes:
+* - A null pointer will be returned if this function is invoked
+* with the global error status set, or if it should fail for any
+* reason.
+*-
+*/
+
+/* Local Constants. */
+ astDECLARE_GLOBALS /* Pointer to thread-specific global data */
+#define KEY_LEN 50 /* Maximum length of a keyword */
+
+/* Local Variables: */
+ AstDSBSpecFrame *new; /* Pointer to the new DSBSpecFrame */
+ char *text; /* Pointer to string value */
+
+/* Get a pointer to the thread specific global data structure. */
+ astGET_GLOBALS(channel);
+
+/* Initialise. */
+ new = NULL;
+
+/* Check the global error status. */
+ if ( !astOK ) return new;
+
+/* If a NULL virtual function table has been supplied, then this is
+ the first loader to be invoked for this DSBSpecFrame. In this case the
+ DSBSpecFrame belongs to this class, so supply appropriate values to be
+ passed to the parent class loader (and its parent, etc.). */
+ if ( !vtab ) {
+ size = sizeof( AstDSBSpecFrame );
+ vtab = &class_vtab;
+ name = "DSBSpecFrame";
+
+/* If required, initialise the virtual function table for this class. */
+ if ( !class_init ) {
+ astInitDSBSpecFrameVtab( vtab, name );
+ class_init = 1;
+ }
+ }
+
+/* Invoke the parent class loader to load data for all the ancestral
+ classes of the current one, returning a pointer to the resulting
+ partly-built DSBSpecFrame. */
+ new = astLoadSpecFrame( mem, size, (AstSpecFrameVtab *) vtab, name,
+ channel );
+ if ( astOK ) {
+
+/* Read input data. */
+/* ================ */
+/* Request the input Channel to read all the input data appropriate to
+ this class into the internal "values list". */
+ astReadClassData( channel, "DSBSpecFrame" );
+
+/* Now read each individual data item from this list and use it to
+ initialise the appropriate instance variable(s) for this class. */
+
+/* In the case of attributes, we first read the "raw" input value,
+ supplying the "unset" value as the default. If a "set" value is
+ obtained, we then use the appropriate (private) Set... member
+ function to validate and set the value properly. */
+
+/* DSBCentre */
+/* --------- */
+ new->dsbcentre = astReadDouble( channel, "dsbcen", AST__BAD );
+ if ( TestDSBCentre( new, status ) ) SetDSBCentre( new, new->dsbcentre, status );
+
+/* IF */
+/* -- */
+ new->ifr = astReadDouble( channel, "if", AST__BAD );
+ if ( TestIF( new, status ) ) SetIF( new, new->ifr, status );
+
+/* SideBand */
+/* -------- */
+ text = astReadString( channel, "sidebn", " " );
+ if( astOK ) {
+ if( !strcmp( text, " " ) ) {
+ new->sideband = BADSB;
+ } else if( !strcmp( text, "USB" ) ) {
+ new->sideband = USB;
+ } else if( !strcmp( text, "LSB" ) ) {
+ new->sideband = LSB;
+ } else if( !strcmp( text, "LO" ) ) {
+ new->sideband = LO;
+ } else {
+ astError( AST__ATTIN, "astRead(%s): Invalid SideBand description "
+ "\"%s\".", status, astGetClass( channel ), text );
+ }
+ if ( TestSideBand( new, status ) ) SetSideBand( new, new->sideband, status );
+ text = astFree( text );
+ }
+
+/* AlignSideBand */
+/* ------------- */
+ new->alignsideband = astReadInt( channel, "alsdbn", -1 );
+ if( TestAlignSideBand( new, status ) ) SetAlignSideBand( new, new->alignsideband, status );
+
+/* If an error occurred, clean up by deleting the new DSBSpecFrame. */
+ if ( !astOK ) new = astDelete( new );
+ }
+
+/* Return the new DSBSpecFrame pointer. */
+ return new;
+}
+
+/* Virtual function interfaces. */
+/* ============================ */
+/* These provide the external interface to the virtual functions defined by
+ this class. Each simply checks the global error status and then locates and
+ executes the appropriate member function, using the function pointer stored
+ in the object's virtual function table (this pointer is located using the
+ astMEMBER macro defined in "object.h").
+
+ Note that the member function may not be the one defined here, as it may
+ have been over-ridden by a derived class. However, it should still have the
+ same interface. */
+
+double astGetImagFreq_( AstDSBSpecFrame *this, int *status ) {
+ if ( !astOK ) return AST__BAD;
+ return (**astMEMBER(this,DSBSpecFrame,GetImagFreq))( this, status );
+}
+
+
+
+
+
+