GIRAFFE Pipeline Reference Manual

giutils.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#ifdef HAVE_SYS_TYPES_H
25# include <sys/types.h>
26#endif
27#include <time.h>
28#include <string.h>
29#include <regex.h>
30
31#include <cxstring.h>
32#include <cxstrutils.h>
33
34#include <cpl_msg.h>
35#include <cpl_error.h>
36#include <cpl_errorstate.h>
37#include <cpl_matrix.h>
38#include <cpl_version.h>
39
40#include "gialias.h"
41#include "gitable.h"
42#include "gimessages.h"
43#include "gierror.h"
44#include "giutils.h"
45
46
55/*
56 * Giraffe version and license
57 */
58
59static const cxchar *_giraffe_license =
60 " This file is part of the GIRAFFE Instrument Pipeline\n"
61 " Copyright (C) 2002-2014 European Southern Observatory\n"
62 "\n"
63 " This program is free software; you can redistribute it and/or modify\n"
64 " it under the terms of the GNU General Public License as published by\n"
65 " the Free Software Foundation; either version 2 of the License, or\n"
66 " (at your option) any later version.\n"
67 "\n"
68 " This program is distributed in the hope that it will be useful,\n"
69 " but WITHOUT ANY WARRANTY; without even the implied warranty of\n"
70 " MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the\n"
71 " GNU General Public License for more details.\n"
72 "\n"
73 " You should have received a copy of the GNU General Public License\n"
74 " along with this program; if not, write to the Free Software\n"
75 " Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301"
76 " USA";
77
78
79inline static cxint
80_giraffe_plist_append(cpl_propertylist *self, cpl_property *p)
81{
82
83 const cxchar *name = cpl_property_get_name(p);
84 const cxchar *comment = cpl_property_get_comment(p);
85
86
87 switch (cpl_property_get_type(p)) {
88 case CPL_TYPE_BOOL:
89 {
90 cxbool value = cpl_property_get_bool(p);
91
92 cpl_propertylist_append_bool(self, name, value);
93 break;
94 }
95
96 case CPL_TYPE_CHAR:
97 {
98 cxchar value = cpl_property_get_char(p);
99
100 cpl_propertylist_append_char(self, name, value);
101 break;
102 }
103
104 case CPL_TYPE_INT:
105 {
106 cxint value = cpl_property_get_int(p);
107
108 cpl_propertylist_append_int(self, name, value);
109 break;
110 }
111
112 case CPL_TYPE_LONG:
113 {
114 cxlong value = cpl_property_get_long(p);
115
116 cpl_propertylist_append_long(self, name, value);
117 break;
118 }
119
120 case CPL_TYPE_FLOAT:
121 {
122 cxfloat value = cpl_property_get_float(p);
123
124 cpl_propertylist_append_float(self, name, value);
125 break;
126 }
127
128 case CPL_TYPE_DOUBLE:
129 {
130 cxdouble value = cpl_property_get_double(p);
131
132 cpl_propertylist_append_double(self, name, value);
133 break;
134 }
135
136 case CPL_TYPE_STRING:
137 {
138 const cxchar *value = cpl_property_get_string(p);
139
140 cpl_propertylist_append_string(self, name, value);
141 break;
142 }
143
144 default:
145
146 /*
147 * We should never reach this point! Since the property
148 * was a valid property it has a valid type. But this
149 * protects against addition of new types.
150 */
151
152 return 1;
153 break;
154 }
155
156 if (comment != NULL) {
157 cpl_propertylist_set_comment(self, name, comment);
158 }
159
160 return 0;
161
162}
163
164
165inline static cxint
166_giraffe_add_frame_info(cpl_propertylist *plist, const cxchar *name,
167 const cxchar *tag, cxint sequence, cxint frame_index,
168 cxint mode)
169{
170
171 const cxchar *id = NULL;
172 const cxchar *group = NULL;
173
174 cxint status = 0;
175
176 cx_string *key = NULL;
177 cx_string *comment = NULL;
178
179
180 if (plist == NULL) {
181 return 1;
182 }
183
184 switch (mode) {
185 case 0:
186 id = "RAW";
187 group = "raw";
188 break;
189
190 case 1:
191 id = "CAL";
192 group = "calibration";
193 break;
194
195 default:
196 return 2;
197 break;
198 }
199
200 key = cx_string_new();
201 comment = cx_string_new();
202
203
204 /*
205 * Frame name
206 */
207
208 cx_string_sprintf(key, "%s%-d %s%-d %s", "ESO PRO REC", sequence, id,
209 frame_index, "NAME");
210 cx_string_sprintf(comment, "%s %s %s", "File name of", group, "frame");
211
212 status = cpl_propertylist_update_string(plist, cx_string_get(key), name);
213
214 if (status != CPL_ERROR_NONE) {
215 cx_string_delete(key);
216 cx_string_delete(comment);
217
218 return 3;
219 }
220
221 status = cpl_propertylist_set_comment(plist, cx_string_get(key),
222 cx_string_get(comment));
223
224 if (status != 0) {
225 cx_string_delete(key);
226 cx_string_delete(comment);
227
228 return 3;
229 }
230
231
232 /*
233 * Frame category
234 */
235
236 cx_string_sprintf(key, "%s%-d %s%-d %s", "ESO PRO REC", sequence, id,
237 frame_index, "CATG");
238 cx_string_sprintf(comment, "%s %s %s", "Frame category of", group,
239 "frame");
240
241 status = cpl_propertylist_update_string(plist, cx_string_get(key), tag);
242
243 if (status != CPL_ERROR_NONE) {
244 cx_string_delete(key);
245 cx_string_delete(comment);
246
247 return 4;
248 }
249
250 status = cpl_propertylist_set_comment(plist, cx_string_get(key),
251 cx_string_get(comment));
252
253 if (status != 0) {
254 cx_string_delete(key);
255 cx_string_delete(comment);
256
257 return 4;
258 }
259
260 cx_string_delete(key);
261 cx_string_delete(comment);
262
263 return 0;
264
265}
266
267
268inline static cxint
269_giraffe_add_option_info(cpl_propertylist *plist,
270 const cpl_parameterlist *options, cxint sequence)
271{
272 cx_assert(plist != NULL);
273 cx_assert(options != NULL);
274 cx_assert(sequence >= 1);
275
276 cx_string *key = cx_string_new();
277 cx_string *comment = cx_string_new();
278
279 cxint pcount = 0;
280 const cpl_parameter *p = cpl_parameterlist_get_first_const(options);
281
282 if (p == NULL) {
283 cx_string_delete(key);
284 cx_string_delete(comment);
285 return 1;
286 }
287
288 while (p != NULL) {
289
290 cxint status = 0;
291 const cxchar *alias = cpl_parameter_get_alias(p, CPL_PARAMETER_MODE_CLI);
292 cx_string *value = cx_string_new();
293 cx_string *preset = cx_string_new();
294
295 switch (cpl_parameter_get_type(p)) {
296 case CPL_TYPE_BOOL:
297 {
298 int bval = cpl_parameter_get_bool(p);
299 cx_string_sprintf(value, "%s", (bval == 1) ? "true" : "false");
300
301 bval = cpl_parameter_get_default_bool(p);
302 cx_string_sprintf(preset, "%s", (bval == 1) ? "true" : "false");
303 break;
304 }
305 case CPL_TYPE_INT:
306 {
307 cx_string_sprintf(value, "%d", cpl_parameter_get_int(p));
308 cx_string_sprintf(preset, "%d", cpl_parameter_get_default_int(p));
309 break;
310 }
311 case CPL_TYPE_DOUBLE:
312 {
313 cx_string_sprintf(value, "%g", cpl_parameter_get_double(p));
314 cx_string_sprintf(preset, "%g", cpl_parameter_get_default_double(p));
315 break;
316 }
317 case CPL_TYPE_STRING:
318 {
319 cx_string_sprintf(value, "%s", cpl_parameter_get_string(p));
320 cx_string_sprintf(preset, "%s", cpl_parameter_get_default_string(p));
321 break;
322 }
323 default:
324 {
325 /* Unsupported parameter type */
326 status = -1;
327 break;
328 }
329 }
330
331 if (status != 0) {
332 cx_string_delete(key);
333 cx_string_delete(comment);
334 cx_string_delete(value);
335 cx_string_delete(preset);
336
337 return -1;
338 }
339
340 ++pcount;
341 cx_string_sprintf(key, "%s%-d %s%-d %s", "ESO PRO REC", sequence,
342 "PARAM", pcount, "NAME");
343 status = cpl_propertylist_update_string(plist, cx_string_get(key), alias);
344
345 if (status != 0) {
346 cx_string_delete(key);
347 cx_string_delete(comment);
348 cx_string_delete(value);
349 cx_string_delete(preset);
350
351 return 2;
352 }
353
354 status = cpl_propertylist_set_comment(plist, cx_string_get(key),
355 cpl_parameter_get_help(p));
356
357 if (status != 0) {
358 cx_string_delete(key);
359 cx_string_delete(comment);
360 cx_string_delete(value);
361 cx_string_delete(preset);
362
363 return 2;
364 }
365
366
367 cx_string_sprintf(key, "%s%-d %s%-d %s", "ESO PRO REC", sequence,
368 "PARAM", pcount, "VALUE");
369 cx_string_sprintf(comment, "Default: %s", cx_string_get(preset));
370
371 status = cpl_propertylist_update_string(plist, cx_string_get(key),
372 cx_string_get(value));
373
374 if (status != 0) {
375 cx_string_delete(key);
376 cx_string_delete(comment);
377 cx_string_delete(value);
378 cx_string_delete(preset);
379
380 return 3;
381 }
382
383 status = cpl_propertylist_set_comment(plist, cx_string_get(key),
384 cx_string_get(comment));
385
386 if (status != 0) {
387 cx_string_delete(key);
388 cx_string_delete(comment);
389 cx_string_delete(value);
390 cx_string_delete(preset);
391
392 return 3;
393 }
394
395 cx_string_delete(value);
396 cx_string_delete(preset);
397
398 p = cpl_parameterlist_get_next_const(options);
399
400 }
401
402 cx_string_delete(key);
403 cx_string_delete(comment);
404
405 return 0;
406}
407
408
419const cxchar *
421{
422
423 return _giraffe_license;
424
425}
426
427
441GiInstrumentMode
442giraffe_get_mode(cpl_propertylist *properties)
443{
444
445 const cxchar *fctid = "giraffe_get_mode";
446 const cxchar *mode;
447
448 cx_string *s = NULL;
449
450 GiInstrumentMode insmode;
451
452
453 if (!properties) {
454 cpl_error_set(fctid, CPL_ERROR_NULL_INPUT);
455 return GIMODE_NONE;
456 }
457
458
459 if (!cpl_propertylist_has(properties, GIALIAS_INSMODE)) {
460 gi_warning("%s: Property (%s) not found\n", fctid, GIALIAS_INSMODE);
461
462 if (!cpl_propertylist_has(properties, GIALIAS_SLITNAME)) {
463 cx_warning("%s: Property (%s) not found\n", fctid,
464 GIALIAS_SLITNAME);
465 return GIMODE_NONE;
466 }
467 else {
468 mode = cpl_propertylist_get_string(properties, GIALIAS_SLITNAME);
469 }
470 }
471 else {
472 mode = cpl_propertylist_get_string(properties, GIALIAS_SLITNAME);
473 }
474
475 if (!mode || strlen(mode) == 0) {
476 cpl_error_set(fctid, CPL_ERROR_ILLEGAL_INPUT);
477 return GIMODE_NONE;
478 }
479
480
481 s = cx_string_create(mode);
482 cx_string_lower(s);
483
484 if (strncmp(cx_string_get(s), "med", 3) == 0) {
485 insmode = GIMODE_MEDUSA;
486 }
487 else if (strncmp(cx_string_get(s), "ifu", 3) == 0) {
488 insmode = GIMODE_IFU;
489 }
490 else if (strncmp(cx_string_get(s), "arg", 3) == 0) {
491 insmode = GIMODE_ARGUS;
492 }
493 else {
494 cpl_error_set(fctid, CPL_ERROR_UNSUPPORTED_MODE);
495 insmode = GIMODE_NONE;
496 }
497
498 cx_string_delete(s);
499
500 return insmode;
501
502}
503
519cxchar *
520giraffe_path_get_basename(const cxchar *path)
521{
522
523 register cxssize base;
524 register cxssize last_nonslash;
525
526 cxsize len;
527
528 cxchar *result;
529
530
531 if (path == NULL) {
532 return NULL;
533 }
534
535 if (path[0] == '\0') {
536 return cx_strdup(".");
537 }
538
539 last_nonslash = strlen(path) - 1;
540
541 while (last_nonslash >= 0 && path[last_nonslash] == '/') {
542 --last_nonslash;
543 }
544
545
546 /* String only containing slashes */
547
548 if (last_nonslash == -1) {
549 return cx_strdup("/");
550 }
551
552 base = last_nonslash;
553
554 while (base >=0 && path[base] != '/') {
555 --base;
556 }
557
558 len = last_nonslash - base;
559
560 result = cx_malloc(len + 1);
561 memcpy(result, path + base + 1, len);
562 result[len] = '\0';
563
564 return result;
565
566}
567
568
581cxchar *
583{
584
585 struct tm *ts;
586
587 time_t seconds = time(NULL);
588
589 cxchar *sdate = NULL;
590
591 cxulong milliseconds = 0;
592
593 cx_string *self = cx_string_new();
594
595
596 cx_assert(self != NULL);
597
598 ts = localtime(&seconds);
599
600 cx_string_sprintf(self, "%4d-%02d-%02dT%02d:%02d:%02d.%03ld",
601 ts->tm_year + 1900,
602 ts->tm_mon + 1,
603 ts->tm_mday,
604 ts->tm_hour,
605 ts->tm_min,
606 ts->tm_sec,
607 milliseconds);
608
609 sdate = cx_strdup(cx_string_get(self));
610 cx_string_delete(self);
611
612 return sdate;
613
614}
615
616
624cxint
625giraffe_add_recipe_info(cpl_propertylist *plist, const GiRecipeInfo *info)
626{
627
628 if (plist == NULL) {
629 return -1;
630 }
631
632 if (info != NULL) {
633
634 cxint status = 0;
635
636 cx_string *name = cx_string_new();
637 cx_string *value = cx_string_new();
638
639
640 cx_string_sprintf(name, "%s%-d %s", "ESO PRO REC", info->sequence,
641 "ID");
642 cx_string_sprintf(value, "%s", info->recipe);
643
644 status = cpl_propertylist_update_string(plist, cx_string_get(name),
645 cx_string_get(value));
646
647
648 if (status != CPL_ERROR_NONE) {
649 cx_string_delete(name);
650 cx_string_delete(value);
651
652 return 1;
653 }
654
655 status = cpl_propertylist_set_comment(plist, cx_string_get(name),
656 "Pipeline recipe (unique) identifier");
657
658 if (status != 0) {
659 cx_string_delete(name);
660 cx_string_delete(value);
661
662 return 1;
663 }
664
665 cx_string_sprintf(name, "%s%-d %s", "ESO PRO REC", info->sequence,
666 "PIPE ID");
667 cx_string_sprintf(value, "%s/%s", PACKAGE, VERSION);
668
669 status = cpl_propertylist_update_string(plist, cx_string_get(name),
670 cx_string_get(value));
671
672
673 if (status != CPL_ERROR_NONE) {
674 cx_string_delete(name);
675 cx_string_delete(value);
676
677 return 1;
678 }
679
680 status = cpl_propertylist_set_comment(plist, cx_string_get(name),
681 "Pipeline (unique) identifier");
682
683 if (status != 0) {
684 cx_string_delete(name);
685 cx_string_delete(value);
686
687 return 1;
688 }
689
690 cx_string_sprintf(name, "%s%-d %s", "ESO PRO REC", info->sequence,
691 "DRS ID");
692 cx_string_sprintf(value, "cpl-%s", cpl_version_get_version());
693
694 status = cpl_propertylist_update_string(plist, cx_string_get(name),
695 cx_string_get(value));
696
697
698 if (status != CPL_ERROR_NONE) {
699 cx_string_delete(name);
700 cx_string_delete(value);
701
702 return 1;
703 }
704
705 status = cpl_propertylist_set_comment(plist, cx_string_get(name),
706 "Data Reduction System identifier");
707
708 if (status != 0) {
709 cx_string_delete(name);
710 cx_string_delete(value);
711
712 return 1;
713 }
714
715 if (info->start != NULL) {
716 cx_string_sprintf(name, "%s%-d %s", "ESO PRO REC",
717 info->sequence, "START");
718 status = cpl_propertylist_update_string(plist,
719 cx_string_get(name),
720 info->start);
721
722 if (status != CPL_ERROR_NONE) {
723 cx_string_delete(name);
724 cx_string_delete(value);
725
726 return 1;
727 }
728
729 status = cpl_propertylist_set_comment(plist, cx_string_get(name),
730 "Date when recipe execution "
731 "started.");
732
733 if (status != 0) {
734 cx_string_delete(name);
735 cx_string_delete(value);
736
737 return 1;
738 }
739 }
740
741 cx_string_delete(name);
742 cx_string_delete(value);
743
744
745 /*
746 * Add recipe options
747 */
748
749 status = _giraffe_add_option_info(plist, info->options, info->sequence);
750
751 if (status != 0) {
752 return 1;
753 }
754
755 }
756
757 return 0;
758
759}
760
761
783cxint
784giraffe_add_frameset_info(cpl_propertylist *plist, const cpl_frameset *set,
785 cxint sequence)
786{
787
788 if (plist == NULL) {
789 return -1;
790 }
791
792 if (set != NULL) {
793
794 cxsize nraw = 0;
795 cxsize ncalib = 0;
796
797 cx_string *key = cx_string_new();
798
799 const cpl_frame *frame = NULL;
800
801 cpl_frameset_iterator *it = cpl_frameset_iterator_new(set);
802
803
804 while ((frame = cpl_frameset_iterator_get_const(it)) != NULL) {
805
806 cpl_frame_group group = cpl_frame_get_group(frame);
807
808 const cxchar *name = cpl_frame_get_filename(frame);
809 const cxchar *tag = cpl_frame_get_tag(frame);
810 const cxchar *base = giraffe_path_get_basename(name);
811
812
813 cx_assert(base != NULL);
814
815 switch (group) {
816 case CPL_FRAME_GROUP_RAW:
817 {
818
819 cxint status = 0;
820
821 ++nraw;
822
823
824 /*
825 * Get the product's ancestor as the archive name of the
826 * first raw file in the reference set
827 */
828
829 if (!cpl_propertylist_has(plist, GIALIAS_ANCESTOR)) {
830
831 if (nraw == 1) {
832
833 cpl_propertylist *_plist = cpl_propertylist_load(name, 0);
834
835 if (_plist == NULL) {
836
837 if (base != NULL) {
838 cx_free((cxchar *)base);
839 }
840
841 cpl_frameset_iterator_delete(it);
842 cx_string_delete(key);
843
844 return -2;
845
846 }
847
848 if (cpl_propertylist_has(_plist, GIALIAS_ANCESTOR)) {
849 cpl_propertylist_copy_property(plist, _plist,
850 GIALIAS_ANCESTOR);
851 }
852 else {
853
854 const cxchar *s =
855 cpl_propertylist_get_string(_plist,
856 GIALIAS_ARCFILE);
857 const cxchar *c = "Inherited archive file name "
858 "of the first raw data frame";
859
860 if (s != NULL) {
861 cpl_propertylist_append_string(plist,
862 GIALIAS_ANCESTOR, s);
863 cpl_propertylist_set_comment(plist,
864 GIALIAS_ANCESTOR, c);
865 }
866
867 }
868
869 cpl_propertylist_delete(_plist);
870
871 }
872
873 }
874
875
876 status = _giraffe_add_frame_info(plist, base, tag,
877 sequence, nraw, 0);
878
879 if (status != 0) {
880 if (base != NULL) {
881 cx_free((cxchar *)base);
882 }
883
884 cpl_frameset_iterator_delete(it);
885 cx_string_delete(key);
886
887 return -2;
888 }
889
890
891 break;
892 }
893
894 case CPL_FRAME_GROUP_CALIB:
895 {
896
897 cpl_propertylist *_plist = NULL;
898
899
900 ++ncalib;
901 cxint status = _giraffe_add_frame_info(plist, base, tag,
902 sequence, ncalib, 1);
903
904 if (status != 0) {
905 if (base != NULL) {
906 cx_free((cxchar *)base);
907 }
908
909 cpl_frameset_iterator_delete(it);
910 cx_string_delete(key);
911
912 return -3;
913 }
914
915 _plist = cpl_propertylist_load(name, 0);
916
917 if (_plist == NULL) {
918 if (base != NULL) {
919 cx_free((cxchar *)base);
920 }
921
922 cpl_frameset_iterator_delete(it);
923 cx_string_delete(key);
924
925 return -3;
926 }
927
928
929 if (cpl_propertylist_has(_plist, GIALIAS_DATAMD5)) {
930
931 const cxchar *s =
932 cpl_propertylist_get_string(_plist, GIALIAS_DATAMD5);
933
934 if (strcmp(s, "Not computed") != 0) {
935
936 cx_string* md5 = cx_string_new();
937
938 cx_string_sprintf(md5, "%s%d %s%"
939 CX_PRINTF_FORMAT_SIZE_TYPE "%s",
940 "ESO PRO REC", sequence, "CAL",
941 ncalib, " DATAMD5");
942
943 status =
944 cpl_propertylist_update_string(plist,
945 cx_string_get(md5),
946 s);
947
948 if (status != CPL_ERROR_NONE) {
949 cx_string_delete(md5);
950 cpl_propertylist_delete(_plist);
951
952 if (base != NULL) {
953 cx_free((cxchar *)base);
954 }
955
956 cpl_frameset_iterator_delete(it);
957 cx_string_delete(key);
958
959 return -3;
960 }
961
962 cx_string_delete(md5);
963 }
964
965 }
966
967 cpl_propertylist_delete(_plist);
968 break;
969 }
970
971 default:
972 break;
973 }
974
975
976 if (base != NULL) {
977 cx_free((cxchar *)base);
978 }
979
980 cpl_frameset_iterator_advance(it, 1);
981
982 }
983
984 cpl_frameset_iterator_delete(it);
985 cx_string_delete(key);
986
987 }
988
989 return 0;
990
991}
992
993
1014cxint
1015giraffe_propertylist_update(cpl_propertylist *self,
1016 cpl_propertylist *properties,
1017 const cxchar *regexp)
1018{
1019
1020 const cxchar *fctid = "giraffe_propertylist_update";
1021
1022 cxlong i;
1023 cxlong sz = 0;
1024
1025
1026 cx_assert(self != NULL);
1027
1028 if (properties == NULL) {
1029 cpl_error_set(fctid, CPL_ERROR_NULL_INPUT);
1030 return -1;
1031 }
1032
1033 sz = cpl_propertylist_get_size(properties);
1034
1035 if (regexp == NULL || regexp[0] == '\0') {
1036
1037 for (i = 0; i < sz; i++) {
1038
1039 cpl_property *p = cpl_propertylist_get(properties, i);
1040 const cxchar *name = cpl_property_get_name(p);
1041
1042
1043 if (!cpl_propertylist_has(self, name)) {
1044
1045 cxint status = _giraffe_plist_append(self, p);
1046
1047 if (status) {
1048 cpl_error_set(fctid, CPL_ERROR_INVALID_TYPE);
1049 return 1;
1050 }
1051 }
1052 }
1053 }
1054 else {
1055
1056 cxint status = 0;
1057
1058 regex_t re;
1059
1060
1061 status = regcomp(&re, regexp, REG_EXTENDED | REG_NOSUB);
1062
1063 if (status) {
1064 cpl_error_set(fctid, CPL_ERROR_ILLEGAL_INPUT);
1065 return 1;
1066 }
1067
1068 for (i = 0; i < sz; i++) {
1069
1070 cpl_property *p = cpl_propertylist_get(properties, i);
1071 const cxchar *name = cpl_property_get_name(p);
1072
1073
1074 if (regexec(&re, name, (size_t)0, NULL, 0) == REG_NOMATCH) {
1075 continue;
1076 }
1077
1078 if (!cpl_propertylist_has(self, name)) {
1079
1080 status = _giraffe_plist_append(self, p);
1081
1082 if (status) {
1083 cpl_error_set(fctid, CPL_ERROR_INVALID_TYPE);
1084 return 1;
1085 }
1086 }
1087 }
1088
1089 regfree(&re);
1090
1091 }
1092
1093 return 0;
1094
1095}
1096
1097
1105cxint
1106giraffe_propertylist_copy(cpl_propertylist *self,
1107 const cxchar *name,
1108 const cpl_propertylist *other,
1109 const cxchar *othername)
1110{
1111
1112 const cxchar *fctid = "giraffe_propertylist_copy";
1113
1114
1115 const cxchar *s;
1116 const cxchar *comment;
1117
1118 cpl_type type;
1119
1120
1121
1122 cx_assert(self != NULL);
1123
1124 if (other == NULL) {
1125 return -1;
1126 }
1127
1128 if (othername == NULL) {
1129 return -2;
1130 }
1131
1132 if (!cpl_propertylist_has(other, othername)) {
1133 return 1;
1134 }
1135
1136 type = cpl_propertylist_get_type(other, othername);
1137
1138
1139 /*
1140 * Determine the name the new property should have in self.
1141 */
1142
1143 s = name == NULL ? othername : name;
1144
1145
1146 /*
1147 * Add the property to the destination list.
1148 */
1149
1150 switch (type) {
1151 case CPL_TYPE_CHAR:
1152 {
1153 cxchar value = cpl_propertylist_get_char(other, othername);
1154
1155 if (cpl_propertylist_has(self, s)) {
1156 cpl_propertylist_set_char(self, s, value);
1157 }
1158 else {
1159 cpl_propertylist_append_char(self, s, value);
1160 }
1161 }
1162 break;
1163
1164 case CPL_TYPE_BOOL:
1165 {
1166 cxbool value = cpl_propertylist_get_bool(other, othername);
1167
1168 if (cpl_propertylist_has(self, s)) {
1169 cpl_propertylist_set_bool(self, s, value);
1170 }
1171 else {
1172 cpl_propertylist_append_bool(self, s, value);
1173 }
1174 }
1175 break;
1176
1177 case CPL_TYPE_INT:
1178 {
1179 cxint value = cpl_propertylist_get_int(other, othername);
1180
1181 if (cpl_propertylist_has(self, s)) {
1182 cpl_propertylist_set_int(self, s, value);
1183 }
1184 else {
1185 cpl_propertylist_append_int(self, s, value);
1186 }
1187 }
1188 break;
1189
1190 case CPL_TYPE_LONG:
1191 {
1192 cxlong value = cpl_propertylist_get_long(other, othername);
1193
1194 if (cpl_propertylist_has(self, s)) {
1195 cpl_propertylist_set_long(self, s, value);
1196 }
1197 else {
1198 cpl_propertylist_append_long(self, s, value);
1199 }
1200 }
1201 break;
1202
1203 case CPL_TYPE_FLOAT:
1204 {
1205 cxfloat value = cpl_propertylist_get_float(other, othername);
1206
1207 if (cpl_propertylist_has(self, s)) {
1208 cpl_propertylist_set_float(self, s, value);
1209 }
1210 else {
1211 cpl_propertylist_append_float(self, s, value);
1212 }
1213 }
1214 break;
1215
1216 case CPL_TYPE_DOUBLE:
1217 {
1218 cxdouble value = cpl_propertylist_get_double(other, othername);
1219
1220 if (cpl_propertylist_has(self, s)) {
1221 cpl_propertylist_set_double(self, s, value);
1222 }
1223 else {
1224 cpl_propertylist_append_double(self, s, value);
1225 }
1226 }
1227 break;
1228
1229 case CPL_TYPE_STRING:
1230 {
1231 const cxchar *value = cpl_propertylist_get_string(other,
1232 othername);
1233
1234 if (cpl_propertylist_has(self, s)) {
1235 cpl_propertylist_set_string(self, s, value);
1236 }
1237 else {
1238 cpl_propertylist_append_string(self, s, value);
1239 }
1240 }
1241 break;
1242
1243 default:
1244 cpl_error_set(fctid, CPL_ERROR_INVALID_TYPE);
1245 return 2;
1246 break;
1247 }
1248
1249 comment = cpl_propertylist_get_comment(other, othername);
1250
1251 if (comment != NULL) {
1252 cpl_propertylist_set_comment(self, s, comment);
1253 }
1254
1255 return 0;
1256
1257}
1258
1259
1260cxint
1261giraffe_propertylist_update_wcs(cpl_propertylist* properties, cxsize naxis,
1262 const cxdouble* crpix, const cxdouble* crval,
1263 const cxchar** ctype, const cxchar** cunit,
1264 const cpl_matrix* cd)
1265{
1266
1267 if (properties == NULL) {
1268 return 0;
1269 }
1270
1271 cpl_propertylist_erase_regexp(properties, "^CRPIX[0-9]", 0);
1272 cpl_propertylist_erase_regexp(properties, "^CRVAL[0-9]", 0);
1273 cpl_propertylist_erase_regexp(properties, "^CDELT[0-9]", 0);
1274 cpl_propertylist_erase_regexp(properties, "^CTYPE[0-9]", 0);
1275 cpl_propertylist_erase_regexp(properties, "^CUNIT[0-9]", 0);
1276 cpl_propertylist_erase_regexp(properties, "^CROTA[0-9]", 0);
1277 cpl_propertylist_erase_regexp(properties, "^CD[0-9]*_[0-9]", 0);
1278 cpl_propertylist_erase_regexp(properties, "^PC[0-9]*_[0-9]", 0);
1279
1280
1281 if (naxis > 0) {
1282
1283
1284 register cxsize i = 0;
1285
1286 cx_string* keyword = cx_string_new();
1287 cx_string* comment = cx_string_new();
1288
1289
1290 cx_assert(cpl_matrix_get_nrow(cd) == cpl_matrix_get_ncol(cd));
1291
1292 for (i = 0; i < naxis; i++) {
1293
1294 cx_string_sprintf(keyword, "CTYPE%-" CX_PRINTF_FORMAT_SIZE_TYPE,
1295 i + 1);
1296 cx_string_sprintf(comment, "Coordinate system of axis %"
1297 CX_PRINTF_FORMAT_SIZE_TYPE, i + 1);
1298 cpl_propertylist_append_string(properties,
1299 cx_string_get(keyword), ctype[i]);
1300 cpl_propertylist_set_comment(properties, cx_string_get(keyword),
1301 cx_string_get(comment));
1302
1303 }
1304
1305 for (i = 0; i < naxis; i++) {
1306
1307 cx_string_sprintf(keyword, "CRPIX%-" CX_PRINTF_FORMAT_SIZE_TYPE,
1308 i + 1);
1309 cx_string_sprintf(comment, "Reference pixel of axis %"
1310 CX_PRINTF_FORMAT_SIZE_TYPE, i + 1);
1311 cpl_propertylist_append_double(properties,
1312 cx_string_get(keyword), crpix[i]);
1313 cpl_propertylist_set_comment(properties, cx_string_get(keyword),
1314 cx_string_get(comment));
1315
1316 }
1317
1318 for (i = 0; i < naxis; i++) {
1319
1320 cx_string_sprintf(keyword, "CRVAL%-" CX_PRINTF_FORMAT_SIZE_TYPE,
1321 i + 1);
1322 cx_string_sprintf(comment, "Coordinate of axis %"
1323 CX_PRINTF_FORMAT_SIZE_TYPE " at reference "
1324 "pixel", i + 1);
1325 cpl_propertylist_append_double(properties,
1326 cx_string_get(keyword), crval[i]);
1327 cpl_propertylist_set_comment(properties, cx_string_get(keyword),
1328 cx_string_get(comment));
1329
1330 }
1331
1332 for (i = 0; i < naxis; i++) {
1333
1334 if (cunit[i] != NULL) {
1335 cx_string_sprintf(keyword, "CUNIT%-"
1336 CX_PRINTF_FORMAT_SIZE_TYPE, i + 1);
1337 cx_string_sprintf(comment, "Unit of coordinate axis %"
1338 CX_PRINTF_FORMAT_SIZE_TYPE, i + 1);
1339 cpl_propertylist_append_string(properties,
1340 cx_string_get(keyword),
1341 cunit[i]);
1342 cpl_propertylist_set_comment(properties,
1343 cx_string_get(keyword),
1344 cx_string_get(comment));
1345 }
1346
1347 }
1348
1349
1350 /*
1351 * CD matrix
1352 */
1353
1354 for (i = 0; i < naxis; i++) {
1355
1356 register cxsize j = 0;
1357
1358
1359 for (j = 0; j < naxis; j++) {
1360
1361 cx_string_sprintf(keyword, "CD%-" CX_PRINTF_FORMAT_SIZE_TYPE
1362 "_%-" CX_PRINTF_FORMAT_SIZE_TYPE, i + 1,
1363 j + 1);
1364 cx_string_sprintf(comment, "Coordinate transformation matrix "
1365 "element");
1366 cpl_propertylist_append_double(properties,
1367 cx_string_get(keyword),
1368 cpl_matrix_get(cd, i, j));
1369 cpl_propertylist_set_comment(properties,
1370 cx_string_get(keyword),
1371 cx_string_get(comment));
1372 }
1373
1374 }
1375
1376 cx_string_delete(keyword);
1377 keyword = NULL;
1378
1379 cx_string_delete(comment);
1380 comment = NULL;
1381
1382 }
1383
1384 return 0;
1385
1386}
1387
1388
1389cxint
1390giraffe_frameset_set_groups(cpl_frameset* set, GiGroupInfo *groups)
1391{
1392
1393 cpl_frame* frame = NULL;
1394
1395 cpl_frameset_iterator *it = NULL;
1396
1397
1398 if (set == NULL) {
1399 return -1;
1400 }
1401
1402 if (groups == NULL || groups->tag == NULL) {
1403 return 0;
1404 }
1405
1406 it = cpl_frameset_iterator_new(set);
1407
1408 while ((frame = cpl_frameset_iterator_get(it)) != NULL) {
1409
1410 const cxchar* tag = cpl_frame_get_tag(frame);
1411
1412 if (tag != NULL &&
1413 cpl_frame_get_group(frame) == CPL_FRAME_GROUP_NONE) {
1414
1415 const GiGroupInfo* g = groups;
1416
1417 while (g->tag != NULL) {
1418 if (strcmp(tag, g->tag) == 0) {
1419 cpl_frame_set_group(frame, g->group);
1420 break;
1421 }
1422 ++g;
1423 }
1424
1425 }
1426
1427 cpl_frameset_iterator_advance(it, 1);
1428
1429 }
1430
1431 cpl_frameset_iterator_delete(it);
1432
1433 return 0;
1434
1435}
1436
1437
1471cxdouble giraffe_propertylist_get_conad(const cpl_propertylist* properties)
1472{
1473
1474 const cxchar* const fctid = "giraffe_propertylist_get_conad";
1475
1476 const cxchar *names[2] = {GIALIAS_CONAD, GIALIAS_CONAD_LEGACY};
1477 const cxchar *name = NULL;
1478
1479 cxdouble conad = 1.;
1480
1481
1482 cx_assert(properties != NULL);
1483
1484
1485 if (!cpl_propertylist_has(properties, GIALIAS_CONAD)) {
1486
1487 if (!cpl_propertylist_has(properties, GIALIAS_CONAD_LEGACY)) {
1488
1489 cpl_msg_error(fctid, "Missing detector gain property (%s, %s)! ",
1490 GIALIAS_CONAD, GIALIAS_CONAD_LEGACY);
1491 cpl_error_set(fctid, CPL_ERROR_DATA_NOT_FOUND);
1492
1493 return 0.;
1494
1495 }
1496 else {
1497 name = names[1];
1498 }
1499
1500
1501 }
1502 else {
1503 name = names[0];
1504 }
1505
1506 conad = cpl_propertylist_get_double(properties, name);
1507
1508 if (conad < 0.) {
1509
1510 cpl_msg_error(fctid, "Invalid conversion factor (%s) %.3g "
1511 "[e-/ADU]", name, conad);
1512 cpl_error_set(fctid, CPL_ERROR_ILLEGAL_INPUT);
1513
1514 return 0.;
1515
1516 }
1517
1518 return conad;
1519
1520}
1521
1522
1554cxdouble
1555giraffe_propertylist_get_ron(const cpl_propertylist* properties)
1556{
1557
1558 const cxchar* const fctid = "giraffe_propertylist_get_ron";
1559
1560
1561 cxdouble ron = 0.;
1562
1563
1564 cx_assert(properties != NULL);
1565
1566 if (!cpl_propertylist_has(properties, GIALIAS_BIASSIGMA)) {
1567 if (!cpl_propertylist_has(properties, GIALIAS_RON)) {
1568 cpl_msg_error(fctid, "Missing detector read-out noise "
1569 "property (%s)!", GIALIAS_RON);
1570 cpl_error_set(fctid, CPL_ERROR_DATA_NOT_FOUND);
1571
1572 return 0.;
1573 }
1574 else {
1575
1576 /*
1577 * Get default detector read-out noise. Note that this value
1578 * is already given in electrons. No conversion needed.
1579 */
1580
1581 cpl_msg_warning(fctid, "Missing bias RMS property (%s)! "
1582 "Using detector read-out noise property (%s).",
1583 GIALIAS_BIASSIGMA, GIALIAS_RON);
1584 ron = cpl_propertylist_get_double(properties, GIALIAS_RON);
1585 }
1586 }
1587 else {
1588
1589 cxdouble conad = 0.;
1590
1591
1592 /*
1593 * Get measured detector read-out noise. This is given in ADU and
1594 * has to be converted into electrons.
1595 */
1596
1597 giraffe_error_push();
1598
1599 conad = giraffe_propertylist_get_conad(properties);
1600
1601 if (cpl_error_get_code() != CPL_ERROR_NONE) {
1602 return 0.;
1603 }
1604
1605 giraffe_error_pop();
1606
1607 ron = cpl_propertylist_get_double(properties, GIALIAS_BIASSIGMA) *
1608 conad;
1609
1610 }
1611
1612 return ron;
1613
1614}
1615/*
1616* The pipeline itself has no concept of treating different FLAT types differently.
1617* For QC parameters this function just reproduces the logic from giraf.oca.
1618*/
1619const char * giraffe_get_flat_type(cpl_propertylist* plist) {
1620 cpl_error_code error_code;
1621 cpl_errorstate prev_state = cpl_errorstate_get();
1622
1623 const char* CATG = cpl_propertylist_get_string(plist, "ESO DPR CATG");
1624 if (CATG == NULL) {
1625 error_code = cpl_error_get_code();
1626 cpl_msg_warning("getDO_CATG", "Failed to get ESO DPR CATG: %d", error_code);
1627 cpl_errorstate_set(prev_state);
1628 return NULL;
1629 }
1630
1631 const char* TYPE = cpl_propertylist_get_string(plist, "ESO DPR TYPE");
1632 if (TYPE == NULL) {
1633 error_code = cpl_error_get_code();
1634 cpl_msg_warning("getDO_CATG", "Failed to get ESO DPR TYPE: %d", error_code);
1635 cpl_errorstate_set(prev_state);
1636 return NULL;
1637 }
1638
1639 const char* TECH = cpl_propertylist_get_string(plist, "ESO DPR TECH");
1640 if (TECH == NULL) {
1641 error_code = cpl_error_get_code();
1642 cpl_msg_warning("getDO_CATG", "Failed to get ESO DPR TECH: %d", error_code);
1643 cpl_errorstate_set(prev_state);
1644 return NULL;
1645 }
1646
1647 if (strstr(CATG, "CALIB") != NULL) {
1648 if (strstr(TYPE, "FLAT") != NULL && strstr(TYPE, "LAMP") != NULL) {
1649 if (strstr(TYPE, "NASMYTH") != NULL) {
1650 if (strstr(TECH, "MOS") != NULL || strstr(TECH, "IFU") != NULL) {
1651 return "NAS"; // NASMYTH
1652 }
1653 }
1654 else if (strstr(TECH, "MOS") != NULL || strstr(TECH, "IFU") != NULL) {
1655 return "ROB"; // ROBOTIC
1656 }
1657 }
1658 else if (strstr(TYPE, "SKY") != NULL) {
1659 if (strstr(TECH, "MOS") != NULL || strstr(TECH, "IFU") != NULL) {
1660 return "SKY";
1661 }
1662 }
1663 }
1664
1665 return NULL;
1666}
1667
1668
1669const int
1670giraffe_qc_airm_see_avg(cpl_propertylist *properties)
1671{
1672 double airmass = 0.0;
1673 double seeing = 0.0;
1674
1675 const cxchar *const fctid = "giraffe_qc_airm_see_avg";
1676
1677 char *qcairm = GIALIAS_QCAIRMAVG;
1678 char *qcsee = GIALIAS_QCSEEAVG;
1679
1680 cpl_errorstate tempes = cpl_errorstate_get();
1681
1682 if (cpl_propertylist_has(properties, GIALIAS_PROSCIENCE)) {
1683 if (cpl_propertylist_get_bool(properties, GIALIAS_PROSCIENCE)) {
1684 qcairm = GIALIAS_QCAIR;
1685 qcsee = GIALIAS_QCFWHM;
1686 }
1687 }
1688
1689 cxbool start = cpl_propertylist_has(properties, GIALIAS_AIRMASS_START);
1690 cxbool end = cpl_propertylist_has(properties, GIALIAS_AIRMASS_END);
1691
1692 if ((start == FALSE) || (end == FALSE)) {
1693 cpl_msg_debug(fctid, "Unable to compute airmass of the "
1694 "observation!");
1695
1696 return -1;
1697 }
1698 else {
1699 airmass =
1700 0.5 *
1701 (cpl_propertylist_get_double(properties, GIALIAS_AIRMASS_START) +
1702 cpl_propertylist_get_double(properties, GIALIAS_AIRMASS_END));
1703
1704
1705 cpl_propertylist_update_double(properties, qcairm, airmass);
1706 cpl_propertylist_set_comment(properties, qcairm,
1707 "Average airmass"
1708 " in the first raw frame");
1709 }
1710 start = cpl_propertylist_has(properties, GIALIAS_FWHM_START);
1711 end = cpl_propertylist_has(properties, GIALIAS_FWHM_END);
1712
1713 if ((start == FALSE) || (end == FALSE)) {
1714 cpl_msg_warning(fctid, "Unable to compute seeing of the "
1715 "observation!");
1716
1717 return -1;
1718 }
1719 else {
1720 seeing =
1721 0.5 * (cpl_propertylist_get_double(properties, GIALIAS_FWHM_START) +
1722 cpl_propertylist_get_double(properties, GIALIAS_FWHM_END));
1723
1724
1725 cpl_propertylist_update_double(properties, qcsee, seeing);
1726 cpl_propertylist_set_comment(properties, qcsee,
1727 "Average seeing"
1728 " in the first raw frame");
1729 }
1730
1731 cpl_errorstate_set(tempes);
1732
1733 return 0;
1734}
1735
1736const int giraffe_qc_update_sci_props(cpl_propertylist* properties, GiTable* fibers) {
1737
1738 cpl_errorstate tempes = cpl_errorstate_get();
1739
1740 cpl_propertylist_append_string(properties, GIALIAS_QCSCHEME,"UVES_STACK");
1741 giraffe_qc_airm_see_avg(properties);
1742 giraffe_propertylist_copy(properties, GIALIAS_QCNFIB, properties,
1743 GIALIAS_NFIBERS);
1744
1745 cpl_table * fibtab = giraffe_table_get(fibers);
1746
1747 int nsci = 0;
1748 int nsky = 0;
1749
1750 nsci = cpl_table_and_selected_string(fibtab, "TYPE", CPL_EQUAL_TO, "M");
1751 cpl_table_select_all(fibtab);
1752 nsky = cpl_table_and_selected_string(fibtab, "TYPE", CPL_EQUAL_TO, "S");
1753 cpl_table_select_all(fibtab);
1754
1755 cpl_propertylist_append_int(properties, GIALIAS_QCNFIBSCI, nsci);
1756 cpl_propertylist_append_int(properties, GIALIAS_QCNFIBSKY, nsky);
1757
1758 cpl_errorstate_set(tempes);
1759
1760 return 0;
1761
1762}
1763
void gi_warning(const cxchar *format,...)
Log a warning.
Definition: gimessages.c:119
cpl_table * giraffe_table_get(const GiTable *self)
Get the table data from a Giraffe table.
Definition: gitable.c:433
cxint giraffe_add_recipe_info(cpl_propertylist *plist, const GiRecipeInfo *info)
Add recipe specific information to a property list.
Definition: giutils.c:625
cxchar * giraffe_localtime_iso8601(void)
Get the current date and time in ISO 8601 format.
Definition: giutils.c:582
cxint giraffe_add_frameset_info(cpl_propertylist *plist, const cpl_frameset *set, cxint sequence)
Add frameset specific information to a property list.
Definition: giutils.c:784
cxchar * giraffe_path_get_basename(const cxchar *path)
Gets the name of a file without any leading directory components.
Definition: giutils.c:520
cxint giraffe_propertylist_copy(cpl_propertylist *self, const cxchar *name, const cpl_propertylist *other, const cxchar *othername)
Copy a property from one list to another.
Definition: giutils.c:1106
cxdouble giraffe_propertylist_get_conad(const cpl_propertylist *properties)
Retrieve the ADU to electrons conversion factor from the given properties.
Definition: giutils.c:1471
const cxchar * giraffe_get_license(void)
Get the pipeline copyright and license.
Definition: giutils.c:420
cxint giraffe_propertylist_update(cpl_propertylist *self, cpl_propertylist *properties, const cxchar *regexp)
Update a property list.
Definition: giutils.c:1015
cxdouble giraffe_propertylist_get_ron(const cpl_propertylist *properties)
Retrieve the read-out noise from the given properties.
Definition: giutils.c:1555
GiInstrumentMode giraffe_get_mode(cpl_propertylist *properties)
Determines the instrument mode from a property list.
Definition: giutils.c:442

This file is part of the GIRAFFE Pipeline Reference Manual 2.17.1.
Documentation copyright © 2002-2006 European Southern Observatory.
Generated on Thu Feb 13 2025 14:13:57 by doxygen 1.9.6 written by Dimitri van Heesch, © 1997-2004