Starlink-AST

 view release on metacpan or  search on metacpan

ast/src/specframe.c  view on Meta::CPAN

*  History:
*     4-NOV-2002 (DSB):
*        Original version.
*     2-FEB-2005 (DSB):
*        - Avoid using astStore to allocate more storage than is supplied
*        in the "data" pointer. This can cause access violations since
*        astStore will then read beyond the end of the "data" area.
*     22-MAR-2005 (DSB):
*        - Re-structure MakeSpecMapping in order to avoid unnecessary
*        access to SpecFrame attributes which may not be set, and to
*        check that all required attributes have been set if UseDefs is
*        zero.
*     23-MAR-2005 (DSB):
*        - Added missing rest frames to SorEqual.
*     12-AUG-2005 (DSB):
*        - Remove GeoLon and GeoLat attributes. Use the new ObsLon and
*        ObsLat attributes in the parent Frame class instead. Note, for
*        backward compatibility the public attribute accessors and the
*        astLoadSpecFrame functions still recogonise GeoLon and GeoLat,
*        but use the ObsLat/ObsLon attributes internally.
*     14-FEB-2006 (DSB):
*        Override astGetObjSize.
*     1-MAR-2006 (DSB):
*        Replace astSetPermMap within DEBUG blocks by astBeginPM/astEndPM.
*     6-OCT-2006 (DSB):
*        Guard against annulling null pointers in subFrame.
*     18-OCT-2006 (DSB):
*        Added SpecOrigin and AlignSpecOffset attributes.
*     23-OCT-2006 (DSB):
*        Fix memory leak caused by addition of SpecOrigin and AlignSpecOffset
*        attributes.
*     15-NOV-2006 (DSB):
*        Only write out SpecOrigin if it is not bad.
*     8-JAN-2006 (DSB):
*        - SubFrame: Copy the SourceSystem and SourceStdOfRest attributes
*        to the System and StdOfRest attributes of the "align_frm"
*        SpecFrame before calling MakeSpecMapping. Previously, the
*        values assigned to  SourceSystem and SourceStdOfRest were
*        ignored, and alignment was always performed in the templates System
*        and StdOfRest.
*        - MakeSpecMapping: Correct logic used to decide if steps 2 and 7
*        can be cancelled.
*        - OriginSystem: Clear the AlignSpecOffset attributes before
*        finding the Mapping between the old and new Systems.
*     16-JAN-2006 (DSB):
*        Fix bug in Dump that caused SrcVRF not to be written out.
*     31-JAN-2007 (DSB):
*        Modified so that a SpecFrame can be used as a template to find a
*        SpecFrame contained within a CmpFrame. This involves changes in
*        Match and the removal of the local versions of SetMaxAxes and
*        SetMinAxes.
*     8-AUG-2007 (DSB):
*        Changed Overlay to avoid the possibility of making permanent
*        changes to the supplied template Frame.
*     3-SEP-2007 (DSB):
*        In SubFrame, since AlignSystem is extended by the SpecFrame class
*        it needs to be cleared before invoking the parent SubFrame
*        method in cases where the result Frame is not a SkyFrame.
*     2-OCT-2007 (DSB):
*        In Overlay, clear AlignSystem as well as System before calling
*        the parent overlay method.
*     4-SEP-2009 (DSB):
*        In MakeSpecMapping, in order to produce alignment that is not
*        affected by the epoch or reference position, make the alignment
*        frame adapt to the epoch and reference position of the target
*        and result Frames.
*     14-SEP-2009 (DSB):
*        In MakeSpecMapping, extend the 4-SEP-2009 fix to cover other
*        attributes that define the available rest frames (e.g.
*        SourceVRF, SourceVel, ObsLat, ObsLon, ObsAlt).
*     16-SEP-2009 (DSB):
*        In MakeSpecMapping, retain the original alignment frame attribute
*        values if we are restoring the integrity of a FrameSet.
*     29-APR-2011 (DSB):
*        Prevent astFindFrame from matching a subclass template against a
*        superclass target.
*     11-MAR-2020 (DSB):
*         In Overlay, only clear the results Units, Label, etc if the result
*         and template Systems differ AND the template System has been set
*         explicitly.
*     27-APR-2020 (DSB):
*         Correct "Heliographic" to "heliocentric".
*class--
*/

/* 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 SpecFrame

/* Define the first and last acceptable System values. */
#define FIRST_SYSTEM AST__FREQ
#define LAST_SYSTEM AST__VREL

/* Define the first and last acceptable StdOfRest values. */
#define FIRST_SOR AST__TPSOR
#define LAST_SOR AST__SCSOR

/* The supported spectral coordinate systems fall into two groups;
   "relative", and "absolute". The relative systems define each axis
   value with respect to the rest frequency, whereas the absolute systems
   have axis values which do not depend on the rest frequency. Define a
   macro which returns one if the specified system is absolute, and zero
   otherwise. */
#define ABS_SYSTEM(sys) \
      ( ( sys == AST__ENERGY || \
          sys == AST__WAVENUM || \
          sys == AST__WAVELEN || \
          sys == AST__AIRWAVE || \
          sys == AST__FREQ ) ? 1 : 0 )

/* Define other numerical constants for use in this module. */
#define GETATTRIB_BUFF_LEN 50
#define GETLABEL_BUFF_LEN 200
#define GETSYMBOL_BUFF_LEN 20
#define GETTITLE_BUFF_LEN 200

/* Header files. */
/* ============= */
/* Interface definitions. */
/* ---------------------- */

#include "globals.h"             /* Thread-safe global data access */
#include "error.h"               /* Error reporting facilities */
#include "memory.h"              /* Memory allocation facilities */
#include "unit.h"                /* Units management facilities */
#include "globals.h"             /* Thread-safe global data access */
#include "object.h"              /* Base Object class */
#include "specmap.h"             /* Spectral coordinate Mappings */
#include "frame.h"               /* Parent Frame class */
#include "skyframe.h"            /* Celestial coordinate frames */
#include "specframe.h"           /* Interface definition for this class */
#include "mapping.h"             /* Coordinate Mappings */
#include "cmpmap.h"              /* Compound Mappings */
#include "unitmap.h"             /* Unit Mappings */
#include "pal.h"                 /* SlaLib interface */
#include "shiftmap.h"            /* Change of origin */

/* Error code definitions. */
/* ----------------------- */
#include "ast_err.h"             /* AST error codes */

/* C header files. */
/* --------------- */
#include <stdarg.h>
#include <stdio.h>
#include <string.h>
#include <ctype.h>
#include <stddef.h>
#include <math.h>
#include <limits.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 used or extended by this
   class. */
static size_t (* parent_getobjsize)( AstObject *, int * );
static AstSystemType (* parent_getalignsystem)( AstFrame *, int * );
static AstSystemType (* parent_getsystem)( AstFrame *, int * );
static const char *(* parent_getattrib)( AstObject *, const char *, int * );
static const char *(* parent_getdomain)( AstFrame *, int * );
static const char *(* parent_getlabel)( AstFrame *, int, int * );
static const char *(* parent_getsymbol)( AstFrame *, int, int * );
static const char *(* parent_gettitle)( AstFrame *, int * );
static const char *(* parent_getunit)( 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_setunit)( AstFrame *, int, const char *, int * );
static void (* parent_clearattrib)( AstObject *, const char *, int * );
static void (* parent_overlay)( AstFrame *, const int *, AstFrame *, int * );
static void (* parent_setattrib)( AstObject *, const char *, int * );
static void (* parent_setsystem)( AstFrame *, AstSystemType, int * );
static void (* parent_clearsystem)( AstFrame *, int * );
static void (* parent_clearunit)( AstFrame *, int, int * );

/* Define a variable to hold a SkyFrame which will be used for formatting
   and unformatting sky positions, etc. */
static AstSkyFrame *skyframe;

/* 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; \
   globals->GetSymbol_Buff[ 0 ] = 0; \
   globals->GetTitle_Buff[ 0 ] = 0; \

/* Create the function that initialises global data for this module. */
astMAKE_INITGLOBALS(SpecFrame)

/* Define macros for accessing each item of thread specific global data. */
#define class_init astGLOBAL(SpecFrame,Class_Init)
#define class_vtab astGLOBAL(SpecFrame,Class_Vtab)
#define getattrib_buff astGLOBAL(SpecFrame,GetAttrib_Buff)
#define getlabel_buff astGLOBAL(SpecFrame,GetLabel_Buff)
#define getsymbol_buff astGLOBAL(SpecFrame,GetSymbol_Buff)
#define gettitle_buff astGLOBAL(SpecFrame,GetTitle_Buff)



static pthread_mutex_t mutex2 = PTHREAD_MUTEX_INITIALIZER;
#define LOCK_MUTEX2 pthread_mutex_lock( &mutex2 );
#define UNLOCK_MUTEX2 pthread_mutex_unlock( &mutex2 );

/* If thread safety is not needed, declare and initialise globals at static
   variables. */
#else

/* Buffer returned by GetAttrib. */
static char getattrib_buff[ 51 ];

/* Default GetLabel string buffer */
static char getlabel_buff[ 201 ];

/* Default GetSymbol buffer */
static char getsymbol_buff[ 21 ];

/* Default Title string buffer */
static char gettitle_buff[ 201 ];


/* Define the class virtual function table and its initialisation flag
   as static variables. */
static AstSpecFrameVtab class_vtab;   /* Virtual function table */
static int class_init = 0;       /* Virtual function table initialised? */

#define LOCK_MUTEX2

ast/src/specframe.c  view on Meta::CPAN

   vtab->ClearSpecOrigin = ClearSpecOrigin;
   vtab->TestSpecOrigin = TestSpecOrigin;
   vtab->GetSpecOrigin = GetSpecOrigin;
   vtab->SetSpecOrigin = SetSpecOrigin;

   vtab->TestAlignSpecOffset = TestAlignSpecOffset;
   vtab->SetAlignSpecOffset = SetAlignSpecOffset;
   vtab->GetAlignSpecOffset = GetAlignSpecOffset;
   vtab->ClearAlignSpecOffset = ClearAlignSpecOffset;

/* 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_getobjsize = object->GetObjSize;
   object->GetObjSize = GetObjSize;

   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_getsystem = frame->GetSystem;
   frame->GetSystem = GetSystem;
   parent_setsystem = frame->SetSystem;
   frame->SetSystem = SetSystem;
   parent_clearsystem = frame->ClearSystem;
   frame->ClearSystem = ClearSystem;

   parent_getalignsystem = frame->GetAlignSystem;
   frame->GetAlignSystem = GetAlignSystem;

   parent_getlabel = frame->GetLabel;
   frame->GetLabel = GetLabel;

   parent_getsymbol = frame->GetSymbol;
   frame->GetSymbol = GetSymbol;

   parent_gettitle = frame->GetTitle;
   frame->GetTitle = GetTitle;

   parent_clearunit = frame->ClearUnit;
   frame->ClearUnit = ClearUnit;

   parent_getunit = frame->GetUnit;
   frame->GetUnit = GetUnit;

   parent_setunit = frame->SetUnit;
   frame->SetUnit = SetUnit;

   parent_match = frame->Match;
   frame->Match = Match;

   parent_overlay = frame->Overlay;
   frame->Overlay = Overlay;

   parent_subframe = frame->SubFrame;
   frame->SubFrame = SubFrame;

/* Store replacement pointers for methods which will be over-ridden by new
   member functions implemented here. */
   frame->GetActiveUnit = GetActiveUnit;
   frame->TestActiveUnit = TestActiveUnit;
   frame->ValidateSystem = ValidateSystem;
   frame->SystemString = SystemString;
   frame->SystemCode = SystemCode;

/* Declare the copy constructor, destructor and class dump
   function. */
   astSetCopy( vtab, Copy );
   astSetDelete( vtab, Delete );
   astSetDump( vtab, Dump, "SpecFrame",
               "Description of spectral coordinate system" );

/* 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 MakeSpecMapping( AstSpecFrame *target, AstSpecFrame *result,
                            AstSpecFrame *align_frm, int report,
                            AstMapping **map, int *status ) {
/*
*  Name:
*     MakeSpecMapping

*  Purpose:
*     Generate a Mapping between two SpecFrames.

*  Type:
*     Private function.

*  Synopsis:
*     #include "specframe.h"
*     int MakeSpecMapping( AstSpecFrame *target, AstSpecFrame *result,
*                          AstSpecFrame *align_frm, int report,
*                          AstMapping **map, int *status ) {

*  Class Membership:
*     SpecFrame member function.

*  Description:
*     This function takes two SpecFrames and generates a Mapping that
*     converts between them, taking account of differences in their
*     coordinate systems, rest frequency, standard of rest, etc.
*
*     In order to cut down the number of transformations to be considered,
*     the scheme works by first converting from the target frame to an
*     "alignment" Frame, using the attributes of the target to define the
*     transformation. A transformation is then found from the alignment

ast/src/specframe.c  view on Meta::CPAN

   int target_axis0;             /* Index of SpecFrame axis in the target */
   int target_naxes;             /* Number of target axes */

/* 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 SpecFrame structure. */
   template = (AstSpecFrame *) template_frame;

/* Obtain the number of axes in the target Frame. */
   target_naxes = astGetNaxes( target );

/* The first criterion for a match is that the template matches as a
   Frame class object. This ensures that the number of axes (1) and
   domain, 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, annul the returned objects, which are not
   needed, but keep the memory allocated for the axis association
   arrays, which we will re-use. */
   if ( astOK && match ) {
      *map = astAnnul( *map );
      *result = astAnnul( *result );
   }

/* If OK so far, obtain pointers to the primary Frames which underlie
   all target axes. Stop when a SpecFrame axis is found. */
   if ( match && astOK ) {
      match = 0;
      for( iaxis = 0; iaxis < target_naxes; iaxis++ ) {
         astPrimaryFrame( target, iaxis, &frame0, &iaxis0 );
         if( astIsASpecFrame( frame0 ) ) {
            frame0 = astAnnul( frame0 );
            target_axis0 = iaxis;
            match = 1;
            break;
         } else {
            frame0 = astAnnul( frame0 );
         }
      }

   }

/* Check at least one SpecFrame axis was found it the target. Store the
   axis associataions. */
   if( match && astOK ) {
      (*template_axes)[ 0 ] = 0;
      (*target_axes)[ 0 ] = target_axis0;

/* Use the target's "astSubFrame" method to create a new Frame (the
   result Frame) with copies of the target axes in the required
   order. 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 );

   }

/* 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 ) {
      *template_axes = astFree( *template_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 OriginStdOfRest( AstSpecFrame *this, AstStdOfRestType newsor,
                             const char *method, int *status ){
/*
*  Name:
*     OriginStdOfRest

*  Purpose:
*     Convert the SpecOrigin in a SpecFrame to a new rest frame.

*  Type:
*     Private function.

*  Synopsis:
*     #include "specframe.h"
*     void OriginStdOfRest( AstSpecFrame *this, AstStdOfRestType newsor,
*                           const char *method, int *status )

*  Class Membership:
*     SpecFrame member function

*  Description:
*     This function converts the value of the SpecOrigin attribute stored
*     within a supplied SpecFrame from the rest frame currently associated
*     with the SpecFrame, to the new rest frame indicated by "newsor".

*  Parameters:
*     this
*        Point to the SpecFrame. On entry, the SpecOrigin value is
*        assumed to refer to the re st frame given by the astGetStdOfRest
*        method. On exit, the SpecOrigin value refers to the rest frame
*        supplied in "newsor". The StdOfRest attribute of the SpecFrame
*        should then be modified in order to keep things consistent.
*     newsor
*        The rest frame to which the SpecOrigin value stored within "this"
*        should refer on exit.
*     method
*        Pointer to a string holding the name of the method to be

ast/src/specframe.c  view on Meta::CPAN

/* Take a copy of the original SpecFrame and ensure the Units, SpecOrigin and
   AlignSpecOffset attributes are cleared. */
         sf1 = astCopy( this );
         astClearUnit( sf1, 0 );
         astClearSpecOrigin( sf1 );
         astClearAlignSpecOffset( sf1 );

/* Take another copy of the SpecFrame and set the old system. */
         sf2 = astCopy( sf1 );
         astSetSystem( sf2, oldsys );

/* Create a Mapping to perform the rest frame change, then use it to convert
   the value to the current system. */
         fs = astConvert( sf2, sf1, "" );
         neworigin = AST__BAD;
         if( fs ) {
            astTran1( fs, 1, &origin, 1, &neworigin );
            fs = astAnnul( fs );
         }

/* Free resources */
         sf1 = astAnnul( sf1 );
         sf2 = astAnnul( sf2 );

/* If succesful, store it in "this". */
         if( neworigin != AST__BAD ) {
            astSetSpecOrigin( this, neworigin );

         } else if( astOK ) {
            astError( AST__ATSER, "%s(%s): Cannot convert the SpecOrigin "
                      "value to a different spectral system.", status, method,
                      astGetClass( this ) );
         }
      }
   }
}


static void Overlay( AstFrame *template, const int *template_axes,
                     AstFrame *result, int *status ) {
/*
*  Name:
*     Overlay

*  Purpose:
*     Overlay the attributes of a template SpecFrame 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:
*     SpecFrame member function (over-rides the protected astOverlay method
*     inherited from the Frame class).

*  Description:
*     This function overlays attributes of a SpecFrame (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 SpecFrame 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 SpecFrame, 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 SpecFrame, or from a class derived from it, then attributes may
*     exist in the template SpecFrame which do not exist in the result Frame.
*     In this case, these attributes will not be transferred.
*/

/* Local Variables: */
   AstFrame *templt;             /* Copy of supplied template Frame */
   AstSystemType new_system;     /* Code identifying new cordinates */
   AstSystemType old_system;     /* Code identifying old coordinates */
   const char *method;           /* Pointer to method string */
   const char *new_class;        /* Pointer to template class string */
   const char *old_class;        /* Pointer to result class string */
   int specframe;                /* Result Frame is a SpecFrame? */

/* Check the global error status. */
   if ( !astOK ) return;

/* Initialise strings used in error messages. */
   new_class = astGetClass( template );
   old_class = astGetClass( result );
   method = "astOverlay";

/* Get the old and new systems. */
   old_system = astGetSystem( result );
   new_system = astGetSystem( template );

/* It may be necessary to make temporary changes to the template Frame
   below. In order to ensure that we make no permanent changes to the
   supplied frame, we will, if necessary, take a deep copy of the
   supplied Frame, storing a pointer to the copy in "templt". If it is
   not necessary to make any changes to the template, we still want
   "templt" to hold a usable pointer, so we initialise it now to hold a
   clone of the supplied pointer. This pointer will be replaced by a
   pointer to a deep copy (if required) below. */
   templt = astClone( template );

/* If the result Frame is a SpecFrame, we must test to see if overlaying its
   System attribute will change the type of coordinate system it describes.
   Determine the value of this attribute for the result and template
   SpecFrames. */
   specframe = astIsASpecFrame( result );
   if( specframe ) {

/* If the coordinate system will change, any value already set for the result
   SpecFrame's Title will no longer be appropriate, so clear it. But note
   the coordinate system will change only if the system values are
   different AND the system has been set explicitly in the template. If
   the system has not been set explicitly in the template, the result will
   retain its original system value. */
      if ( new_system != old_system && astTestSystem( template ) ) {
         astClearTitle( result );

/* If the systems have the same default units, we can retain the current
   Unit value. */
         if( strcmp( DefUnit( new_system, method, new_class, status ),
                     DefUnit( old_system, method, old_class, status ) ) ) {
            astClearUnit( result, 0 );
         }

/* If necessary, clear inappropriate values for all those axis attributes
   whose access functions are over-ridden by this class (these access functions
   will then provide suitable defaults appropriate to the new coordinate system
   instead). */
         astClearLabel( result, 0 );
         astClearSymbol( result, 0 );
      }

/* If the result Frame is not a SpecFrame, we must temporarily clear the
   System and AlignSystem values since the values used by this class
   are only appropriate to this class. Use a deep copy to avoid the danger
   of making any permanent changes to the suppied Frame. */
   } else {
      if( astTestSystem( template ) ) {
         templt = astAnnul( templt );
         templt = astCopy( template );
         astClearSystem( templt );
         astClearAlignSystem( templt );
      }
   }

/* Invoke the parent class astOverlay method to transfer attributes inherited
   from the parent class. */
   (*parent_overlay)( templt, template_axes, result, status );

/* Check if the result Frame is a SpecFrame or from a class derived from
   SpecFrame. If not, we cannot transfer SpecFrame attributes to it as it is
   insufficiently specialised. In this case simply omit these attributes. */
   if ( specframe && 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 SpecFrame attribute in turn. Note,
   SourceVRF must be overlayed before SourceVel. Otherwise the stored value
   for SourceVel would be changed from the default SourceVRF to the specified
   SourceVRF when SourceVRF was overlayed. */
      OVERLAY(AlignStdOfRest)
      OVERLAY(AlignSpecOffset);
      OVERLAY(RefDec)
      OVERLAY(RefRA)
      OVERLAY(RestFreq)
      OVERLAY(SourceSys)
      OVERLAY(SourceVRF)
      OVERLAY(SourceVel)
      OVERLAY(StdOfRest)
      OVERLAY(SpecOrigin)
   }

/* Free resources */
   templt = astAnnul( templt );

/* 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 SpecFrame.

*  Type:
*     Private function.

*  Synopsis:
*     #include "specframe.h"
*     void SetAttrib( AstObject *this, const char *setting, int *status )

*  Class Membership:
*     SpecFrame member function (extends the astSetAttrib method inherited from
*     the Mapping class).

*  Description:
*     This function assigns an attribute value for a SpecFrame, 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 SpecFrame.
*     setting
*        Pointer to a null terminated string specifying the new attribute
*        value.
*     status
*        Pointer to the inherited status variable.

ast/src/specframe.c  view on Meta::CPAN

   case AST__HLSOR:
      result = "Heliocentric";
      break;

   case AST__LDSOR:
      result = "LSRD";
      break;

   case AST__LKSOR:
      result = "LSRK";
      break;

   case AST__LGSOR:
      result = "Local_group";
      break;

   case AST__GLSOR:
      result = "Galactic";
      break;

   case AST__SCSOR:
      result = "Source";
      break;

   }

/* Return the result pointer. */
   return result;
}

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 SpecFrame and convert to the new coordinate
*     system.

*  Type:
*     Private function.

*  Synopsis:
*     #include "specframe.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:
*     SpecFrame member function (over-rides the protected astSubFrame
*     method inherited from the Frame class).

*  Description:
*     This function selects a requested sub-set (or super-set) of the axes
*     from a "target" SpecFrame 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 SpecFrame, 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 SpecFrame. 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
*        SpecFrame 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
*     SpecFrame object. This results in another object of the same class
*     only if the single SpecFrame axis is selected exactly once.
*     Otherwise, the result is a Frame class object which inherits the
*     SpecFrame's axis information (if appropriate) but none of the other
*     properties of a SpecFrame.
*     -  In the event that a SpecFrame 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: */
   AstSpecFrame *target;      /* Pointer to the SpecFrame structure */
   AstSpecFrame *temp;        /* Pointer to copy of target SpecFrame */
   AstSpecFrame *align_frm;   /* Frame in which to align the SpecFrames */
   int match;                 /* Coordinate conversion is possible? */
   int report;                /* Report errors if SpecFrames cannot be aligned? */

/* Initialise the returned values. */
   *map = NULL;
   *result = NULL;
   match = 0;

/* Check the global error status. */
   if ( !astOK ) return match;

/* Obtain a pointer to the target SpecFrame structure. */
   target = (AstSpecFrame *) target_frame;

/* Result is a SpecFrame. */
/* -------------------------- */
/* Check if the result Frame is to have one axis obtained by selecting
   the single target SpecFrame axis. If so, the result will also be
   a SpecFrame. */
   if ( ( result_naxes == 1 ) && ( target_axes[ 0 ] == 0 ) ) {

/* Form the result from a copy of the target. */
      *result = astCopy( target );

/* Initialise a flag to indicate that MakeSpecMapping should not report
   errors if no Mapping can be created. */
      report = 0;

/* If required, overlay the template attributes on to the result SpecFrame.
   Also get the system and standard of rest in which to align the two
   SpecFrames. These are the values from the template (if there is a
   template). */
      if ( template ) {
         astOverlay( template, template_axes, *result );
         if( astIsASpecFrame( template ) ) {
            align_frm = astCopy( template );

/* Since we now know that both the template and target are SpecFrames, it
   should usually be possible to convert betwen them. If conversion is
   *not* possible (fpr instance if no rest frequency is availalbe, etc)
   then the user will probably be interested in knowing the reason why
   conversion is not possible. Therefore, indicate that MakeSpecMapping
   should report errors if no Mapping can be created. */
            report = 1;

         } else {
            align_frm = astCopy( target );
         }

/* If no template was supplied, align in the System and StdOfRest of the
   target. */
      } else {
         VerifyAttrs( target, "convert between different spectral systems",
                   "StdOfRest", "astMatch", status );
         align_frm = astCopy( target );
      }

/* The MakeSpecMapping function uses the System and StdOfRest attributes to
   define the alignment frame. But the AlignSystem and AlignStdOfRest
   attributes should be used for this purpose. Therefore, copy the values
   of the AlignSystem and AlignStdOfRest attributes to the System and
   StdOfRest attribute. */
      astSetSystem( align_frm, astGetAlignSystem( align_frm ) );
      astSetStdOfRest( align_frm, astGetAlignStdOfRest( align_frm ) );

/* Generate a Mapping that takes account of changes in the sky coordinate
   system (equinox, epoch, etc.) between the target SpecFrame and the result
   SpecFrame. If this Mapping can be generated, set "match" to indicate that
   coordinate conversion is possible. If the template is a specframe,
   report errors if a match is not possible. */
      match = ( MakeSpecMapping( target, (AstSpecFrame *) *result,
                align_frm, report, map, status ) != 0 );

/* Free resources. */
      align_frm = astAnnul( align_frm );

/* Result is not a SpecFrame. */
/* ------------------------------ */
/* In this case, we select axes as if the target were from the Frame
   class.  However, since the resulting data will then be separated
   from their enclosing SpecFrame, default attribute values may differ
   if the methods for obtaining them were over-ridden by the SpecFrame
   class. To overcome this, we ensure that these values are explicitly
   set for the result Frame (rather than relying on their defaults). */
   } else {

/* Make a temporary copy of the target SpecFrame. We will explicitly
   set the attribute values in this copy so as not to modify the original. */
      temp = astCopy( target );

/* Define a macro to test if an attribute is set. If not, set it
   explicitly to its default value. */
#define SET(attribute) \
   if ( !astTest##attribute( temp ) ) { \
      astSet##attribute( temp, astGet##attribute( temp ) ); \
   }

/* Set attribute values which apply to the Frame as a whole and which
   we want to retain, but whose defaults are over-ridden by the
   SpecFrame class. */
      SET(Domain)
      SET(Title)

/* Define a macro to test if an attribute is set for axis zero (the only
   axis of a SpecFrame). If not, set it explicitly to its default value. */
#define SET_AXIS(attribute) \
   if ( !astTest##attribute( temp, 0 ) ) { \
      astSet##attribute( temp, 0, \
                         astGet##attribute( temp, 0 ) ); \
   }

/* Use this macro to set explicit values for all the axis attributes
   for which the SpecFrame class over-rides the default value. */
      SET_AXIS(Label)
      SET_AXIS(Symbol)
      SET_AXIS(Unit)

/* Clear attributes which have an extended range of values allowed by
   this class. */
      astClearSystem( temp );
      astClearAlignSystem( temp );

/* Invoke the astSubFrame method inherited from the Frame class to
   produce the result Frame by selecting the required set of axes and
   overlaying the template Frame's attributes. */
      match = (*parent_subframe)( (AstFrame *) temp, template,
                                  result_naxes, target_axes, template_axes,
                                  map, result, status );

/* Delete the temporary copy of the target SpecFrame. */
      temp = astDelete( temp );
   }

/* 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;

/* Undefine macros local to this function. */
#undef SET
#undef SET_AXIS
}

static AstSystemType SystemCode( AstFrame *this, const char *system, int *status ) {
/*
*  Name:
*     SystemCode

*  Purpose:
*     Convert a string into a coordinate system type code.

*  Type:
*     Private function.

*  Synopsis:
*     #include "specframe.h"
*     AstSystemType SystemCode( AstFrame *this, const char *system, int *status )

*  Class Membership:
*     SpecFrame member function (over-rides the astSystemCode method
*     inherited from the Frame class).

*  Description:
*     This function converts a string used for the external
*     description of a coordinate system into a SpecFrame
*     coordinate system type code (System attribute value). It is the
*     inverse of the astSystemString function.

*  Parameters:
*     this
*        The Frame.
*     system
*        Pointer to a constant null-terminated string containing the
*        external description of the sky coordinate system.
*     status
*        Pointer to the inherited status variable.

*  Returned Value:
*     The System type code.



( run in 0.523 second using v1.01-cache-2.11-cpan-600a1bdf6e4 )