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

This file is part of the GIRAFFE Pipeline Reference Manual 2.16.11.
Documentation copyright © 2002-2006 European Southern Observatory.
Generated on Tue Apr 23 2024 11:02:51 by doxygen 1.9.6 written by Dimitri van Heesch, © 1997-2004