1 /*
2 *class++
3 * Name:
4 * SpecFluxFrame
5
6 * Purpose:
7 * Compound spectrum/flux Frame.
8
9 * Constructor Function:
10 c astSpecFluxFrame
11 f AST_SPECFLUXFRAME
12
13 * Description:
14 * A SpecFluxFrame combines a SpecFrame and a FluxFrame into a single
15 * 2-dimensional compound Frame. Such a Frame can for instance be used
16 * to describe a Plot of a spectrum in which the first axis represents
17 * spectral position and the second axis represents flux.
18
19 * Inheritance:
20 * The SpecFluxFrame class inherits from the CmpFrame class.
21
22 * Attributes:
23 * The SpecFluxFrame class does not define any new attributes beyond
24 * those which are applicable to all CmpFrames. However, the attributes
25 * of the component Frames can be accessed as if they were attributes
26 * of the SpecFluxFrame. For instance, the SpecFluxFrame will recognise
27 * the "StdOfRest" attribute and forward access requests to the component
28 * SpecFrame. An axis index can optionally be appended to the end of any
29 * attribute name, in which case the request to access the attribute will
30 * be forwarded to the primary Frame defining the specified axis.
31
32 * Functions:
33 c The SpecFluxFrame class does not define any new functions beyond those
34 f The SpecFluxFrame class does not define any new routines beyond those
35 * which are applicable to all CmpFrames.
36
37 * Copyright:
38 * Copyright (C) 1997-2006 Council for the Central Laboratory of the
39 * Research Councils
40
41 * Licence:
42 * This program is free software: you can redistribute it and/or
43 * modify it under the terms of the GNU Lesser General Public
44 * License as published by the Free Software Foundation, either
45 * version 3 of the License, or (at your option) any later
46 * version.
47 *
48 * This program is distributed in the hope that it will be useful,
49 * but WITHOUT ANY WARRANTY; without even the implied warranty of
50 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
51 * GNU Lesser General Public License for more details.
52 *
53 * You should have received a copy of the GNU Lesser General
54 * License along with this program. If not, see
55 * <http://www.gnu.org/licenses/>.
56
57 * Authors:
58 * DSB: David S. Berry (Starlink)
59
60 * History:
61 * 8-DEC-2004 (DSB):
62 * Original version.
63 * 29-APR-2011 (DSB):
64 * Prevent astFindFrame from matching a subclass template against a
65 * superclass target.
66 *class--
67 */
68
69 /* Module Macros. */
70 /* ============== */
71 /* Set the name of the class we are implementing. This indicates to
72 the header files that define class interfaces that they should make
73 "protected" symbols available. */
74 #define astCLASS SpecFluxFrame
75
76 /* Define the first and last acceptable System values. */
77 #define FIRST_SYSTEM AST__COMP
78 #define LAST_SYSTEM AST__COMP
79
80 /* Include files. */
81 /* ============== */
82 /* Interface definitions. */
83 /* ---------------------- */
84
85 #include "globals.h" /* Thread-safe global data access */
86 #include "error.h" /* Error reporting facilities */
87 #include "memory.h" /* Memory allocation facilities */
88 #include "globals.h" /* Thread-safe global data access */
89 #include "object.h" /* Base Object class */
90 #include "mapping.h" /* Coordinate Mappings */
91 #include "unitmap.h" /* Unit Mappings */
92 #include "permmap.h" /* Coordinate permutation Mappings */
93 #include "cmpmap.h" /* Compound Mappings */
94 #include "axis.h" /* Coordinate axes */
95 #include "cmpframe.h" /* Parent CmpFrame class */
96 #include "tranmap.h" /* Separated transformation Mappings */
97 #include "mathmap.h" /* Algebraic Mappings */
98 #include "ratemap.h" /* Differential Mappings */
99 #include "specframe.h" /* SpecFrame class */
100 #include "fluxframe.h" /* FluxFrame class */
101 #include "specfluxframe.h" /* Interface definition for this class */
102
103 /* Error code definitions. */
104 /* ----------------------- */
105 #include "ast_err.h" /* AST error codes */
106
107 /* C header files. */
108 /* --------------- */
109 #include <float.h>
110 #include <math.h>
111 #include <ctype.h>
112 #include <stdarg.h>
113 #include <stddef.h>
114 #include <stdio.h>
115 #include <stdlib.h>
116 #include <string.h>
117
118 /* Module Variables. */
119 /* ================= */
120
121 /* Address of this static variable is used as a unique identifier for
122 member of this class. */
123 static int class_check;
124
125 /* Pointers to parent class methods which are extended by this class. */
126 static int (* parent_match)( AstFrame *, AstFrame *, int, int **, int **, AstMapping **, AstFrame **, int * );
127 static int (* parent_subframe)( AstFrame *, AstFrame *, int, const int *, const int *, AstMapping **, AstFrame **, int * );
128 static const char *(* parent_gettitle)( AstFrame *, int * );
129
130 /* Define macros for accessing each item of thread specific global data. */
131 #ifdef THREAD_SAFE
132
133 /* Define how to initialise thread-specific globals. */
134 #define GLOBAL_inits \
135 globals->Class_Init = 0; \
136 globals->GetTitle_Buff[ 0 ] = 0;
137
138 /* Create the function that initialises global data for this module. */
139 astMAKE_INITGLOBALS(SpecFluxFrame)
140
141 /* Define macros for accessing each item of thread specific global data. */
142 #define class_init astGLOBAL(SpecFluxFrame,Class_Init)
143 #define class_vtab astGLOBAL(SpecFluxFrame,Class_Vtab)
144 #define gettitle_buff astGLOBAL(SpecFluxFrame,GetTitle_Buff)
145
146
147
148 /* If thread safety is not needed, declare and initialise globals at static
149 variables. */
150 #else
151
152 static char gettitle_buff[ 101 ];
153
154
155 /* Define the class virtual function table and its initialisation flag
156 as static variables. */
157 static AstSpecFluxFrameVtab class_vtab; /* Virtual function table */
158 static int class_init = 0; /* Virtual function table initialised? */
159
160 #endif
161
162 /* External Interface Function Prototypes. */
163 /* ======================================= */
164 /* The following functions have public prototypes only (i.e. no
165 protected prototypes), so we must provide local prototypes for use
166 within this module. */
167 AstSpecFluxFrame *astSpecFluxFrameId_( void *, void *, const char *, ... );
168
169 /* Prototypes for Private Member Functions. */
170 /* ======================================== */
171 static AstFluxFrame *GetFluxFrame( AstSpecFluxFrame *, int, int * );
172 static AstMapping *MakeMap2( AstSpecFluxFrame *, int * );
173 static AstMapping *MakeMap3( AstSpecFluxFrame *, AstSpecFluxFrame *, int * );
174 static AstMapping *MakeMapF( AstFluxFrame *, AstSpecFrame *, AstFluxFrame *, AstSpecFrame *, int * );
175 static AstMapping *MakeMapI( AstFluxFrame *, AstSpecFrame *, AstFluxFrame *, AstSpecFrame *, int * );
176 static AstSpecFrame *GetSpecFrame( AstSpecFluxFrame *, int, int * );
177 static const char *GetTitle( AstFrame *, int * );
178 static int MakeSFMapping( AstSpecFluxFrame *, AstSpecFluxFrame *, AstMapping **, int * );
179 static int Match( AstFrame *, AstFrame *, int, int **, int **, AstMapping **, AstFrame **, int * );
180 static int SubFrame( AstFrame *, AstFrame *, int, const int *, const int *, AstMapping **, AstFrame **, int * );
181 static void Dump( AstObject *, AstChannel *, int * );
182
183 /* Member functions. */
184 /* ================= */
185
GetFluxFrame(AstSpecFluxFrame * this,int std,int * status)186 static AstFluxFrame *GetFluxFrame( AstSpecFluxFrame *this, int std, int *status ){
187 /*
188 * Name:
189 * GetFluxFrame
190
191 * Purpose:
192 * Return a pointer to the FluxFrame in a FluxSpecFrame.
193
194 * Type:
195 * Private function.
196
197 * Synopsis:
198 * #include "specfluxframe.h"
199 * AstFluxFrame *GetFluxFrame( AstSpecFluxFrame *this, int std, int *status )
200
201 * Class Membership:
202 * SpecFluxFrame member function.
203
204 * Description:
205 * Returns a pointer to the FluxFrame in a SpecFluxFrame.
206
207 * Parameters:
208 * this
209 * Pointer to the SpecFluxFrame.
210 * std
211 * If non zero, then the returned FluxFrame is a standardised copy of
212 * the FluxFrame in the supplied SpecFluxFrame, in which the System has
213 * been set explicitly (rather than potentially being defaulted), and
214 * the Units have been cleared to use default units appropriate to
215 * the flux System.
216 * status
217 * Pointer to the inherited status variable.
218
219 * Returned Value:
220 * A pointer to the FluxFrame. Should be freed using astAnnul when no
221 * longer needed.
222
223 * Notes:
224 * NULL is returned if this function is invoked with the global error
225 * status set or if it should fail for any reason.
226 */
227
228 /* Local Variables; */
229 AstFluxFrame *ff;
230 AstFluxFrame *ret;
231
232 /* Check the global error status. */
233 if ( !astOK ) return NULL;
234
235 /* The FluxFrame is always the second Frame in the parent CmpFrame. */
236 ff = (AstFluxFrame *) ((AstCmpFrame *)this)->frame2;
237
238 /* Produce a standardised copy of the FluxFrame if required, or clone the
239 above pointer otherwise. */
240 if( std ) {
241 ret = astCopy( ff );
242 astSetSystem( ret, astGetSystem( ff ) );
243 astClearUnit( ret, 0 );
244 } else {
245 ret = astClone( ff );
246 }
247
248 /* Annul the returned pointer if anything went wrong. */
249 if( !astOK ) ret = astAnnul( ret );
250
251 /* Return the result. */
252 return ret;
253 }
254
GetSpecFrame(AstSpecFluxFrame * this,int std,int * status)255 static AstSpecFrame *GetSpecFrame( AstSpecFluxFrame *this, int std, int *status ){
256 /*
257 * Name:
258 * GetSpecFrame
259
260 * Purpose:
261 * Return a pointer to the SpecFrame in a FluxSpecFrame.
262
263 * Type:
264 * Private function.
265
266 * Synopsis:
267 * #include "specfluxframe.h"
268 * AstSpecFrame *GetSpecFrame( AstSpecFluxFrame *this, int std, int *status )
269
270 * Class Membership:
271 * SpecFluxFrame member function.
272
273 * Description:
274 * Returns a pointer to the SpecFrame in a SpecFluxFrame.
275
276 * Parameters:
277 * this
278 * Pointer to the SpecFluxFrame.
279 * std
280 * If non zero, then the returned SpecFrame is a standardised copy of
281 * the SpecFrame in the supplied SpecFluxFrame, in which the System
282 * and Units have been set explicitly to the values appropriate to the
283 * flux system in use in the FluxFrame in the supplied SpecFluxFrame.
284 * status
285 * Pointer to the inherited status variable.
286
287 * Returned Value:
288 * A pointer to the FluxFrame. Should be freed using astAnnul when no
289 * longer needed.
290
291 * Notes:
292 * NULL is returned if this function is invoked with the global error
293 * status set or if it should fail for any reason.
294 */
295
296 /* Local Variables; */
297 AstFluxFrame *ff;
298 AstSpecFrame *ret;
299 AstSpecFrame *sf;
300
301 /* Check the global error status. */
302 if ( !astOK ) return NULL;
303
304 /* Get a pointer to the SpecFrame (the first Frame in the parent CmpFrame). */
305 sf = (AstSpecFrame *) ((AstCmpFrame *)this)->frame1;
306
307 /* If we want a standardised version of the SpecFrame... */
308 if( std ) {
309
310 /* The FluxFrame is always the second Frame in the parent CmpFrame. */
311 ff = (AstFluxFrame *) ((AstCmpFrame *)this)->frame2;
312
313 /* Produce a copy of the SpecFrame and set its System and Units
314 appropriate to the flux system (expressed in default units). */
315 ret = astCopy( sf );
316 astSetSystem( ret, astGetDensitySystem( ff ) );
317 astSetUnit( ret, 0, astGetDensityUnit( ff ) );
318
319 /* If we are not standardising the SpecFrame, just return a clone of the
320 pointer in the parent CmpFrame. */
321 } else {
322 ret = astClone( sf );
323 }
324
325 /* Annul the returned pointer if anything went wrong. */
326 if( !astOK ) ret = astAnnul( ret );
327
328 /* Return the result. */
329 return ret;
330 }
331
GetTitle(AstFrame * this_frame,int * status)332 static const char *GetTitle( AstFrame *this_frame, int *status ) {
333 /*
334 * Name:
335 * GetTitle
336
337 * Purpose:
338 * Obtain a pointer to the Title string for a SpecFluxFrame.
339
340 * Type:
341 * Private function.
342
343 * Synopsis:
344 * #include "specfluxframe.h"
345 * const char *GetTitle( AstFrame *this_frame, int *status )
346
347 * Class Membership:
348 * SpecFluxFrame member function (over-rides the astGetTitle method
349 * inherited from the CmpFrame class).
350
351 * Description:
352 * This function returns a pointer to the Title string for a SpecFluxFrame.
353 * A pointer to a suitable default string is returned if no Title value has
354 * previously been set.
355
356 * Parameters:
357 * this
358 * Pointer to the SpecFluxFrame.
359 * status
360 * Pointer to the inherited status variable.
361
362 * Returned Value:
363 * Pointer to a null-terminated character string containing the requested
364 * information.
365
366 * Notes:
367 * - A NULL pointer will be returned if this function is invoked with the
368 * global error status set, or if it should fail for any reason.
369 */
370
371 /* Local Variables: */
372 astDECLARE_GLOBALS
373 AstSpecFluxFrame *this;
374 AstSpecFrame *sf;
375 AstFluxFrame *ff;
376 const char *result;
377
378 /* Check the global error status. */
379 if ( !astOK ) return NULL;
380
381 /* Get a pointer to the thread specific global data structure. */
382 astGET_GLOBALS(this_frame);
383
384 /* Initialise. */
385 result = NULL;
386
387 /* Obtain a pointer to the SpecFluxFrame structure. */
388 this = (AstSpecFluxFrame *) this_frame;
389
390 /* See if a Title string has been set. If so, use the parent astGetTitle
391 method to obtain a pointer to it. */
392 if ( astTestTitle( this ) ) {
393 result = (*parent_gettitle)( this_frame, status );
394
395 /* Otherwise, we will generate a default Title string. Obtain the values of the
396 SpecFrame's attributes that determine what this string will be. */
397 } else {
398 ff = GetFluxFrame( this, 0, status );
399 sf = GetSpecFrame( this, 0, status );
400
401 if( astOK ) {
402 sprintf( gettitle_buff, "%s versus %s", astGetLabel( ff, 0 ),
403 astGetLabel( sf, 0 ) );
404 gettitle_buff[ 0 ] = toupper( gettitle_buff[ 0 ] );
405 result = gettitle_buff;
406 }
407
408 ff = astAnnul( ff );
409 sf = astAnnul( sf );
410
411 }
412
413 /* If an error occurred, clear the returned pointer value. */
414 if ( !astOK ) result = NULL;
415
416 /* Return the result. */
417 return result;
418 }
419
astInitSpecFluxFrameVtab_(AstSpecFluxFrameVtab * vtab,const char * name,int * status)420 void astInitSpecFluxFrameVtab_( AstSpecFluxFrameVtab *vtab, const char *name, int *status ) {
421 /*
422 *+
423 * Name:
424 * astInitSpecFluxFrameVtab
425
426 * Purpose:
427 * Initialise a virtual function table for a SpecFluxFrame.
428
429 * Type:
430 * Protected function.
431
432 * Synopsis:
433 * #include "specfluxframe.h"
434 * void astInitSpecFluxFrameVtab( AstSpecFluxFrameVtab *vtab, const char *name )
435
436 * Class Membership:
437 * SpecFluxFrame vtab initialiser.
438
439 * Description:
440 * This function initialises the component of a virtual function
441 * table which is used by the SpecFluxFrame class.
442
443 * Parameters:
444 * vtab
445 * Pointer to the virtual function table. The components used by
446 * all ancestral classes will be initialised if they have not already
447 * been initialised.
448 * name
449 * Pointer to a constant null-terminated character string which contains
450 * the name of the class to which the virtual function table belongs (it
451 * is this pointer value that will subsequently be returned by the Object
452 * astClass function).
453 *-
454 */
455
456 /* Local Variables: */
457 astDECLARE_GLOBALS /* Pointer to thread-specific global data */
458 AstObjectVtab *object; /* Pointer to Object component of Vtab */
459 AstFrameVtab *frame; /* Pointer to Frame component of Vtab */
460 AstMappingVtab *mapping; /* Pointer to Mapping component of Vtab */
461
462 /* Check the local error status. */
463 if ( !astOK ) return;
464
465 /* Get a pointer to the thread specific global data structure. */
466 astGET_GLOBALS(NULL);
467
468 /* Initialize the component of the virtual function table used by the
469 parent class. */
470 astInitCmpFrameVtab( (AstCmpFrameVtab *) vtab, name );
471
472 /* Store a unique "magic" value in the virtual function table. This
473 will be used (by astIsASpecFluxFrame) to determine if an object belongs
474 to this class. We can conveniently use the address of the (static)
475 class_check variable to generate this unique value. */
476 vtab->id.check = &class_check;
477 vtab->id.parent = &(((AstCmpFrameVtab *) vtab)->id);
478
479 /* Initialise member function pointers. */
480 /* ------------------------------------ */
481 /* Store pointers to the member functions (implemented here) that
482 provide virtual methods for this class. */
483
484 /* Save the inherited pointers to methods that will be extended, and
485 replace them with pointers to the new member functions. */
486 object = (AstObjectVtab *) vtab;
487 frame = (AstFrameVtab *) vtab;
488 mapping = (AstMappingVtab *) vtab;
489
490 /* Store replacement pointers for methods which will be over-ridden by
491 new member functions implemented here. */
492
493 parent_match = frame->Match;
494 frame->Match = Match;
495
496 parent_subframe = frame->SubFrame;
497 frame->SubFrame = SubFrame;
498
499 parent_gettitle = frame->GetTitle;
500 frame->GetTitle = GetTitle;
501
502 /* Declare the copy constructor, destructor and class dump
503 function. */
504 astSetDump( vtab, Dump, "SpecFluxFrame",
505 "Compound spectral/flux coordinate system description" );
506
507 /* If we have just initialised the vtab for the current class, indicate
508 that the vtab is now initialised, and store a pointer to the class
509 identifier in the base "object" level of the vtab. */
510 if( vtab == &class_vtab ) {
511 class_init = 1;
512 astSetVtabClassIdentifier( vtab, &(vtab->id) );
513 }
514 }
515
MakeMap2(AstSpecFluxFrame * this,int * status)516 static AstMapping *MakeMap2( AstSpecFluxFrame *this, int *status ){
517 /*
518 * Name:
519 * MakeMap2
520
521 * Purpose:
522 * Generate the second Mapping required by MakeSFMapping
523
524 * Type:
525 * Private function.
526
527 * Synopsis:
528 * #include "specfluxframe.h"
529 * AstMapping *MakeMap2( AstSpecFluxFrame *this, int *status )
530
531 * Class Membership:
532 * SpecFluxFrame member function.
533
534 * Description:
535 * The second Mapping used by MakeSFMapping contains three Mappings in
536 * parallel which converts v1 (flux value) and x1 (spectral position) into
537 * default units, and passes the third axis (a copy of flux value)
538 * unchanged.
539
540 * Parameters:
541 * this
542 * Pointer to the SpecFluxFrame to use.
543 * status
544 * Pointer to the inherited status variable.
545
546 * Returned Value:
547 * A pointer to the required Mapping, or NULL if the Mapping cannot be
548 * created. The Mapping will have 3 inputs and 3 outputs.
549
550 * Notes:
551 * NULL is returned if this function is invoked with the global error
552 * status set or if it should fail for any reason.
553 */
554
555 /* Local Variables: */
556 AstFrame *f1;
557 AstFrame *f2;
558 AstFrameSet *fs;
559 AstMapping *ax1_map;
560 AstMapping *ax2_map;
561 AstMapping *ax3_map;
562 AstMapping *ret;
563 AstMapping *tmap;
564
565 /* Initialise. */
566 ret = NULL;
567
568 /* Check the global error status. */
569 if ( !astOK ) return ret;
570
571 /* Input 0 is the supplied FluxFrame value and output 0 is the corresponding
572 value in the default units for the FluxFrame system. Take a copy of the
573 supplied FluxFrame, and fix its System value (which may be a default value
574 based on the Units string), and then clear the Units so that it represents
575 default units for the System. */
576 f1 = (AstFrame *) GetFluxFrame( this, 0, status );
577 f2 = (AstFrame *) GetFluxFrame( this, 1, status );
578
579 /* Now, if conversion was possible, get the Mapping from the supplied
580 FluxFrame to the default units FluxFrame. */
581 fs = astConvert( f1, f2, "" );
582 f1 = astAnnul( f1 );
583 f2 = astAnnul( f2 );
584
585 if( fs ) {
586 ax1_map = astGetMapping( fs, AST__BASE, AST__CURRENT );
587 fs = astAnnul( fs );
588
589 /* Input 1 is the supplied SpecFrame value and output 1 is the corresponding
590 value in the spectral system used by the flux system (wavelength or
591 frequency). Take a copy of the supplied SpecFrame, and fix its System
592 value to wavelength or frequency (depending on the System value of the
593 FluxFrame), and set up units of Hz or Angstrom (these are the spectral
594 position units used within the default flux units for a FluxFrame). */
595 f1 = (AstFrame *) GetSpecFrame( this, 0, status );
596 f2 = (AstFrame *) GetSpecFrame( this, 1, status );
597
598 /* Now, if conversion was possible, get the Mapping from the supplied
599 SpecFrame to the required SpecFrame. */
600 fs = astConvert( f1, f2, "" );
601 f1 = astAnnul( f1 );
602 f2 = astAnnul( f2 );
603
604 if( fs ) {
605 ax2_map = astGetMapping( fs, AST__BASE, AST__CURRENT );
606 fs = astAnnul( fs );
607
608 /* Create a UnitMap for the 3rd axis. */
609 ax3_map = (AstMapping *) astUnitMap( 1, "", status );
610
611 /* Create a parallel CmpMap containing the three Mappings. */
612 tmap = (AstMapping *) astCmpMap( ax1_map, ax2_map, 0, "", status );
613 ret = (AstMapping *) astCmpMap( tmap, ax3_map, 0, "", status );
614
615 /* Free remaining resources. */
616 tmap = astAnnul( tmap );
617 ax2_map = astAnnul( ax2_map );
618 ax3_map = astAnnul( ax3_map );
619
620 }
621 ax1_map = astAnnul( ax1_map );
622 }
623
624 /* If an error has occurred, return NULL. */
625 if( !astOK ) ret = astAnnul( ret );
626
627 /* Return the result */
628 return ret;
629 }
630
MakeMap3(AstSpecFluxFrame * target,AstSpecFluxFrame * result,int * status)631 static AstMapping *MakeMap3( AstSpecFluxFrame *target, AstSpecFluxFrame *result, int *status ){
632 /*
633 * Name:
634 * MakeMap3
635
636 * Purpose:
637 * Generate the third Mapping required by MakeSFMapping
638
639 * Type:
640 * Private function.
641
642 * Synopsis:
643 * #include "specfluxframe.h"
644 * AstMapping *MakeMap3( AstSpecFluxFrame *target, AstSpecFluxFrame *result, int *status )
645
646 * Class Membership:
647 * SpecFluxFrame member function.
648
649 * Description:
650 * The third Mapping used by MakeSFMapping converts input (v1,x1) in
651 * default units to output (v2,x2) in default units. The third axis (x1)
652 * in original units is converted to x2 in original units.
653
654 * Parameters:
655 * target
656 * Pointer to the first SpecFluxFrame.
657 * result
658 * Pointer to the second SpecFluxFrame.
659 * status
660 * Pointer to the inherited status variable.
661
662 * Returned Value:
663 * A pointer to the required Mapping, or NULL if the Mapping cannot be
664 * created. The Mapping will have 3 inputs and 3 outputs.
665
666 * Notes:
667 * NULL is returned if this function is invoked with the global error
668 * status set or if it should fail for any reason.
669 */
670
671 /* Local Variables: */
672 AstFluxFrame *ff2;
673 AstFluxFrame *ff1;
674 AstFrameSet *fs;
675 AstMapping *fmap;
676 AstMapping *imap;
677 AstMapping *mapa;
678 AstMapping *mapb;
679 AstMapping *ret;
680 AstSpecFrame *sf2;
681 AstSpecFrame *sf1;
682
683 /* Initialise */
684 ret = NULL;
685
686 /* Check the global error status. */
687 if ( !astOK ) return ret;
688
689 /* The first two inputs and outputs are related by a TranMap which
690 converts between standardised (v1,x1) and standardised (v2,x2). Get
691 pointers to the standardised SpecFrames and FluxFrames in the two
692 supplied SpecFluxFrames. */
693 ff1 = GetFluxFrame( target, 1, status );
694 sf1 = GetSpecFrame( target, 1, status );
695 ff2 = GetFluxFrame( result, 1, status );
696 sf2 = GetSpecFrame( result, 1, status );
697
698 /* Create the Mapping which defines the forward transformation of the
699 required TranMap. The forward transformation of this Mapping goes from
700 (v1,x1) to (v2,x2). */
701 fmap = MakeMapF( ff1, sf1, ff2, sf2, status );
702
703 /* Create the Mapping which defines the inverse transformation of the
704 required TranMap. The inverse transformation of this Mapping goes from
705 (v2,x2) to (v1,x1). */
706 imap = MakeMapI( ff1, sf1, ff2, sf2, status );
707
708 /* Combine these into a TranMap */
709 if( fmap && imap ) {
710 mapa = (AstMapping *) astTranMap( fmap, imap, "", status );
711 } else {
712 mapa = NULL;
713 }
714
715 /* Free resources. */
716 ff1 = astAnnul( ff1 );
717 sf1 = astAnnul( sf1 );
718 ff2 = astAnnul( ff2 );
719 sf2 = astAnnul( sf2 );
720 if( fmap ) fmap = astAnnul( fmap );
721 if( imap ) imap = astAnnul( imap );
722
723 /* The third input and output are related by a Mapping which converts
724 between supplied (x1) and supplied (x2). Get pointers to the original
725 unmodified SpecFrames in the two supplied SpecFluxFrames. */
726 sf1 = GetSpecFrame( target, 0, status );
727 sf2 = GetSpecFrame( result, 0, status );
728
729 /* Find the Mapping from the first to the second. */
730 fs = astConvert( sf1, sf2, "" );
731 if( fs ) {
732 mapb = astGetMapping( fs, AST__BASE, AST__CURRENT );
733 fs = astAnnul( fs );
734 } else {
735 mapb = NULL;
736 }
737
738 /* Free resources. */
739 sf1 = astAnnul( sf1 );
740 sf2 = astAnnul( sf2 );
741
742 /* Combine the two Mappings in parallel. */
743 if( mapa && mapb ) ret = (AstMapping *) astCmpMap( mapa, mapb, 0, "", status );
744 if( mapa ) mapa = astAnnul( mapa );
745 if( mapb ) mapb = astAnnul( mapb );
746
747 /* If an error has occurred, return NULL. */
748 if( !astOK ) ret = astAnnul( ret );
749
750 /* Return the result */
751 return ret;
752 }
753
MakeMapF(AstFluxFrame * v1,AstSpecFrame * x1,AstFluxFrame * v2,AstSpecFrame * x2,int * status)754 static AstMapping *MakeMapF( AstFluxFrame *v1, AstSpecFrame *x1,
755 AstFluxFrame *v2, AstSpecFrame *x2, int *status ){
756 /*
757 * Name:
758 * MakeMapF
759
760 * Purpose:
761 * Generate the forward part of the third Mapping required by MakeSFMapping
762
763 * Type:
764 * Private function.
765
766 * Synopsis:
767 * #include "specfluxframe.h"
768 * AstMapping *MakeMapF( AstFluxFrame *v1, AstSpecFrame *x1,
769 * AstFluxFrame *v2, AstSpecFrame *x2, int *status )
770
771 * Class Membership:
772 * SpecFluxFrame member function.
773
774 * Description:
775 * Theis creates a 2-input 2-output Mapping which transforms
776 * input (v1,x1) in default units to output (v2,x2) in default units.
777
778 * Parameters:
779 * v1
780 * Pointer to the standardised input FluxFrame.
781 * x1
782 * Pointer to the standardised input SpecFrame.
783 * v2
784 * Pointer to the standardised output FluxFrame.
785 * x2
786 * Pointer to the standardised output SpecFrame.
787 * status
788 * Pointer to the inherited status variable.
789
790 * Returned Value:
791 * A pointer to the required Mapping, or NULL if the Mapping cannot be
792 * created.
793
794 * Notes:
795 * NULL is returned if this function is invoked with the global error
796 * status set or if it should fail for any reason.
797 */
798
799 /* Local Variables: */
800 AstCmpMap *cmap1;
801 AstCmpMap *cmap2;
802 AstCmpMap *cmap3;
803 AstFrameSet *fs;
804 AstMapping *m;
805 AstMapping *ret;
806 AstMathMap *div;
807 AstPermMap *perm;
808 AstRateMap *rate;
809 AstUnitMap *unit;
810 const char *fwd[1];
811 const char *inv[2];
812 int inperm[ 2 ];
813 int outperm[ 3 ];
814
815 /* Initialise */
816 ret = NULL;
817
818 /* Check the global error status. */
819 if ( !astOK ) return ret;
820
821 /* First create the required component Mappings.
822 --------------------------------------------- */
823
824 /* A Mapping which maps input spectral position (x1) into output spectral
825 position (x2). */
826 fs = astConvert( x1, x2, "" );
827 if( fs ) {
828 m = astGetMapping( fs, AST__BASE, AST__CURRENT );
829
830 /* A 1-input 1-output Mapping in which the input is spectral position (x1)
831 and the output is the rate of change of output spectral position (x2)
832 with respect to input spectral position (x1). */
833 rate = astRateMap( m, 0, 0, "", status );
834
835 /* A MathMap which is used to divide the flux value (v1) by the absolute rate
836 of change of x2 wrt x1 */
837 fwd[ 0 ] = "out=in0/abs(in1)";
838 inv[ 0 ] = "in0";
839 inv[ 1 ] = "in1";
840 div = astMathMap( 2, 1, 1, fwd, 2, inv, "", status );
841
842 /* A 1D UnitMap used to copy v1. */
843 unit = astUnitMap( 1, "", status );
844
845 /* A PermMap which is used to produce an extra output copy of x1. */
846 inperm[ 0 ] = 0;
847 inperm[ 1 ] = 2;
848 outperm[ 0 ] = 0;
849 outperm[ 1 ] = 1;
850 outperm[ 2 ] = 1;
851 perm = astPermMap( 2, inperm, 3, outperm, NULL, "", status );
852
853 /* Now combine these component Mappings together.
854 --------------------------------------------- */
855
856 /* First put the UnitMap and the RateMap in parallel. This produces a 2-in
857 2-out Mapping in which the inputs are (v1,x1) and the outputs are
858 (v1,dx2/dx1). */
859 cmap1 = astCmpMap( unit, rate, 0, "", status );
860
861 /* Now put this in series with the dividing MathMap. This results in a
862 2-in, 1-out Mapping in which the inputs are v1 and x1 and the single
863 output is v2. */
864 cmap2 = astCmpMap( cmap1, div, 1, "", status );
865
866 /* Now put this in parallel with the x1->x2 Mapping. This results in a
867 3-in, 2-out Mapping in which the inputs are (v1,x1,x1) and the outputs
868 are (v2,x2). */
869 cmap3 = astCmpMap( cmap2, m, 0, "", status );
870
871 /* Finally put this in series with the PermMap. This results in a 2-in,
872 2-out Mapping in which the inputs are (v1,x1) and the outputs are
873 (v2,x2). */
874 ret = (AstMapping *) astCmpMap( perm, cmap3, 1, "", status );
875
876 /* Free resources. */
877 fs = astAnnul( fs );
878 m = astAnnul( m );
879 rate = astAnnul( rate );
880 div= astAnnul( div );
881 unit = astAnnul( unit );
882 perm = astAnnul( perm );
883 cmap1 = astAnnul( cmap1 );
884 cmap2 = astAnnul( cmap2 );
885 cmap3 = astAnnul( cmap3 );
886 }
887
888 /* If an error has occurred, return NULL. */
889 if( !astOK ) ret = astAnnul( ret );
890
891 /* Return the result */
892 return ret;
893 }
894
MakeMapI(AstFluxFrame * v1,AstSpecFrame * x1,AstFluxFrame * v2,AstSpecFrame * x2,int * status)895 static AstMapping *MakeMapI( AstFluxFrame *v1, AstSpecFrame *x1,
896 AstFluxFrame *v2, AstSpecFrame *x2, int *status ){
897 /*
898 * Name:
899 * MakeMapI
900
901 * Purpose:
902 * Generate the inverse part of the third Mapping required by MakeSFMapping
903
904 * Type:
905 * Private function.
906
907 * Synopsis:
908 * #include "specfluxframe.h"
909 * AstMapping *MakeMapI( AstFluxFrame *v1, AstSpecFrame *x1,
910 * AstFluxFrame *v2, AstSpecFrame *x2 )
911
912 * Class Membership:
913 * SpecFluxFrame member function.
914
915 * Description:
916 * This creates a 2-input 2-output Mapping in which the inverse
917 * transformation transforms "outputs" representing (v2,x2) into
918 * "inputs" representing (v1,x1).
919
920 * Parameters:
921 * v1
922 * Pointer to the standardised input FluxFrame.
923 * x1
924 * Pointer to the standardised input SpecFrame.
925 * v2
926 * Pointer to the standardised output FluxFrame.
927 * x2
928 * Pointer to the standardised output SpecFrame.
929
930 * Returned Value:
931 * A pointer to the required Mapping, or NULL if the Mapping cannot be
932 * created.
933
934 * Notes:
935 * NULL is returned if this function is invoked with the global error
936 * status set or if it should fail for any reason.
937 */
938
939 /* Local Variables: */
940 AstCmpMap *cmap1;
941 AstCmpMap *cmap2;
942 AstCmpMap *cmap3;
943 AstCmpMap *cmap4;
944 AstCmpMap *cmap5;
945 AstFrameSet *fs;
946 AstMapping *m;
947 AstMapping *ret;
948 AstMathMap *mult;
949 AstPermMap *perm;
950 AstRateMap *rate;
951 AstUnitMap *unit;
952 const char *fwd[1];
953 const char *inv[2];
954 int inperm[ 2 ];
955 int outperm[ 3 ];
956
957 /* Initialise */
958 ret = NULL;
959
960 /* Check the global error status. */
961 if ( !astOK ) return ret;
962
963 /* We create a CmpMap in which the forward transformation foes from
964 (v2,x2) to (v1,x1) and we finally invert this Mapping to get the
965 required Mapping in which the *inverse* transformation goes from
966 (v2,x2) to (v1,x1).
967
968 First create the required component Mappings.
969 --------------------------------------------- */
970
971 /* A Mapping which maps spectral position x1 into spectral position x2. */
972 fs = astConvert( x1, x2, "" );
973 if( fs ) {
974 m = astGetMapping( fs, AST__BASE, AST__CURRENT );
975
976 /* A 1-input 1-output Mapping in which the input is spectral position x1
977 and the output is the rate of change of spectral position x2 with
978 respect to spectral position x1. */
979 rate = astRateMap( m, 0, 0, "", status );
980
981 /* Now invert "m" so that its forward transformation goes from x2 to x1.
982 The RateMap created above retains a copy of the original Invert flag
983 for "m" and uses it in preference to the current value when transforming
984 points. */
985 astInvert( m );
986
987 /* A MathMap which is used to multiple the flux value v2 by the
988 absolute rate of change of x2 wrt x1 */
989 fwd[ 0 ] = "out=in0*abs(in1)";
990 inv[ 0 ] = "in0";
991 inv[ 1 ] = "in1";
992 mult = astMathMap( 2, 1, 1, fwd, 2, inv, "", status );
993
994 /* A 1D UnitMap used to copy various values. */
995 unit = astUnitMap( 1, "", status );
996
997 /* A PermMap which is used to produce an extra copy of x1. */
998 inperm[ 0 ] = 0;
999 inperm[ 1 ] = 2;
1000 outperm[ 0 ] = 0;
1001 outperm[ 1 ] = 1;
1002 outperm[ 2 ] = 1;
1003 perm = astPermMap( 2, inperm, 3, outperm, NULL, "", status );
1004
1005 /* Now combine these component Mappings together.
1006 --------------------------------------------- */
1007
1008 /* First put the UnitMap and the RateMap in parallel. This produces a 2-in
1009 2-out Mapping in which the inputs are (v2,x1) and the outputs are
1010 (v2,dx2/dx1). */
1011 cmap1 = astCmpMap( unit, rate, 0, "", status );
1012
1013 /* Now put this in series with the multiplying MathMap. This results in a
1014 2-in, 1-out Mapping in which the inputs are (v2,x1) and the single
1015 output is v1. */
1016 cmap2 = astCmpMap( cmap1, mult, 1, "", status );
1017
1018 /* Now put this in parallel with the UnitMap to get a 3-in, 2-out Mapping
1019 in which the inputs are (v2,x1,x1) and the outputs are (v1,x1). */
1020 cmap3 = astCmpMap( cmap2, unit, 0, "", status );
1021
1022 /* Now put this in series with the PermMap to get a 2-in, 2-out Mapping
1023 in which the inputs are (v2,x1) and the outputs are (v1,x1). */
1024 cmap4 = astCmpMap( perm, cmap3, 1, "", status );
1025
1026 /* Now put the UnitMap in parallel with the (x2->x1 Mapping to get a
1027 2-in, 2-out Mapping in which the inputs are (v2,x2) and the outputs are
1028 (v2,x1). */
1029 cmap5 = astCmpMap( unit, m, 0, "", status );
1030
1031 /* Finally put this in series with "cmap4" to get a 2-in 2-out Mapping
1032 from (v2,x2) to (v1,x1). */
1033 ret = (AstMapping *) astCmpMap( cmap5, cmap4, 1, "", status );
1034
1035 /* Invert this so that the inverse transformation goes from (v2,x2) to
1036 (v1,x1). */
1037 astInvert( ret );
1038
1039 /* Free resources. */
1040 fs = astAnnul( fs );
1041 m = astAnnul( m );
1042 rate = astAnnul( rate );
1043 mult = astAnnul( mult );
1044 unit = astAnnul( unit );
1045 perm = astAnnul( perm );
1046 cmap1 = astAnnul( cmap1 );
1047 cmap2 = astAnnul( cmap2 );
1048 cmap3 = astAnnul( cmap3 );
1049 cmap4 = astAnnul( cmap4 );
1050 cmap5 = astAnnul( cmap5 );
1051 }
1052
1053 /* If an error has occurred, return NULL. */
1054 if( !astOK ) ret = astAnnul( ret );
1055
1056 /* Return the result */
1057 return ret;
1058 }
1059
MakeSFMapping(AstSpecFluxFrame * target,AstSpecFluxFrame * result,AstMapping ** map,int * status)1060 static int MakeSFMapping( AstSpecFluxFrame *target, AstSpecFluxFrame *result,
1061 AstMapping **map, int *status ){
1062 /*
1063 * Name:
1064 * MakeSFMapping
1065
1066 * Purpose:
1067 * Generate a Mapping between two SpecFluxFrames.
1068
1069 * Type:
1070 * Private function.
1071
1072 * Synopsis:
1073 * #include "specfluxframe.h"
1074 * int MakeSFMapping( AstSpecFluxFrame *target, AstSpecFluxFrame *result,
1075 * AstMapping **map, int *status )
1076
1077 * Class Membership:
1078 * SpecFluxFrame member function.
1079
1080 * Description:
1081 * This function takes two SpecFluxFrames and generates a Mapping that
1082 * converts between them, taking account of differences in their
1083 * coordinate systems, systems, units, etc. (but not allowing for any
1084 * axis permutations).
1085
1086 * Parameters:
1087 * target
1088 * Pointer to the first SpecFluxFrame.
1089 * result
1090 * Pointer to the second SpecFluxFrame.
1091 * map
1092 * Pointer to a location which is to receive a pointer to the
1093 * returned Mapping. The forward transformation of this Mapping
1094 * will convert from "target" coordinates to "result"
1095 * coordinates, and the inverse transformation will convert in
1096 * the opposite direction (all coordinate values in radians).
1097 * status
1098 * Pointer to the inherited status variable.
1099
1100 * Returned Value:
1101 * Non-zero if the Mapping could be generated, or zero if the two
1102 * SpecFluxFrames are sufficiently un-related that no meaningful Mapping
1103 * can be produced.
1104
1105 * Notes:
1106 * A value of zero is returned if this function is invoked with the
1107 * global error status set or if it should fail for any reason.
1108 */
1109
1110 /* Local Variables: */
1111 AstMapping *map1;
1112 AstMapping *map2;
1113 AstMapping *map3;
1114 AstMapping *map4;
1115 AstMapping *map5;
1116 AstMapping *tmap1;
1117 AstMapping *tmap2;
1118 AstMapping *tmap3;
1119 AstMapping *tmap4;
1120 int inperm[2];
1121 int match;
1122 int outperm[3];
1123
1124 /* Check the global error status. */
1125 if ( !astOK ) return 0;
1126
1127 /* Initialise the returned values. */
1128 match = 0;
1129 *map = NULL;
1130
1131 /* Initialise other things. */
1132 map1 = NULL;
1133 map2 = NULL;
1134 map3 = NULL;
1135 map4 = NULL;
1136 map5 = NULL;
1137 tmap1 = NULL;
1138 tmap2 = NULL;
1139 tmap3 = NULL;
1140 tmap4 = NULL;
1141
1142 /* At the top level, the required Mapping consists of five Mappings in
1143 series. Inputs 0 and 1 of the total Mapping correspond to the SpecFrame
1144 and FluxFrame in the target SpecFluxFrame. These are referred to as X1
1145 and V1. Outputs 0 and 1 of the total Mapping correspond to the SpecFrame
1146 and FluxFrame in the result SpecFluxFrame. These are referred to as X2
1147 and V2. */
1148
1149 /* Map1 is a PermMap which copies v1 to its first output and x1 to its
1150 second and third outputs. The inverse transformation copies v1 from
1151 its first output and x1 from its third output. */
1152 inperm[ 0 ] = 2;
1153 inperm[ 1 ] = 0;
1154 outperm[ 0 ] = 1;
1155 outperm[ 1 ] = 0;
1156 outperm[ 2 ] = 0;
1157 map1 = (AstMapping *) astPermMap( 2, inperm, 3, outperm, NULL, "", status );
1158
1159 /* Map2 contains three Mappings in parallel which converts v1 and x1 into
1160 default units, and passes the third axis unchanged. */
1161 map2 = MakeMap2( target, status );
1162
1163 /* Map3 converts ( v1,x1) in default units to (v2,x2) in default units.
1164 The third axis (x1) in original units is convert to x2 in original
1165 units. */
1166 map3 = map2 ? MakeMap3( target, result, status ) : NULL;
1167
1168 /* Map4 converts (v2,x2) in default units to (v2,x2) in original units
1169 and passes the third axis unchanged. This is similar to Map2 but based
1170 on the result ratherthan the target, and in the opposite direction. */
1171 if( map3 ) {
1172 map4 = MakeMap2( result, status );
1173 if( map4 ) astInvert( map4 );
1174 } else {
1175 map4 = NULL;
1176 }
1177
1178 /* Map5 is a PermMap which is the inverse of Map1. */
1179 map5 = map4 ? astCopy( map1 ) : NULL;
1180 if( map5 ) astInvert( map5 );
1181
1182 /* Combine all 6 Mappings in series. */
1183 if( map5 ) {
1184 tmap1 = (AstMapping *) astCmpMap( map1, map2, 1, "", status );
1185 tmap2 = (AstMapping *) astCmpMap( tmap1, map3, 1, "", status );
1186 tmap3 = (AstMapping *) astCmpMap( tmap2, map4, 1, "", status );
1187 tmap4 = (AstMapping *) astCmpMap( tmap3, map5, 1, "", status );
1188
1189 /* Return the simplified total Mapping. */
1190 *map = astSimplify( tmap4 );
1191 match = 1;
1192 }
1193
1194 /* Free resources. */
1195 if( map1 ) map1 = astAnnul( map1 );
1196 if( map2 ) map2 = astAnnul( map2 );
1197 if( map3 ) map3 = astAnnul( map3 );
1198 if( map4 ) map4 = astAnnul( map4 );
1199 if( map5 ) map5 = astAnnul( map5 );
1200 if( tmap1 ) tmap1 = astAnnul( tmap1 );
1201 if( tmap2 ) tmap2 = astAnnul( tmap2 );
1202 if( tmap3 ) tmap3 = astAnnul( tmap3 );
1203 if( tmap4 ) tmap4 = astAnnul( tmap4 );
1204
1205 /* If an error occurred, annul the returned Mapping and clear the
1206 returned values. */
1207 if ( !astOK ) {
1208 *map = astAnnul( *map );
1209 match = 0;
1210 }
1211
1212 /* Return the result. */
1213 return match;
1214 }
1215
Match(AstFrame * template_frame,AstFrame * target,int matchsub,int ** template_axes,int ** target_axes,AstMapping ** map,AstFrame ** result,int * status)1216 static int Match( AstFrame *template_frame, AstFrame *target, int matchsub,
1217 int **template_axes, int **target_axes,
1218 AstMapping **map, AstFrame **result, int *status ) {
1219 /*
1220 * Name:
1221 * Match
1222
1223 * Purpose:
1224 * Determine if conversion is possible between two coordinate systems.
1225
1226 * Type:
1227 * Private function.
1228
1229 * Synopsis:
1230 * #include "specfluxframe.h"
1231 * int Match( AstFrame *template, AstFrame *target, int matchsub,
1232 * int **template_axes, int **target_axes,
1233 * AstMapping **map, AstFrame **result, int *status )
1234
1235 * Class Membership:
1236 * SpecFluxFrame member function (over-rides the protected astMatch
1237 * method inherited from the Frame class).
1238
1239 * Description:
1240 * This function matches a "template" SpecFluxFrame to a "target" Frame
1241 * and determines whether it is possible to convert coordinates
1242 * between them. If it is, a Mapping that performs the
1243 * transformation is returned along with a new Frame that describes
1244 * the coordinate system that results when this Mapping is applied
1245 * to the "target" coordinate system. In addition, information is
1246 * returned to allow the axes in this "result" Frame to be
1247 * associated with the corresponding axes in the "target" Frame and
1248 * "template" SpecFluxFrame from which they are derived.
1249
1250 * Parameters:
1251 * template
1252 * Pointer to the template SpecFluxFrame. This describes the
1253 * coordinate system (or set of possible coordinate systems)
1254 * into which we wish to convert our coordinates.
1255 * target
1256 * Pointer to the target Frame. This describes the coordinate
1257 * system in which we already have coordinates.
1258 * matchsub
1259 * If zero then a match only occurs if the template is of the same
1260 * class as the target, or of a more specialised class. If non-zero
1261 * then a match can occur even if this is not the case.
1262 * template_axes
1263 * Address of a location where a pointer to int will be returned
1264 * if the requested coordinate conversion is possible. This
1265 * pointer will point at a dynamically allocated array of
1266 * integers with one element for each axis of the "result" Frame
1267 * (see below). It must be freed by the caller (using astFree)
1268 * when no longer required.
1269 *
1270 * For each axis in the result Frame, the corresponding element
1271 * of this array will return the (zero-based) index of the
1272 * template SpecFluxFrame axis from which it is derived. If it is not
1273 * derived from any template axis, a value of -1 will be
1274 * returned instead.
1275 * target_axes
1276 * Address of a location where a pointer to int will be returned
1277 * if the requested coordinate conversion is possible. This
1278 * pointer will point at a dynamically allocated array of
1279 * integers with one element for each axis of the "result" Frame
1280 * (see below). It must be freed by the caller (using astFree)
1281 * when no longer required.
1282 *
1283 * For each axis in the result Frame, the corresponding element
1284 * of this array will return the (zero-based) index of the
1285 * target Frame axis from which it is derived. If it is not
1286 * derived from any target axis, a value of -1 will be returned
1287 * instead.
1288 * map
1289 * Address of a location where a pointer to a new Mapping will
1290 * be returned if the requested coordinate conversion is
1291 * possible. If returned, the forward transformation of this
1292 * Mapping may be used to convert coordinates between the
1293 * "target" Frame and the "result" Frame (see below) and the
1294 * inverse transformation will convert in the opposite
1295 * direction.
1296 * result
1297 * Address of a location where a pointer to a new Frame will be
1298 * returned if the requested coordinate conversion is
1299 * possible. If returned, this Frame describes the coordinate
1300 * system that results from applying the returned Mapping
1301 * (above) to the "target" coordinate system. In general, this
1302 * Frame will combine attributes from (and will therefore be
1303 * more specific than) both the target Frame and the template
1304 * SpecFluxFrame. In particular, when the template allows the
1305 * possibility of transformaing to any one of a set of
1306 * alternative coordinate systems, the "result" Frame will
1307 * indicate which of the alternatives was used.
1308 * status
1309 * Pointer to the inherited status variable.
1310
1311 * Returned Value:
1312 * A non-zero value is returned if the requested coordinate
1313 * conversion is possible. Otherwise zero is returned (this will
1314 * not in itself result in an error condition).
1315
1316 * Notes:
1317 * - By default, the "result" Frame will have its number of axes
1318 * and axis order determined by the "template" SpecFluxFrame. However,
1319 * if the PreserveAxes attribute of the template SpecFluxFrame is
1320 * non-zero, then the axis count and axis order of the "target"
1321 * Frame will be used instead.
1322 * - A value of zero will be returned if this function is invoked
1323 * with the global error status set, or if it should fail for any
1324 * reason.
1325 */
1326
1327 /* Local Variables: */
1328 AstSpecFluxFrame *template; /* Pointer to template SpecFluxFrame structure */
1329 int match; /* Coordinate conversion possible? */
1330 int swap1; /* Template axes swapped? */
1331 int swap2; /* Target axes swapped? */
1332 int swap; /* Additional axis swap needed? */
1333
1334 /* Initialise the returned values. */
1335 *template_axes = NULL;
1336 *target_axes = NULL;
1337 *map = NULL;
1338 *result = NULL;
1339 match = 0;
1340
1341 /* Check the global error status. */
1342 if ( !astOK ) return match;
1343
1344 /* Obtain a pointer to the template SpecFluxFrame structure. */
1345 template = (AstSpecFluxFrame *) template_frame;
1346
1347 /* If the target is not a SpecFluxFrame, use the results returned by the
1348 parent Match method inherited from the CmpFrame class. */
1349 if( !astIsASpecFluxFrame( target ) ) {
1350 match = (*parent_match)( template_frame, target, matchsub, template_axes,
1351 target_axes, map, result, status );
1352
1353
1354 /* If the target is a SpecFluxFrame, see if we can convert between target
1355 and template */
1356 } else {
1357
1358 /* We must now decide how the order of the axes in the result Frame relates to
1359 the order of axes in the target Frame. There are two factors involved. The
1360 first depends on whether the axis permutation array for the template
1361 SpecFluxFrame (whose method we are executing) causes an axis
1362 reversal. Determine this by permuting axis index zero. */
1363 swap1 = ( astValidateAxis( template, 0, 1, "astMatch" ) != 0 );
1364
1365 /* The second factor depends on whether the axes of the target SpecFluxFrame
1366 causes an axis reversal. Determine this by permuting axis index zero. */
1367 swap2 = ( astValidateAxis( target, 0, 1, "astMatch" ) != 0 );
1368
1369 /* Combine these to determine if an additional axis swap will be
1370 needed. */
1371 swap = ( swap1 != swap2 );
1372
1373 /* Now check to see if this additional swap is permitted by the template's
1374 Permute attribute. */
1375 match = ( !swap || astGetPermute( template ) );
1376
1377 /* Allocate the target and template axes arrays. */
1378 *template_axes = astMalloc( sizeof(int)*2 );
1379 *target_axes = astMalloc( sizeof(int)*2 );
1380
1381 /* If the Frames still match, we next set up the axis association
1382 arrays. */
1383 if ( astOK && match ) {
1384
1385 /* If the target axis order is to be preserved, then the target axis
1386 association involves no permutation but the template axis
1387 association may involve an axis swap. */
1388 if ( astGetPreserveAxes( template ) ) {
1389 (*template_axes)[ 0 ] = swap;
1390 (*template_axes)[ 1 ] = !swap;
1391 (*target_axes)[ 0 ] = 0;
1392 (*target_axes)[ 1 ] = 1;
1393
1394 /* Otherwise, any swap applies to the target axis association
1395 instead. */
1396 } else {
1397 (*template_axes)[ 0 ] = 0;
1398 (*template_axes)[ 1 ] = 1;
1399 (*target_axes)[ 0 ] = swap;
1400 (*target_axes)[ 1 ] = !swap;
1401 }
1402
1403 /* Use the target's "astSubFrame" method to create a new Frame (the
1404 result Frame) with copies of the target axes in the required
1405 order. This process also overlays the template attributes on to the
1406 target Frame and returns a Mapping between the target and result
1407 Frames which effects the required coordinate conversion. */
1408 match = astSubFrame( target, template, 2, *target_axes, *template_axes,
1409 map, result );
1410
1411 /* If an error occurred, or conversion to the result Frame's
1412 coordinate system was not possible, then free all memory, annul the
1413 returned objects, and reset the returned value. */
1414 if ( !astOK || !match ) {
1415 *template_axes = astFree( *template_axes );
1416 *target_axes = astFree( *target_axes );
1417 if( *map ) *map = astAnnul( *map );
1418 if( *result ) *result = astAnnul( *result );
1419 match = 0;
1420 }
1421 }
1422 }
1423
1424 /* Return the result. */
1425 return match;
1426 }
1427
SubFrame(AstFrame * target_frame,AstFrame * template,int result_naxes,const int * target_axes,const int * template_axes,AstMapping ** map,AstFrame ** result,int * status)1428 static int SubFrame( AstFrame *target_frame, AstFrame *template,
1429 int result_naxes, const int *target_axes,
1430 const int *template_axes, AstMapping **map,
1431 AstFrame **result, int *status ) {
1432 /*
1433 * Name:
1434 * SubFrame
1435
1436 * Purpose:
1437 * Select axes from a SpecFluxFrame and convert to the new coordinate system.
1438
1439 * Type:
1440 * Private function.
1441
1442 * Synopsis:
1443 * #include "specfluxframe.h"
1444 * int SubFrame( AstFrame *target, AstFrame *template,
1445 * int result_naxes, const int *target_axes,
1446 * const int *template_axes, AstMapping **map,
1447 * AstFrame **result, int *status )
1448
1449 * Class Membership:
1450 * SpecFluxFrame member function (over-rides the protected astSubFrame
1451 * method inherited from the Frame class).
1452
1453 * Description:
1454 * This function selects a requested sub-set (or super-set) of the
1455 * axes from a "target" SpecFluxFrame and creates a new Frame with
1456 * copies of the selected axes assembled in the requested order. It
1457 * then optionally overlays the attributes of a "template" Frame on
1458 * to the result. It returns both the resulting Frame and a Mapping
1459 * that describes how to convert between the coordinate systems
1460 * described by the target and result Frames. If necessary, this
1461 * Mapping takes account of any differences in the Frames'
1462 * attributes due to the influence of the template.
1463
1464 * Parameters:
1465 * target
1466 * Pointer to the target SpecFluxFrame, from which axes are to be selected.
1467 * template
1468 * Pointer to the template Frame, from which new attributes for
1469 * the result Frame are to be obtained. Optionally, this may be
1470 * NULL, in which case no overlaying of template attributes will
1471 * be performed.
1472 * result_naxes
1473 * Number of axes to be selected from the target Frame. This
1474 * number may be greater than or less than the number of axes in
1475 * this Frame (or equal).
1476 * target_axes
1477 * Pointer to an array of int with result_naxes elements, giving
1478 * a list of the (zero-based) axis indices of the axes to be
1479 * selected from the target SpecFluxFrame. The order in which these
1480 * are given determines the order in which the axes appear in
1481 * the result Frame. If any of the values in this array is set
1482 * to -1, the corresponding result axis will not be derived from
1483 * the target Frame, but will be assigned default attributes
1484 * instead.
1485 * template_axes
1486 * Pointer to an array of int with result_naxes elements. This
1487 * should contain a list of the template axes (given as
1488 * zero-based axis indices) with which the axes of the result
1489 * Frame are to be associated. This array determines which axes
1490 * are used when overlaying axis-dependent attributes of the
1491 * template on to the result. If any element of this array is
1492 * set to -1, the corresponding result axis will not receive any
1493 * template attributes.
1494 *
1495 * If the template argument is given as NULL, this array is not
1496 * used and a NULL pointer may also be supplied here.
1497 * map
1498 * Address of a location to receive a pointer to the returned
1499 * Mapping. The forward transformation of this Mapping will
1500 * describe how to convert coordinates from the coordinate
1501 * system described by the target SpecFluxFrame to that described by
1502 * the result Frame. The inverse transformation will convert in
1503 * the opposite direction.
1504 * result
1505 * Address of a location to receive a pointer to the result Frame.
1506 * status
1507 * Pointer to the inherited status variable.
1508
1509 * Returned Value:
1510 * A non-zero value is returned if coordinate conversion is
1511 * possible between the target and the result Frame. Otherwise zero
1512 * is returned and *map and *result are returned as NULL (but this
1513 * will not in itself result in an error condition). In general,
1514 * coordinate conversion should always be possible if no template
1515 * Frame is supplied but may not always be possible otherwise.
1516
1517 * Notes:
1518 * - A value of zero will be returned if this function is invoked
1519 * with the global error status set, or if it should fail for any
1520 * reason.
1521
1522 * Implementation Deficiencies:
1523 * - It is not clear that the method of handling "extra" axes is
1524 * the best one, nor is the method of setting the "following" flag
1525 * necessarily correct. However, it is also not obvious that this
1526 * feature will ever be needed, so improvements have been left
1527 * until the requirement is clearer.
1528 */
1529
1530 /* Local Variables: */
1531 AstMapping *tmpmap; /* Temporary Mapping pointer */
1532 AstPermMap *permmap; /* Pointer to PermMap */
1533 AstSpecFluxFrame *target; /* Pointer to target SpecFluxFrame structure */
1534 int match; /* Coordinate conversion is possible? */
1535 int perm[ 2 ]; /* Permutation array for axis swap */
1536 int result_swap; /* Swap result SpecFluxFrame coordinates? */
1537 int target_swap; /* Swap target SpecFluxFrame coordinates? */
1538
1539 /* Initialise the returned values. */
1540 *map = NULL;
1541 *result = NULL;
1542 match = 0;
1543
1544 /* Check the global error status. */
1545 if ( !astOK ) return match;
1546
1547 /* If the template is not a SpecFluxFrame we use the parent SubFrame
1548 method inherited form the CmpFrame class. */
1549 if( !template || !astIsASpecFluxFrame( template ) || result_naxes != 2 ) {
1550 match = (*parent_subframe)( target_frame, template, result_naxes,
1551 target_axes, template_axes, map, result, status );
1552
1553 /* Otherwise... */
1554 } else {
1555
1556 /* Obtain a pointer to the target SpecFluxFrame structure. */
1557 target = (AstSpecFluxFrame *) target_frame;
1558
1559 /* Form the result from a copy of the target and then permute its axes
1560 into the order required. */
1561 *result = astCopy( target );
1562 astPermAxes( *result, target_axes );
1563
1564 /* Overlay the template attributes on to the result SpecFrame. */
1565 astOverlay( template, template_axes, *result );
1566
1567 /* Generate a Mapping that takes account of changes in the coordinate
1568 system (system, units, etc.) between the target SpecFluxFrame and the
1569 result SpecFluxFrame. If this Mapping can be generated, set "match" to
1570 indicate that coordinate conversion is possible. */
1571 match = MakeSFMapping( target, (AstSpecFluxFrame *) *result, map, status );
1572
1573 /* If a Mapping has been obtained, it will expect coordinate values to be
1574 supplied in (flux,spec) pairs. Test whether we need to swap the
1575 order of the target SpecFluxFrame coordinates to conform with this. */
1576 if ( astOK && match ) {
1577 target_swap = ( astValidateAxis( target, 0, 1, "astSubFrame" ) != 0 );
1578
1579 /* Coordinates will also be delivered in (flux,spec) pairs, so check
1580 to see whether the result SpecFluxFrame coordinate order should be
1581 swapped. */
1582 result_swap = ( target_swap != ( target_axes[ 0 ] != 0 ) );
1583
1584 /* If either set of coordinates needs swapping, create a PermMap that
1585 will swap a pair of coordinates. */
1586 permmap = NULL;
1587 if ( target_swap || result_swap ) {
1588 perm[ 0 ] = 1;
1589 perm[ 1 ] = 0;
1590 permmap = astPermMap( 2, perm, 2, perm, NULL, "", status );
1591 }
1592
1593 /* If necessary, prefix this PermMap to the main Mapping. */
1594 if ( target_swap ) {
1595 tmpmap = (AstMapping *) astCmpMap( permmap, *map, 1, "", status );
1596 *map = astAnnul( *map );
1597 *map = tmpmap;
1598 }
1599
1600 /* Also, if necessary, append it to the main Mapping. */
1601 if ( result_swap ) {
1602 tmpmap = (AstMapping *) astCmpMap( *map, permmap, 1, "", status );
1603 *map = astAnnul( *map );
1604 *map = tmpmap;
1605 }
1606
1607 /* Annul the pointer to the PermMap (if created). */
1608 if ( permmap ) permmap = astAnnul( permmap );
1609 }
1610 }
1611
1612 /* If an error occurred, clean up by annulling the result pointers and
1613 returning appropriate null values. */
1614 if ( !astOK ) {
1615 *map = astAnnul( *map );
1616 *result = astAnnul( *result );
1617 match = 0;
1618 }
1619
1620 /* Return the result. */
1621 return match;
1622 }
1623
1624 /* Functions which access class attributes. */
1625 /* ---------------------------------------- */
1626 /* Implement member functions to access the attributes associated with
1627 the axes of a SpecFluxFrame using the private macros defined for this
1628 purpose at the start of this file. */
1629
1630 /* Copy constructor. */
1631 /* ----------------- */
1632
1633 /* Destructor. */
1634 /* ----------- */
1635
1636 /* Dump function. */
1637 /* -------------- */
Dump(AstObject * this_object,AstChannel * channel,int * status)1638 static void Dump( AstObject *this_object, AstChannel *channel, int *status ) {
1639 /*
1640 * Name:
1641 * Dump
1642
1643 * Purpose:
1644 * Dump function for SpecFluxFrame objects.
1645
1646 * Type:
1647 * Private function.
1648
1649 * Synopsis:
1650 * void Dump( AstObject *this, AstChannel *channel, int *status )
1651
1652 * Description:
1653 * This function implements the Dump function which writes out data
1654 * for the SpecFluxFrame class to an output Channel.
1655
1656 * Parameters:
1657 * this
1658 * Pointer to the SpecFluxFrame whose data are being written.
1659 * channel
1660 * Pointer to the Channel to which the data are being written.
1661 * status
1662 * Pointer to the inherited status variable.
1663 */
1664
1665 /* Local Variables: */
1666 AstSpecFluxFrame *this; /* Pointer to the SpecFluxFrame structure */
1667
1668 /* Check the global error status. */
1669 if ( !astOK ) return;
1670
1671 /* Obtain a pointer to the SpecFluxFrame structure. */
1672 this = (AstSpecFluxFrame *) this_object;
1673
1674 /* Write out values representing the instance variables for the
1675 SpecFluxFrame class. Accompany these with appropriate comment strings,
1676 possibly depending on the values being written.*/
1677
1678 /* In the case of attributes, we first use the appropriate (private)
1679 Test... member function to see if they are set. If so, we then use
1680 the (private) Get... function to obtain the value to be written
1681 out.
1682
1683 For attributes which are not set, we use the astGet... method to
1684 obtain the value instead. This will supply a default value
1685 (possibly provided by a derived class which over-rides this method)
1686 which is more useful to a human reader as it corresponds to the
1687 actual default attribute value. Since "set" will be zero, these
1688 values are for information only and will not be read back. */
1689
1690 }
1691
1692 /* Standard class functions. */
1693 /* ========================= */
1694 /* Implement the astIsASpecFluxFrame and astCheckSpecFluxFrame functions using
1695 the macros defined for this purpose in the "object.h" header file. */
astMAKE_ISA(SpecFluxFrame,CmpFrame)1696 astMAKE_ISA(SpecFluxFrame,CmpFrame)
1697 astMAKE_CHECK(SpecFluxFrame)
1698
1699 AstSpecFluxFrame *astSpecFluxFrame_( void *frame1_void, void *frame2_void,
1700 const char *options, int *status, ...) {
1701 /*
1702 *++
1703 * Name:
1704 c astSpecFluxFrame
1705 f AST_SPECFLUXFRAME
1706
1707 * Purpose:
1708 * Create a SpecFluxFrame.
1709
1710 * Type:
1711 * Public function.
1712
1713 * Synopsis:
1714 c #include "specfluxframe.h"
1715 c AstSpecFluxFrame *astSpecFluxFrame( AstSpecFrame *frame1, AstFluxFrame *frame2,
1716 c const char *options, ... )
1717 f RESULT = AST_SPECFLUXFRAME( FRAME1, FRAME2, OPTIONS, STATUS )
1718
1719 * Class Membership:
1720 * SpecFluxFrame constructor.
1721
1722 * Description:
1723 * This function creates a new SpecFluxFrame and optionally initialises
1724 * its attributes.
1725 *
1726 * A SpecFluxFrame combines a SpecFrame and a FluxFrame into a single
1727 * 2-dimensional compound Frame. Such a Frame can for instance be used
1728 * to describe a Plot of a spectrum in which the first axis represents
1729 * spectral position and the second axis represents flux.
1730
1731 * Parameters:
1732 c frame1
1733 f FRAME1 = INTEGER (Given)
1734 * Pointer to the SpecFrame. This will form the first axis in the
1735 * new SpecFluxFrame.
1736 c frame2
1737 f FRAME2 = INTEGER (Given)
1738 * Pointer to the FluxFrame. This will form the second axis in the
1739 * new SpecFluxFrame. The "SpecVal" attribute of this FluxFrame is
1740 * not used by the SpecFluxFrame class and so may be set to AST__BAD
1741 * when the FluxFrame is created.
1742 c options
1743 f OPTIONS = CHARACTER * ( * ) (Given)
1744 c Pointer to a null-terminated string containing an optional
1745 c comma-separated list of attribute assignments to be used for
1746 c initialising the new SpecFluxFrame. The syntax used is identical to
1747 c that for the astSet function and may include "printf" format
1748 c specifiers identified by "%" symbols in the normal way.
1749 f A character string containing an optional comma-separated
1750 f list of attribute assignments to be used for initialising the
1751 f new SpecFluxFrame. The syntax used is identical to that for the
1752 f AST_SET routine.
1753 c ...
1754 c If the "options" string contains "%" format specifiers, then
1755 c an optional list of additional arguments may follow it in
1756 c order to supply values to be substituted for these
1757 c specifiers. The rules for supplying these are identical to
1758 c those for the astSet function (and for the C "printf"
1759 c function).
1760 f STATUS = INTEGER (Given and Returned)
1761 f The global status.
1762
1763 * Returned Value:
1764 c astSpecFluxFrame()
1765 f AST_SPECFLUXFRAME = INTEGER
1766 * A pointer to the new SpecFluxFrame.
1767
1768 * Notes:
1769 * - The supplied Frame pointers are stored directly, rather than
1770 * being used to create deep copies of the supplied Frames. This means
1771 * that any subsequent changes made to the Frames via the supplied
1772 * pointers will result in equivalent changes being visible in the
1773 * SpecFluxFrame.
1774 * - A null Object pointer (AST__NULL) will be returned if this
1775 c function is invoked with the AST error status set, or if it
1776 f function is invoked with STATUS set to an error value, or if it
1777 * should fail for any reason.
1778
1779 * Status Handling:
1780 * The protected interface to this function includes an extra
1781 * parameter at the end of the parameter list descirbed above. This
1782 * parameter is a pointer to the integer inherited status
1783 * variable: "int *status".
1784
1785 *--
1786
1787 * Implementation Notes:
1788 * - This function implements the basic SpecFluxFrame constructor which
1789 * is available via the protected interface to the SpecFluxFrame class.
1790 * A public interface is provided by the astSpecFluxFrameId_ function.
1791 * - Because this function has a variable argument list, it is
1792 * invoked by a macro that evaluates to a function pointer (not a
1793 * function invocation) and no checking or casting of arguments is
1794 * performed before the function is invoked. Because of this, the
1795 * "frame1" and "frame2" parameters are of type (void *) and are
1796 * converted and validated within the function itself.
1797 */
1798
1799 /* Local Variables: */
1800 astDECLARE_GLOBALS /* Pointer to thread-specific global data */
1801 AstSpecFluxFrame *new; /* Pointer to new SpecFluxFrame */
1802 AstFluxFrame *frame2; /* Pointer to FluxFrame structure */
1803 AstSpecFrame *frame1; /* Pointer to SpecFrame structure */
1804 va_list args; /* Variable argument list */
1805
1806 /* Get a pointer to the thread specific global data structure. */
1807 astGET_GLOBALS(NULL);
1808
1809 /* Check the global status. */
1810 new = NULL;
1811 if ( !astOK ) return new;
1812
1813 /* Obtain and validate pointers to the Frame structures provided. */
1814 frame1 = astCheckSpecFrame( frame1_void );
1815 frame2 = astCheckFluxFrame( frame2_void );
1816 if ( astOK ) {
1817
1818 /* Initialise the SpecFluxFrame, allocating memory and initialising the
1819 virtual function table as well if necessary. */
1820 new = astInitSpecFluxFrame( NULL, sizeof( AstSpecFluxFrame ), !class_init,
1821 &class_vtab, "SpecFluxFrame", frame1, frame2 );
1822
1823 /* If successful, note that the virtual function table has been
1824 initialised. */
1825 if ( astOK ) {
1826 class_init = 1;
1827
1828 /* Obtain the variable argument list and pass it along with the
1829 options string to the astVSet method to initialise the new
1830 SpecFluxFrame's attributes. */
1831 va_start( args, status );
1832 astVSet( new, options, NULL, args );
1833 va_end( args );
1834
1835 /* If an error occurred, clean up by deleting the new object. */
1836 if ( !astOK ) new = astDelete( new );
1837 }
1838 }
1839
1840 /* Return a pointer to the new SpecFluxFrame. */
1841 return new;
1842 }
1843
astSpecFluxFrameId_(void * frame1_void,void * frame2_void,const char * options,...)1844 AstSpecFluxFrame *astSpecFluxFrameId_( void *frame1_void, void *frame2_void,
1845 const char *options, ... ) {
1846 /*
1847 * Name:
1848 * astSpecFluxFrameId_
1849
1850 * Purpose:
1851 * Create a SpecFluxFrame.
1852
1853 * Type:
1854 * Private function.
1855
1856 * Synopsis:
1857 * #include "specfluxframe.h"
1858 * AstSpecFluxFrame *astSpecFluxFrameId_( void *frame1_void, void *frame2_void,
1859 * const char *options, ... )
1860
1861 * Class Membership:
1862 * SpecFluxFrame constructor.
1863
1864 * Description:
1865 * This function implements the external (public) interface to the
1866 * astSpecFluxFrame constructor function. It returns an ID value
1867 * (instead of a true C pointer) to external users, and must be
1868 * provided because astSpecFluxFrame_ has a variable argument list which
1869 * cannot be encapsulated in a macro (where this conversion would
1870 * otherwise occur). For the same reason, the "frame1" and "frame2"
1871 * parameters are of type (void *) and are converted and validated
1872 * within the function itself.
1873 *
1874 * The variable argument list also prevents this function from
1875 * invoking astSpecFluxFrame_ directly, so it must be a
1876 * re-implementation of it in all respects, except for the final
1877 * conversion of the result to an ID value.
1878
1879 * Parameters:
1880 * As for astSpecFluxFrame_.
1881
1882 * Returned Value:
1883 * The ID value associated with the new SpecFluxFrame.
1884 */
1885
1886 /* Local Variables: */
1887 astDECLARE_GLOBALS /* Pointer to thread-specific global data */
1888 AstSpecFluxFrame *new; /* Pointer to new SpecFluxFrame */
1889 AstSpecFrame *frame1; /* Pointer to first Frame structure */
1890 AstFluxFrame *frame2; /* Pointer to second Frame structure */
1891 va_list args; /* Variable argument list */
1892
1893 int *status; /* Get a pointer to the thread specific global data structure. */
1894 astGET_GLOBALS(NULL);
1895
1896 /* Pointer to inherited status value */
1897
1898 /* Get a pointer to the inherited status value. */
1899 status = astGetStatusPtr;
1900
1901 /* Check the global status. */
1902 new = NULL;
1903 if ( !astOK ) return new;
1904
1905 /* Obtain the Frame pointers from the ID's supplied and validate the
1906 pointers to ensure they identify valid Frames. */
1907 frame1 = astVerifySpecFrame( astMakePointer( frame1_void ) );
1908 frame2 = astVerifyFluxFrame( astMakePointer( frame2_void ) );
1909 if ( astOK ) {
1910
1911 /* Initialise the SpecFluxFrame, allocating memory and initialising the
1912 virtual function table as well if necessary. */
1913 new = astInitSpecFluxFrame( NULL, sizeof( AstSpecFluxFrame ), !class_init,
1914 &class_vtab, "SpecFluxFrame", frame1, frame2 );
1915
1916 /* If successful, note that the virtual function table has been
1917 initialised. */
1918 if ( astOK ) {
1919 class_init = 1;
1920
1921 /* Obtain the variable argument list and pass it along with the
1922 options string to the astVSet method to initialise the new
1923 SpecFluxFrame's attributes. */
1924 va_start( args, options );
1925 astVSet( new, options, NULL, args );
1926 va_end( args );
1927
1928 /* If an error occurred, clean up by deleting the new object. */
1929 if ( !astOK ) new = astDelete( new );
1930 }
1931 }
1932
1933 /* Return an ID value for the new SpecFluxFrame. */
1934 return astMakeId( new );
1935 }
1936
astInitSpecFluxFrame_(void * mem,size_t size,int init,AstSpecFluxFrameVtab * vtab,const char * name,AstSpecFrame * frame1,AstFluxFrame * frame2,int * status)1937 AstSpecFluxFrame *astInitSpecFluxFrame_( void *mem, size_t size, int init,
1938 AstSpecFluxFrameVtab *vtab, const char *name,
1939 AstSpecFrame *frame1, AstFluxFrame *frame2, int *status ) {
1940 /*
1941 *+
1942 * Name:
1943 * astInitSpecFluxFrame
1944
1945 * Purpose:
1946 * Initialise a SpecFluxFrame.
1947
1948 * Type:
1949 * Protected function.
1950
1951 * Synopsis:
1952 * #include "specfluxframe.h"
1953 * AstSpecFluxFrame *astInitSpecFluxFrame( void *mem, size_t size, int init,
1954 * AstSpecFluxFrameVtab *vtab, const char *name,
1955 * AstSpecFrame *frame1, AstFluxFrame *frame2 )
1956
1957 * Class Membership:
1958 * SpecFluxFrame initialiser.
1959
1960 * Description:
1961 * This function is provided for use by class implementations to
1962 * initialise a new SpecFluxFrame object. It allocates memory (if
1963 * necessary) to accommodate the SpecFluxFrame plus any additional data
1964 * associated with the derived class. It then initialises a
1965 * SpecFluxFrame structure at the start of this memory. If the "init"
1966 * flag is set, it also initialises the contents of a virtual
1967 * function table for a SpecFluxFrame at the start of the memory passed
1968 * via the "vtab" parameter.
1969
1970 * Parameters:
1971 * mem
1972 * A pointer to the memory in which the SpecFluxFrame is to be
1973 * created. This must be of sufficient size to accommodate the
1974 * SpecFluxFrame data (sizeof(SpecFluxFrame)) plus any data used by the
1975 * derived class. If a value of NULL is given, this function
1976 * will allocate the memory itself using the "size" parameter to
1977 * determine its size.
1978 * size
1979 * The amount of memory used by the SpecFluxFrame (plus derived class
1980 * data). This will be used to allocate memory if a value of
1981 * NULL is given for the "mem" parameter. This value is also
1982 * stored in the SpecFluxFrame structure, so a valid value must be
1983 * supplied even if not required for allocating memory.
1984 * init
1985 * A logical flag indicating if the SpecFluxFrame's virtual function
1986 * table is to be initialised. If this value is non-zero, the
1987 * virtual function table will be initialised by this function.
1988 * vtab
1989 * Pointer to the start of the virtual function table to be
1990 * associated with the new SpecFluxFrame.
1991 * name
1992 * Pointer to a constant null-terminated character string which
1993 * contains the name of the class to which the new object
1994 * belongs (it is this pointer value that will subsequently be
1995 * returned by the Object astClass function).
1996 * frame1
1997 * Pointer to the SpecFrame
1998 * frame2
1999 * Pointer to the FluxFrame
2000
2001 * Returned Value:
2002 * A pointer to the new SpecFluxFrame.
2003
2004 * Notes:
2005 * - A null pointer will be returned if this function is invoked
2006 * with the global error status set, or if it should fail for any
2007 * reason.
2008 *-
2009 */
2010
2011 /* Local Variables: */
2012 AstSpecFluxFrame *new; /* Pointer to new SpecFluxFrame */
2013
2014 /* Check the global status. */
2015 if ( !astOK ) return NULL;
2016
2017 /* If necessary, initialise the virtual function table. */
2018 if ( init ) astInitSpecFluxFrameVtab( vtab, name );
2019
2020 /* Initialise a Frame structure (the parent class) as the first
2021 component within the SpecFluxFrame structure, allocating memory if
2022 necessary. Set the number of Frame axes to zero, since all axis
2023 information is stored within the component Frames. */
2024 new = astInitCmpFrame( mem, size, 0, (AstCmpFrameVtab *) vtab, name,
2025 frame1, frame2 );
2026 if ( astOK ) {
2027
2028
2029 /* If an error occurred, clean up by deleting the new object. */
2030 if ( !astOK ) new = astDelete( new );
2031 }
2032
2033 /* Return a pointer to the new object. */
2034 return new;
2035 }
2036
astLoadSpecFluxFrame_(void * mem,size_t size,AstSpecFluxFrameVtab * vtab,const char * name,AstChannel * channel,int * status)2037 AstSpecFluxFrame *astLoadSpecFluxFrame_( void *mem, size_t size,
2038 AstSpecFluxFrameVtab *vtab, const char *name,
2039 AstChannel *channel, int *status ) {
2040 /*
2041 *+
2042 * Name:
2043 * astLoadSpecFluxFrame
2044
2045 * Purpose:
2046 * Load a SpecFluxFrame.
2047
2048 * Type:
2049 * Protected function.
2050
2051 * Synopsis:
2052 * #include "specfluxframe.h"
2053 * AstSpecFluxFrame *astLoadSpecFluxFrame( void *mem, size_t size,
2054 * AstSpecFluxFrameVtab *vtab, const char *name,
2055 * AstChannel *channel )
2056
2057 * Class Membership:
2058 * SpecFluxFrame loader.
2059
2060 * Description:
2061 * This function is provided to load a new SpecFluxFrame using data read
2062 * from a Channel. It first loads the data used by the parent class
2063 * (which allocates memory if necessary) and then initialises a
2064 * SpecFluxFrame structure in this memory, using data read from the
2065 * input Channel.
2066
2067 * Parameters:
2068 * mem
2069 * A pointer to the memory into which the SpecFluxFrame is to be
2070 * loaded. This must be of sufficient size to accommodate the
2071 * SpecFluxFrame data (sizeof(SpecFluxFrame)) plus any data used by
2072 * derived classes. If a value of NULL is given, this function
2073 * will allocate the memory itself using the "size" parameter to
2074 * determine its size.
2075 * size
2076 * The amount of memory used by the SpecFluxFrame (plus derived class
2077 * data). This will be used to allocate memory if a value of
2078 * NULL is given for the "mem" parameter. This value is also
2079 * stored in the SpecFluxFrame structure, so a valid value must be
2080 * supplied even if not required for allocating memory.
2081 *
2082 * If the "vtab" parameter is NULL, the "size" value is ignored
2083 * and sizeof(AstSpecFluxFrame) is used instead.
2084 * vtab
2085 * Pointer to the start of the virtual function table to be
2086 * associated with the new SpecFluxFrame. If this is NULL, a pointer
2087 * to the (static) virtual function table for the SpecFluxFrame class
2088 * is used instead.
2089 * name
2090 * Pointer to a constant null-terminated character string which
2091 * contains the name of the class to which the new object
2092 * belongs (it is this pointer value that will subsequently be
2093 * returned by the astGetClass method).
2094 *
2095 * If the "vtab" parameter is NULL, the "name" value is ignored
2096 * and a pointer to the string "SpecFluxFrame" is used instead.
2097
2098 * Returned Value:
2099 * A pointer to the new SpecFluxFrame.
2100
2101 * Notes:
2102 * - A null pointer will be returned if this function is invoked
2103 * with the global error status set, or if it should fail for any
2104 * reason.
2105 *-
2106 */
2107
2108 /* Local Constants: */
2109 astDECLARE_GLOBALS /* Pointer to thread-specific global data */
2110 #define KEY_LEN 50 /* Maximum length of a keyword */
2111
2112 /* Local Variables: */
2113 AstSpecFluxFrame *new; /* Pointer to the new SpecFluxFrame */
2114
2115 /* Initialise. */
2116 new = NULL;
2117
2118 /* Get a pointer to the thread specific global data structure. */
2119 astGET_GLOBALS(channel);
2120
2121 /* Check the global error status. */
2122 if ( !astOK ) return new;
2123
2124 /* If a NULL virtual function table has been supplied, then this is
2125 the first loader to be invoked for this SpecFluxFrame. In this case the
2126 SpecFluxFrame belongs to this class, so supply appropriate values to be
2127 passed to the parent class loader (and its parent, etc.). */
2128 if ( !vtab ) {
2129 size = sizeof( AstSpecFluxFrame );
2130 vtab = &class_vtab;
2131 name = "SpecFluxFrame";
2132
2133 /* If required, initialise the virtual function table for this class. */
2134 if ( !class_init ) {
2135 astInitSpecFluxFrameVtab( vtab, name );
2136 class_init = 1;
2137 }
2138 }
2139
2140 /* Invoke the parent class loader to load data for all the ancestral
2141 classes of the current one, returning a pointer to the resulting
2142 partly-built SpecFluxFrame. */
2143 new = astLoadCmpFrame( mem, size, (AstCmpFrameVtab *) vtab, name,
2144 channel );
2145
2146 if ( astOK ) {
2147
2148 /* Read input data. */
2149 /* ================ */
2150 /* Request the input Channel to read all the input data appropriate to
2151 this class into the internal "values list". */
2152 astReadClassData( channel, "SpecFluxFrame" );
2153
2154 /* Now read each individual data item from this list and use it to
2155 initialise the appropriate instance variable(s) for this class. */
2156
2157 /* In the case of attributes, we first read the "raw" input value,
2158 supplying the "unset" value as the default. If a "set" value is
2159 obtained, we then use the appropriate (private) Set... member
2160 function to validate and set the value properly. */
2161 /* (none) */
2162
2163 /* If an error occurred, clean up by deleting the new SpecFluxFrame. */
2164 if ( !astOK ) new = astDelete( new );
2165 }
2166
2167 /* Return the new SpecFluxFrame pointer. */
2168 return new;
2169
2170 /* Undefine macros local to this function. */
2171 #undef KEY_LEN
2172 }
2173
2174 /* Virtual function interfaces. */
2175 /* ============================ */
2176 /* These provide the external interface to the virtual functions defined by
2177 this class. Each simply checks the global error status and then locates and
2178 executes the appropriate member function, using the function pointer stored
2179 in the object's virtual function table (this pointer is located using the
2180 astMEMBER macro defined in "object.h").
2181
2182 Note that the member function may not be the one defined here, as it may
2183 have been over-ridden by a derived class. However, it should still have the
2184 same interface. */
2185
2186
2187
2188
2189
2190