GIRAFFE Pipeline Reference Manual

gigrating.c
1/*
2 * This file is part of the GIRAFFE Pipeline
3 * Copyright (C) 2002-2019 European Southern Observatory
4 *
5 * This program is free software; you can redistribute it and/or modify
6 * it under the terms of the GNU General Public License as published by
7 * the Free Software Foundation; either version 2 of the License, or
8 * (at your option) any later version.
9 *
10 * This program is distributed in the hope that it will be useful,
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 * GNU General Public License for more details.
14 *
15 * You should have received a copy of the GNU General Public License
16 * along with this program; if not, write to the Free Software
17 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
18 */
19
20#ifdef HAVE_CONFIG_H
21# include <config.h>
22#endif
23
24#include <math.h>
25
26#include <cxmemory.h>
27#include <cxmessages.h>
28
29#include "gimacros.h"
30#include "gialias.h"
31#include "gigrating.h"
32
33#define GIFITS_KEYWORD_MISSING_MSG "FITS KEYWORD [%s] not found!! Aborting..."
34
35
44static const cxdouble GI_WAVELENGTH_EPSILON = 1.e-8; /* 1.e-4 */
45
46
47inline static cxint
48_giraffe_grating_copy(GiGrating *self, cpl_table *grating, cxint row,
49 GiInstrumentMode mode)
50{
51
52 const cxchar *c_resolution = NULL;
53
54
55 cx_assert(self != NULL);
56 cx_assert(grating != NULL);
57
58
59 if (row >= cpl_table_get_nrow(grating)) {
60 return 1;
61 }
62
63
64 if (!cpl_table_has_column(grating, "ORDER")) {
65 return 2;
66 }
67 else {
68 self->order = cpl_table_get_int(grating, "ORDER", row, NULL);
69 }
70
71
72 if (!cpl_table_has_column(grating, "WLEN0")) {
73 return 2;
74 }
75 else {
76 self->wlen0 = cpl_table_get_double(grating, "WLEN0", row, NULL);
77 }
78
79
80 if (!cpl_table_has_column(grating, "WLMIN")) {
81 return 2;
82 }
83 else {
84 self->wlenmin = cpl_table_get_double(grating, "WLMIN", row, NULL);
85 }
86
87
88 if (!cpl_table_has_column(grating, "WLMAX")) {
89 return 2;
90 }
91 else {
92 self->wlenmax = cpl_table_get_double(grating, "WLMAX", row, NULL);
93 }
94
95
96 if (!cpl_table_has_column(grating, "BAND")) {
97 return 2;
98 }
99 else {
100 self->band = cpl_table_get_double(grating, "BAND", row, NULL);
101 }
102
103
104 switch (mode) {
105 case GIMODE_MEDUSA:
106 c_resolution = "RMED";
107 break;
108
109 case GIMODE_IFU:
110 case GIMODE_ARGUS:
111 c_resolution = "RIFA";
112 break;
113
114 default:
115 return 3;
116 break;
117 }
118
119 if (!cpl_table_has_column(grating, c_resolution)) {
120 return 2;
121 }
122 else {
123 self->resol = cpl_table_get_int(grating, c_resolution, row, NULL);
124 }
125
126
127 if (!cpl_table_has_column(grating, "THETA")) {
128 return 2;
129 }
130 else {
131 self->theta = cpl_table_get_double(grating, "THETA", row, NULL);
132 }
133
134
135 if (!cpl_table_has_column(grating, "FCOLL")) {
136 return 2;
137 }
138 else {
139 self->fcoll = cpl_table_get_double(grating, "FCOLL", row, NULL);
140 }
141
142
143 if (!cpl_table_has_column(grating, "GCAM")) {
144 return 2;
145 }
146 else {
147 self->gcam = cpl_table_get_double(grating, "GCAM", row, NULL);
148 }
149
150
151 if (!cpl_table_has_column(grating, "SDX")) {
152 return 2;
153 }
154 else {
155 self->sdx = cpl_table_get_double(grating, "SDX", row, NULL);
156 }
157
158
159 if (!cpl_table_has_column(grating, "SDY")) {
160 return 2;
161 }
162 else {
163 self->sdy = cpl_table_get_double(grating, "SDY", row, NULL);
164 }
165
166
167 if (!cpl_table_has_column(grating, "SPHI")) {
168 return 2;
169 }
170 else {
171 self->sphi = cpl_table_get_double(grating, "SPHI", row, NULL);
172 }
173
174 return 0;
175
176}
177
178
188GiGrating *
190{
191
192 GiGrating *grating = (GiGrating *) cx_calloc(1, sizeof *grating);
193
194 grating->name = cx_string_new();
195 grating->setup = cx_string_new();
196 grating->filter = cx_string_new();
197 grating->slit = cx_string_new();
198
199 return grating;
200
201}
202
203
220GiGrating *
221giraffe_grating_create(const GiImage *spectra, const GiTable *grating)
222{
223
224 const cxchar *const c_setup = "SETUP";
225
226 const cxchar *setup = NULL;
227
228 cxint i;
229 cxint order;
230 cxint row = -1;
231 cxint status = 0;
232
233 cxdouble wlen0;
234
235 cpl_propertylist *properties = NULL;
236
237 cpl_table *_grating = NULL;
238
239 GiGrating *self = NULL;
240
241 GiInstrumentMode mode;
242
243
244
245 if (spectra == NULL || grating == NULL) {
246 return NULL;
247 }
248
249 properties = giraffe_image_get_properties(spectra);
250
251 if (properties == NULL) {
252 return NULL;
253 }
254
255 _grating = giraffe_table_get(grating);
256
257 if (_grating == NULL) {
258 return NULL;
259 }
260
261
262 /*
263 * Get instrument setup information from the reference image
264 * and fill the grating setup structure with the appropriate
265 * data from the grating table. The central wavelength and the
266 * order information provided by the reference image is used
267 * to select the grating data.
268 */
269
270 self = giraffe_grating_new();
271
272 /* Grating name */
273
274 if (!cpl_propertylist_has(properties, GIALIAS_GRATNAME)) {
276 return NULL;
277 }
278 else {
279 cx_string_set(self->name,
280 cpl_propertylist_get_string(properties,
281 GIALIAS_GRATNAME));
282 }
283
284 /* Order sorting filter name */
285
286 if (!cpl_propertylist_has(properties, GIALIAS_FILTNAME)) {
288 return NULL;
289 }
290 else {
291 cx_string_set(self->filter,
292 cpl_propertylist_get_string(properties,
293 GIALIAS_FILTNAME));
294 }
295
296 /* Slit name */
297
298 if (!cpl_propertylist_has(properties, GIALIAS_SLITNAME)) {
300 return NULL;
301 }
302 else {
303 cx_string_set(self->slit,
304 cpl_propertylist_get_string(properties,
305 GIALIAS_SLITNAME));
306 }
307
308 /* Spacing of grating grooves */
309
310 if (!cpl_propertylist_has(properties, GIALIAS_GRATGRV)) {
312 return NULL;
313 }
314 else {
315
316 cxdouble grooves = cpl_propertylist_get_double(properties,
317 GIALIAS_GRATGRV);
318 self->space = 1. / fabs(GI_MM_TO_NM * grooves);
319
320 }
321
322 /* Instrument mode */
323
324 mode = giraffe_get_mode(properties);
325
326
327 /*
328 * Select the grating data for the current setup
329 */
330
331 if (!cpl_table_has_column(_grating, "ORDER") ||
332 !cpl_table_has_column(_grating, "WLEN0")) {
333
335 return NULL;
336
337 }
338
339 if (!cpl_propertylist_has(properties, GIALIAS_GRATWLEN)) {
341 return NULL;
342 }
343 else {
344 wlen0 = cpl_propertylist_get_double(properties, GIALIAS_GRATWLEN);
345 }
346
347 if (!cpl_propertylist_has(properties, GIALIAS_GRATORDER)) {
349 return NULL;
350 }
351 else {
352 order = cpl_propertylist_get_int(properties, GIALIAS_GRATORDER);
353 }
354
355
356 for (i = 0; i < cpl_table_get_nrow(_grating); i++) {
357
358 cxint _order = cpl_table_get_int(_grating, "ORDER", i, NULL);
359
360 if (order == _order) {
361
362 cxdouble _wlen0 = cpl_table_get_double(_grating, "WLEN0",
363 i, NULL);
364
365 if (fabs(wlen0 - _wlen0) < GI_WAVELENGTH_EPSILON) {
366 row = i;
367 break;
368 }
369
370 }
371
372 }
373
374 if (row < 0) {
376 return NULL;
377 }
378
379 /*
380 * Try to figure out the setup identifier.
381 */
382
383 /* FIXME: Check whether we can live with an empty setup string
384 * at later stages of the wavelength calibration.
385 */
386
387 if (cpl_propertylist_has(properties, GIALIAS_SETUPNAME)) {
388 setup = cpl_propertylist_get_string(properties, GIALIAS_SETUPNAME);
389 cx_string_set(self->setup, setup);
390 }
391 else {
392 if (cpl_table_has_column(_grating, c_setup)) {
393 setup = cpl_table_get_string(_grating, c_setup, row);
394 cx_string_set(self->setup, setup);
395 }
396 }
397
398
399 status = _giraffe_grating_copy(self, _grating, row, mode);
400
401 if (status != 0) {
403 return NULL;
404 }
405
406 return self;
407
408}
409
410
423void
425{
426
427 if (self == NULL) {
428 return;
429 }
430
431 if (self->name != NULL) {
432 cx_string_delete(self->name);
433 }
434
435 if (self->setup != NULL) {
436 cx_string_delete(self->setup);
437 }
438
439 if (self->filter != NULL) {
440 cx_string_delete(self->filter);
441 }
442
443 if (self->slit != NULL) {
444 cx_string_delete(self->slit);
445 }
446
447 cx_free(self);
448
449 return;
450
451}
452
453
476cxint
477giraffe_grating_setup(GiTable *grating_table, GiImage *spectra,
478 GiGrating *grating_setup)
479{
480
481 const cxchar* const fctid = "giraffe_grating_setup";
482
483 const cxchar* c_name_setup = "SETUP";
484 const cxchar* c_name_order = "ORDER";
485 const cxchar* c_name_wl0 = "WLEN0";
486 const cxchar* c_name_wlmin = "WLMIN";
487 const cxchar* c_name_wlmax = "WLMAX";
488 const cxchar* c_name_band = "BAND";
489 const cxchar* c_name_theta = "THETA";
490 const cxchar* c_name_fcoll = "FCOLL";
491 const cxchar* c_name_gcam = "GCAM";
492 const cxchar* c_name_sdx = "SDX";
493 const cxchar* c_name_sdy = "SDY";
494 const cxchar* c_name_sdphi = "SPHI";
495 const cxchar* c_name_rmed = "RMED";
496 const cxchar* c_name_rifa = "RIFA";
497
498 cxint i = 0;
499 cxint row_match = 0;
500 cxint row_nulls = 0;
501
502 cxdouble wlen_match = 0.;
503 cxdouble wlen = 0.;
504 cxdouble tmp_gratgrv = 0.;
505
506
507 cx_string* slit_name = NULL;
508
509 cpl_propertylist* ref_plimg = NULL;
510
511 cpl_table* ref_gtable = NULL;
512
513 GiInstrumentMode instrument_mode;
514
515
516 /************************************************************************
517 Preprocessing
518 ************************************************************************/
519
520 if (grating_table == NULL) {
521 return 1;
522 }
523
524 if (spectra == NULL) {
525 return 1;
526 }
527
528 if (grating_setup == NULL) {
529 return 1;
530 }
531
532 ref_plimg = giraffe_image_get_properties(spectra);
533 if (ref_plimg == NULL) {
534 return 128;
535 }
536
537 ref_gtable = giraffe_table_get(grating_table);
538 if (ref_gtable == NULL) {
539 return 128;
540 }
541
542 slit_name = cx_string_new();
543
544 /************************************************************************
545 Processing
546 ************************************************************************/
547
548 /*
549 * Retrieve Grating information from associated image...
550 */
551
552 if (cpl_propertylist_has(ref_plimg, GIALIAS_GRATWLEN) == FALSE) {
553 cpl_msg_error(fctid, GIFITS_KEYWORD_MISSING_MSG, GIALIAS_GRATWLEN);
554 cx_string_delete(slit_name);
555 return 2;
556 }
557 else {
558 grating_setup->wlen0 = cpl_propertylist_get_double(ref_plimg,
559 GIALIAS_GRATWLEN);
560 }
561
562 if (cpl_propertylist_has(ref_plimg, GIALIAS_SLITNAME) == FALSE) {
563 cpl_msg_error(fctid, GIFITS_KEYWORD_MISSING_MSG, GIALIAS_SLITNAME);
564 cx_string_delete(slit_name);
565 return 2;
566 }
567 else {
568 cx_string_set(slit_name,
569 cpl_propertylist_get_string(ref_plimg,
570 GIALIAS_SLITNAME));
571 }
572
573 if (cpl_propertylist_has(ref_plimg, GIALIAS_GRATGRV) == FALSE) {
574 cpl_msg_error(fctid, GIFITS_KEYWORD_MISSING_MSG, GIALIAS_GRATGRV);
575 cx_string_delete(slit_name);
576 return 2;
577 }
578 else {
579 tmp_gratgrv = cpl_propertylist_get_double(ref_plimg,
580 GIALIAS_GRATGRV);
581 }
582
583 if (cpl_propertylist_has(ref_plimg, GIALIAS_GRATNAME) == FALSE) {
584 cpl_msg_error(fctid, GIFITS_KEYWORD_MISSING_MSG, GIALIAS_GRATNAME);
585 cx_string_delete(slit_name);
586 return 2;
587 }
588 else {
589 cx_string_set(grating_setup->name,
590 cpl_propertylist_get_string(ref_plimg,
591 GIALIAS_GRATNAME));
592 }
593
594 if (cpl_propertylist_has(ref_plimg, GIALIAS_FILTNAME) == FALSE) {
595 cpl_msg_error(fctid, GIFITS_KEYWORD_MISSING_MSG, GIALIAS_FILTNAME);
596 cx_string_delete(slit_name);
597 return 2;
598 }
599 else {
600 cx_string_set(grating_setup->filter,
601 cpl_propertylist_get_string(ref_plimg,
602 GIALIAS_FILTNAME));
603 }
604
605
606 /*
607 * Find wavelength nearest to central wavelength...
608 */
609
610 for (i = 0; i < cpl_table_get_nrow(ref_gtable); i++) {
611
612 wlen = cpl_table_get(ref_gtable, c_name_wl0, i, &row_nulls);
613
614 if (fabs(wlen - grating_setup->wlen0) <
615 fabs(wlen_match - grating_setup->wlen0)) {
616 wlen_match = wlen;
617 row_match = i;
618 }
619
620 }
621
622
623 /*
624 * Have we found a match?...
625 */
626
627 if (fabs(wlen_match - grating_setup->wlen0) > GI_WAVELENGTH_EPSILON) {
628
629 cpl_msg_error(fctid, "Central wavelength [%f] nout found in grating "
630 "table, aborting...", grating_setup->wlen0);
631 cx_string_delete(slit_name);
632 return 3;
633 }
634 else {
635 cpl_msg_debug(fctid, "Found wlen0 in grating table at position %d",
636 row_match);
637 }
638
639
640 /*
641 * Retrieve values associated to matched wavelength from
642 * grating table...
643 */
644
645 cx_string_set(grating_setup->setup,
646 (cxchar*) cpl_table_get_string(ref_gtable, c_name_setup,
647 row_match));
648
649 cx_string_set(grating_setup->slit, cx_string_get(slit_name));
650
651 grating_setup->order = cpl_table_get(ref_gtable, c_name_order,
652 row_match, &row_nulls);
653
654 grating_setup->wlenmin = cpl_table_get(ref_gtable, c_name_wlmin,
655 row_match, &row_nulls);
656
657 grating_setup->wlenmax = cpl_table_get(ref_gtable, c_name_wlmax,
658 row_match, &row_nulls);
659
660 grating_setup->band = cpl_table_get(ref_gtable, c_name_band,
661 row_match, &row_nulls);
662
663 grating_setup->theta = cpl_table_get(ref_gtable, c_name_theta,
664 row_match, &row_nulls);
665
666 grating_setup->space = 1.0 / fabs(GI_MM_TO_NM * tmp_gratgrv);
667
668
669 instrument_mode = giraffe_get_mode(ref_plimg);
670
671 switch (instrument_mode) {
672 case GIMODE_MEDUSA:
673 grating_setup->resol = cpl_table_get(ref_gtable, c_name_rmed,
674 row_match, &row_nulls);
675 break;
676
677 case GIMODE_IFU:
678 grating_setup->resol = cpl_table_get(ref_gtable, c_name_rifa,
679 row_match, &row_nulls);
680 break;
681
682 case GIMODE_ARGUS:
683 grating_setup->resol = cpl_table_get(ref_gtable, c_name_rifa,
684 row_match, &row_nulls);
685 break;
686
687 default:
688 grating_setup->resol = -1.0;
689 break;
690 }
691
692 grating_setup->fcoll =
693 cpl_table_get(ref_gtable, c_name_fcoll, row_match, &row_nulls);
694
695 grating_setup->gcam =
696 cpl_table_get(ref_gtable, c_name_gcam, row_match, &row_nulls);
697
698 grating_setup->sdx =
699 cpl_table_get(ref_gtable, c_name_sdx, row_match, &row_nulls);
700
701 grating_setup->sdy =
702 cpl_table_get(ref_gtable, c_name_sdy, row_match, &row_nulls);
703
704 grating_setup->sphi =
705 cpl_table_get(ref_gtable, c_name_sdphi, row_match, &row_nulls);
706
707 cx_string_delete(slit_name);
708
709 return 0;
710
711}
712
713
724void
726{
727
728 const cxchar *fctid = "giraffe_grating_dump";
729
730 if (grating == NULL) {
731 return;
732 }
733
734 cpl_msg_debug(fctid, "---- GiGrating -------------------------");
735
736 cpl_msg_debug(fctid, "Grating Name : %s",
737 cx_string_get(grating->name));
738 cpl_msg_debug(fctid, "Grating Filter Name : %s",
739 cx_string_get(grating->filter));
740 cpl_msg_debug(fctid, "Grating Setup Name : %s",
741 cx_string_get(grating->setup));
742 cpl_msg_debug(fctid, "Grating Order : %12d", grating->order);
743 cpl_msg_debug(fctid, "Grating Wlen0 : %12.6f", grating->wlen0);
744 cpl_msg_debug(fctid, "Grating Wlen Min : %12.6f", grating->wlenmin);
745 cpl_msg_debug(fctid, "Grating Wlen Max : %12.6f", grating->wlenmax);
746 cpl_msg_debug(fctid, "Grating Band : %12.6f", grating->band);
747 cpl_msg_debug(fctid, "Grating Resol : %12d", grating->resol);
748 cpl_msg_debug(fctid, "Grating Space : %12.6f", grating->space);
749 cpl_msg_debug(fctid, "Grating Theta : %12.6f", grating->theta);
750 cpl_msg_debug(fctid, "Grating FColl : %12.6f", grating->fcoll);
751 cpl_msg_debug(fctid, "Grating GCam : %12.6f", grating->gcam);
752 cpl_msg_debug(fctid, "Grating SlitDx : %12.6f", grating->sdx);
753 cpl_msg_debug(fctid, "Grating SlitDy : %12.6f", grating->sdy);
754 cpl_msg_debug(fctid, "Grating SlitPhi : %12.6f", grating->sphi);
755
756 return;
757
758}
cxint giraffe_grating_setup(GiTable *grating_table, GiImage *spectra, GiGrating *grating_setup)
Retrieves grating information and returns it in a GiGrating structure.
Definition: gigrating.c:477
void giraffe_grating_dump(const GiGrating *grating)
Dump the the information contained in a GiGrating to output.
Definition: gigrating.c:725
GiGrating * giraffe_grating_new(void)
Create a new GiGrating.
Definition: gigrating.c:189
GiGrating * giraffe_grating_create(const GiImage *spectra, const GiTable *grating)
Create a GiGrating from a reference image.
Definition: gigrating.c:221
void giraffe_grating_delete(GiGrating *self)
Destroys an GiGrating object.
Definition: gigrating.c:424
cpl_propertylist * giraffe_image_get_properties(const GiImage *self)
Get the properties of an image.
Definition: giimage.c:282
cpl_table * giraffe_table_get(const GiTable *self)
Get the table data from a Giraffe table.
Definition: gitable.c:433
GiInstrumentMode giraffe_get_mode(cpl_propertylist *properties)
Determines the instrument mode from a property list.
Definition: giutils.c:444
Structure to handle Grating Information.
Definition: gigrating.h:44
cxdouble wlenmax
Definition: gigrating.h:52
cxdouble sdy
Definition: gigrating.h:60
cx_string * name
Definition: gigrating.h:46
cx_string * setup
Definition: gigrating.h:45
cxdouble space
Definition: gigrating.h:55
cxdouble fcoll
Definition: gigrating.h:57
cxdouble wlen0
Definition: gigrating.h:50
cxdouble sdx
Definition: gigrating.h:59
cxint resol
Definition: gigrating.h:54
cxdouble gcam
Definition: gigrating.h:58
cx_string * slit
Definition: gigrating.h:48
cxdouble band
Definition: gigrating.h:53
cxdouble wlenmin
Definition: gigrating.h:51
cxdouble sphi
Definition: gigrating.h:61
cxint order
Definition: gigrating.h:49
cx_string * filter
Definition: gigrating.h:47
cxdouble theta
Definition: gigrating.h:56

This file is part of the GIRAFFE Pipeline Reference Manual 2.19.4.
Documentation copyright © 2002-2006 European Southern Observatory.
Generated on Fri Feb 6 2026 13:47:22 by doxygen 1.9.6 written by Dimitri van Heesch, © 1997-2004