32 #ifdef HAVE_SYS_TYPES_H
33 # include <sys/types.h>
40 #include <cxstrutils.h>
43 #include <cpl_error.h>
44 #include <cpl_matrix.h>
47 #include "gimessages.h"
63 static const cxchar *_giraffe_license =
64 " This file is part of the GIRAFFE Instrument Pipeline\n"
65 " Copyright (C) 2002-2014 European Southern Observatory\n"
67 " This program is free software; you can redistribute it and/or modify\n"
68 " it under the terms of the GNU General Public License as published by\n"
69 " the Free Software Foundation; either version 2 of the License, or\n"
70 " (at your option) any later version.\n"
72 " This program is distributed in the hope that it will be useful,\n"
73 " but WITHOUT ANY WARRANTY; without even the implied warranty of\n"
74 " MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the\n"
75 " GNU General Public License for more details.\n"
77 " You should have received a copy of the GNU General Public License\n"
78 " along with this program; if not, write to the Free Software\n"
79 " Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301"
84 _giraffe_plist_append(cpl_propertylist *
self, cpl_property *p)
87 const cxchar *name = cpl_property_get_name(p);
88 const cxchar *comment = cpl_property_get_comment(p);
91 switch (cpl_property_get_type(p)) {
94 cxbool value = cpl_property_get_bool(p);
96 cpl_propertylist_append_bool(
self, name, value);
102 cxchar value = cpl_property_get_char(p);
104 cpl_propertylist_append_char(
self, name, value);
110 cxint value = cpl_property_get_int(p);
112 cpl_propertylist_append_int(
self, name, value);
118 cxlong value = cpl_property_get_long(p);
120 cpl_propertylist_append_long(
self, name, value);
126 cxfloat value = cpl_property_get_float(p);
128 cpl_propertylist_append_float(
self, name, value);
132 case CPL_TYPE_DOUBLE:
134 cxdouble value = cpl_property_get_double(p);
136 cpl_propertylist_append_double(
self, name, value);
140 case CPL_TYPE_STRING:
142 const cxchar *value = cpl_property_get_string(p);
144 cpl_propertylist_append_string(
self, name, value);
160 if (comment != NULL) {
161 cpl_propertylist_set_comment(
self, name, comment);
170 _giraffe_add_frame_info(cpl_propertylist *plist,
const cxchar *name,
171 const cxchar *tag, cxint sequence, cxint frame_index,
175 const cxchar *
id = NULL;
176 const cxchar *group = NULL;
180 cx_string *key = NULL;
181 cx_string *comment = NULL;
196 group =
"calibration";
204 key = cx_string_new();
205 comment = cx_string_new();
212 cx_string_sprintf(key,
"%s%-d %s%-d %s",
"ESO PRO REC", sequence,
id,
213 frame_index,
"NAME");
214 cx_string_sprintf(comment,
"%s %s %s",
"File name of", group,
"frame");
216 status = cpl_propertylist_update_string(plist, cx_string_get(key), name);
218 if (status != CPL_ERROR_NONE) {
219 cx_string_delete(key);
220 cx_string_delete(comment);
225 status = cpl_propertylist_set_comment(plist, cx_string_get(key),
226 cx_string_get(comment));
229 cx_string_delete(key);
230 cx_string_delete(comment);
240 cx_string_sprintf(key,
"%s%-d %s%-d %s",
"ESO PRO REC", sequence,
id,
241 frame_index,
"CATG");
242 cx_string_sprintf(comment,
"%s %s %s",
"Frame category of", group,
245 status = cpl_propertylist_update_string(plist, cx_string_get(key), tag);
247 if (status != CPL_ERROR_NONE) {
248 cx_string_delete(key);
249 cx_string_delete(comment);
254 status = cpl_propertylist_set_comment(plist, cx_string_get(key),
255 cx_string_get(comment));
258 cx_string_delete(key);
259 cx_string_delete(comment);
264 cx_string_delete(key);
265 cx_string_delete(comment);
286 return _giraffe_license;
308 const cxchar *fctid =
"giraffe_get_mode";
313 GiInstrumentMode insmode;
317 cpl_error_set(fctid, CPL_ERROR_NULL_INPUT);
322 if (!cpl_propertylist_has(properties, GIALIAS_INSMODE)) {
323 gi_warning(
"%s: Property (%s) not found\n", fctid, GIALIAS_INSMODE);
325 if (!cpl_propertylist_has(properties, GIALIAS_SLITNAME)) {
326 cx_warning(
"%s: Property (%s) not found\n", fctid,
331 mode = cpl_propertylist_get_string(properties, GIALIAS_SLITNAME);
335 mode = cpl_propertylist_get_string(properties, GIALIAS_SLITNAME);
338 if (!mode || strlen(mode) == 0) {
339 cpl_error_set(fctid, CPL_ERROR_ILLEGAL_INPUT);
344 s = cx_string_create(mode);
347 if (strncmp(cx_string_get(s),
"med", 3) == 0) {
348 insmode = GIMODE_MEDUSA;
350 else if (strncmp(cx_string_get(s),
"ifu", 3) == 0) {
351 insmode = GIMODE_IFU;
353 else if (strncmp(cx_string_get(s),
"arg", 3) == 0) {
354 insmode = GIMODE_ARGUS;
357 cpl_error_set(fctid, CPL_ERROR_UNSUPPORTED_MODE);
358 insmode = GIMODE_NONE;
386 register cxssize base;
387 register cxssize last_nonslash;
398 if (path[0] ==
'\0') {
399 return cx_strdup(
".");
402 last_nonslash = strlen(path) - 1;
404 while (last_nonslash >= 0 && path[last_nonslash] ==
'/') {
411 if (last_nonslash == -1) {
412 return cx_strdup(
"/");
415 base = last_nonslash;
417 while (base >=0 && path[base] !=
'/') {
421 len = last_nonslash - base;
423 result = cx_malloc(len + 1);
424 memcpy(result, path + base + 1, len);
450 time_t seconds = time(NULL);
452 cxchar *sdate = NULL;
454 cxulong milliseconds = 0;
456 cx_string *
self = cx_string_new();
459 cx_assert(
self != NULL);
461 ts = localtime(&seconds);
463 cx_string_sprintf(
self,
"%4d-%02d-%02dT%02d:%02d:%02d.%03ld",
472 sdate = cx_strdup(cx_string_get(
self));
473 cx_string_delete(
self);
499 cx_string *name = cx_string_new();
500 cx_string *value = cx_string_new();
503 cx_string_sprintf(name,
"%s%-d %s",
"ESO PRO REC", info->sequence,
505 cx_string_sprintf(value,
"%s/%s", PACKAGE, VERSION);
507 status = cpl_propertylist_update_string(plist, cx_string_get(name),
508 cx_string_get(value));
511 if (status != CPL_ERROR_NONE) {
512 cx_string_delete(name);
513 cx_string_delete(value);
518 status = cpl_propertylist_set_comment(plist, cx_string_get(name),
519 "Pipeline (unique) identifier");
522 cx_string_delete(name);
523 cx_string_delete(value);
528 if (info->start != NULL) {
529 cx_string_sprintf(name,
"%s%-d %s",
"ESO PRO REC",
530 info->sequence,
"START");
531 status = cpl_propertylist_update_string(plist,
535 if (status != CPL_ERROR_NONE) {
536 cx_string_delete(name);
537 cx_string_delete(value);
542 status = cpl_propertylist_set_comment(plist, cx_string_get(name),
543 "Date when recipe execution "
547 cx_string_delete(name);
548 cx_string_delete(value);
554 cx_string_delete(name);
555 cx_string_delete(value);
599 cx_string *key = cx_string_new();
601 const cpl_frame *frame = NULL;
603 cpl_frameset_iterator *it = cpl_frameset_iterator_new(
set);
606 while ((frame = cpl_frameset_iterator_get_const(it)) != NULL) {
608 cpl_frame_group group = cpl_frame_get_group(frame);
610 const cxchar *name = cpl_frame_get_filename(frame);
611 const cxchar *tag = cpl_frame_get_tag(frame);
615 cx_assert(base != NULL);
618 case CPL_FRAME_GROUP_RAW:
621 cxint status = _giraffe_add_frame_info(plist, base, tag,
626 cx_free((cxchar *)base);
629 cpl_frameset_iterator_delete(it);
630 cx_string_delete(key);
638 case CPL_FRAME_GROUP_CALIB:
641 cpl_propertylist *_plist = NULL;
645 cxint status = _giraffe_add_frame_info(plist, base, tag,
646 sequence, ncalib, 1);
650 cx_free((cxchar *)base);
653 cpl_frameset_iterator_delete(it);
654 cx_string_delete(key);
659 _plist = cpl_propertylist_load(name, 0);
661 if (_plist == NULL) {
663 cx_free((cxchar *)base);
666 cpl_frameset_iterator_delete(it);
667 cx_string_delete(key);
673 if (cpl_propertylist_has(_plist, GIALIAS_DATAMD5)) {
676 cpl_propertylist_get_string(_plist, GIALIAS_DATAMD5);
678 if (strcmp(s,
"Not computed") != 0) {
680 cx_string* md5 = cx_string_new();
682 cx_string_sprintf(md5,
"%s%d %s%"
683 CX_PRINTF_FORMAT_SIZE_TYPE
"%s",
684 "ESO PRO REC", sequence,
"CAL",
688 cpl_propertylist_update_string(plist,
692 if (status != CPL_ERROR_NONE) {
693 cx_string_delete(md5);
694 cpl_propertylist_delete(_plist);
697 cx_free((cxchar *)base);
700 cpl_frameset_iterator_delete(it);
701 cx_string_delete(key);
706 cx_string_delete(md5);
711 cpl_propertylist_delete(_plist);
721 cx_free((cxchar *)base);
724 cpl_frameset_iterator_advance(it, 1);
728 cpl_frameset_iterator_delete(it);
729 cx_string_delete(key);
760 cpl_propertylist *properties,
761 const cxchar *regexp)
764 const cxchar *fctid =
"giraffe_propertylist_update";
770 cx_assert(
self != NULL);
772 if (properties == NULL) {
773 cpl_error_set(fctid, CPL_ERROR_NULL_INPUT);
777 sz = cpl_propertylist_get_size(properties);
779 if (regexp == NULL || regexp[0] ==
'\0') {
781 for (i = 0; i < sz; i++) {
783 cpl_property *p = cpl_propertylist_get(properties, i);
784 const cxchar *name = cpl_property_get_name(p);
787 if (!cpl_propertylist_has(
self, name)) {
789 cxint status = _giraffe_plist_append(
self, p);
792 cpl_error_set(fctid, CPL_ERROR_INVALID_TYPE);
805 status = regcomp(&re, regexp, REG_EXTENDED | REG_NOSUB);
808 cpl_error_set(fctid, CPL_ERROR_ILLEGAL_INPUT);
812 for (i = 0; i < sz; i++) {
814 cpl_property *p = cpl_propertylist_get(properties, i);
815 const cxchar *name = cpl_property_get_name(p);
818 if (regexec(&re, name, (
size_t)0, NULL, 0) == REG_NOMATCH) {
822 if (!cpl_propertylist_has(
self, name)) {
824 status = _giraffe_plist_append(
self, p);
827 cpl_error_set(fctid, CPL_ERROR_INVALID_TYPE);
852 const cpl_propertylist *other,
853 const cxchar *othername)
856 const cxchar *fctid =
"giraffe_propertylist_copy";
860 const cxchar *comment;
866 cx_assert(
self != NULL);
872 if (othername == NULL) {
876 if (!cpl_propertylist_has(other, othername)) {
880 type = cpl_propertylist_get_type(other, othername);
887 s = name == NULL ? othername : name;
897 cxchar value = cpl_propertylist_get_char(other, othername);
899 if (cpl_propertylist_has(
self, s)) {
900 cpl_propertylist_set_char(
self, s, value);
903 cpl_propertylist_append_char(
self, s, value);
910 cxbool value = cpl_propertylist_get_bool(other, othername);
912 if (cpl_propertylist_has(
self, s)) {
913 cpl_propertylist_set_bool(
self, s, value);
916 cpl_propertylist_append_bool(
self, s, value);
923 cxint value = cpl_propertylist_get_int(other, othername);
925 if (cpl_propertylist_has(
self, s)) {
926 cpl_propertylist_set_int(
self, s, value);
929 cpl_propertylist_append_int(
self, s, value);
936 cxlong value = cpl_propertylist_get_long(other, othername);
938 if (cpl_propertylist_has(
self, s)) {
939 cpl_propertylist_set_long(
self, s, value);
942 cpl_propertylist_append_long(
self, s, value);
949 cxfloat value = cpl_propertylist_get_float(other, othername);
951 if (cpl_propertylist_has(
self, s)) {
952 cpl_propertylist_set_float(
self, s, value);
955 cpl_propertylist_append_float(
self, s, value);
960 case CPL_TYPE_DOUBLE:
962 cxdouble value = cpl_propertylist_get_double(other, othername);
964 if (cpl_propertylist_has(
self, s)) {
965 cpl_propertylist_set_double(
self, s, value);
968 cpl_propertylist_append_double(
self, s, value);
973 case CPL_TYPE_STRING:
975 const cxchar *value = cpl_propertylist_get_string(other,
978 if (cpl_propertylist_has(
self, s)) {
979 cpl_propertylist_set_string(
self, s, value);
982 cpl_propertylist_append_string(
self, s, value);
988 cpl_error_set(fctid, CPL_ERROR_INVALID_TYPE);
993 comment = cpl_propertylist_get_comment(other, othername);
995 if (comment != NULL) {
996 cpl_propertylist_set_comment(
self, s, comment);
1005 giraffe_propertylist_update_wcs(cpl_propertylist* properties, cxsize naxis,
1006 const cxdouble* crpix,
const cxdouble* crval,
1007 const cxchar** ctype,
const cxchar** cunit,
1008 const cpl_matrix* cd)
1011 if (properties == NULL) {
1015 cpl_propertylist_erase_regexp(properties,
"^CRPIX[0-9]", 0);
1016 cpl_propertylist_erase_regexp(properties,
"^CRVAL[0-9]", 0);
1017 cpl_propertylist_erase_regexp(properties,
"^CDELT[0-9]", 0);
1018 cpl_propertylist_erase_regexp(properties,
"^CTYPE[0-9]", 0);
1019 cpl_propertylist_erase_regexp(properties,
"^CUNIT[0-9]", 0);
1020 cpl_propertylist_erase_regexp(properties,
"^CROTA[0-9]", 0);
1021 cpl_propertylist_erase_regexp(properties,
"^CD[0-9]*_[0-9]", 0);
1022 cpl_propertylist_erase_regexp(properties,
"^PC[0-9]*_[0-9]", 0);
1028 register cxsize i = 0;
1030 cx_string* keyword = cx_string_new();
1031 cx_string* comment = cx_string_new();
1034 cx_assert(cpl_matrix_get_nrow(cd) == cpl_matrix_get_ncol(cd));
1036 for (i = 0; i < naxis; i++) {
1038 cx_string_sprintf(keyword,
"CTYPE%-" CX_PRINTF_FORMAT_SIZE_TYPE,
1040 cx_string_sprintf(comment,
"Coordinate system of axis %"
1041 CX_PRINTF_FORMAT_SIZE_TYPE, i + 1);
1042 cpl_propertylist_append_string(properties,
1043 cx_string_get(keyword), ctype[i]);
1044 cpl_propertylist_set_comment(properties, cx_string_get(keyword),
1045 cx_string_get(comment));
1049 for (i = 0; i < naxis; i++) {
1051 cx_string_sprintf(keyword,
"CRPIX%-" CX_PRINTF_FORMAT_SIZE_TYPE,
1053 cx_string_sprintf(comment,
"Reference pixel of axis %"
1054 CX_PRINTF_FORMAT_SIZE_TYPE, i + 1);
1055 cpl_propertylist_append_double(properties,
1056 cx_string_get(keyword), crpix[i]);
1057 cpl_propertylist_set_comment(properties, cx_string_get(keyword),
1058 cx_string_get(comment));
1062 for (i = 0; i < naxis; i++) {
1064 cx_string_sprintf(keyword,
"CRVAL%-" CX_PRINTF_FORMAT_SIZE_TYPE,
1066 cx_string_sprintf(comment,
"Coordinate of axis %"
1067 CX_PRINTF_FORMAT_SIZE_TYPE
" at reference "
1069 cpl_propertylist_append_double(properties,
1070 cx_string_get(keyword), crval[i]);
1071 cpl_propertylist_set_comment(properties, cx_string_get(keyword),
1072 cx_string_get(comment));
1076 for (i = 0; i < naxis; i++) {
1078 if (cunit[i] != NULL) {
1079 cx_string_sprintf(keyword,
"CUNIT%-"
1080 CX_PRINTF_FORMAT_SIZE_TYPE, i + 1);
1081 cx_string_sprintf(comment,
"Unit of coordinate axis %"
1082 CX_PRINTF_FORMAT_SIZE_TYPE, i + 1);
1083 cpl_propertylist_append_string(properties,
1084 cx_string_get(keyword),
1086 cpl_propertylist_set_comment(properties,
1087 cx_string_get(keyword),
1088 cx_string_get(comment));
1098 for (i = 0; i < naxis; i++) {
1100 register cxsize j = 0;
1103 for (j = 0; j < naxis; j++) {
1105 cx_string_sprintf(keyword,
"CD%-" CX_PRINTF_FORMAT_SIZE_TYPE
1106 "_%-" CX_PRINTF_FORMAT_SIZE_TYPE, i + 1,
1108 cx_string_sprintf(comment,
"Coordinate transformation matrix "
1110 cpl_propertylist_append_double(properties,
1111 cx_string_get(keyword),
1112 cpl_matrix_get(cd, i, j));
1113 cpl_propertylist_set_comment(properties,
1114 cx_string_get(keyword),
1115 cx_string_get(comment));
1120 cx_string_delete(keyword);
1123 cx_string_delete(comment);
1134 giraffe_frameset_set_groups(cpl_frameset*
set, GiGroupInfo *groups)
1137 cpl_frame* frame = NULL;
1139 cpl_frameset_iterator *it = NULL;
1146 if (groups == NULL || groups->tag == NULL) {
1150 it = cpl_frameset_iterator_new(
set);
1152 while ((frame = cpl_frameset_iterator_get(it)) != NULL) {
1154 const cxchar* tag = cpl_frame_get_tag(frame);
1157 cpl_frame_get_group(frame) == CPL_FRAME_GROUP_NONE) {
1159 const GiGroupInfo* g = groups;
1161 while (g->tag != NULL) {
1162 if (strcmp(tag, g->tag) == 0) {
1163 cpl_frame_set_group(frame, g->group);
1171 cpl_frameset_iterator_advance(it, 1);
1175 cpl_frameset_iterator_delete(it);
1216 const cxchar*
const fctid =
"giraffe_propertylist_get_ron";
1222 cx_assert(properties != NULL);
1224 if (!cpl_propertylist_has(properties, GIALIAS_BIASSIGMA)) {
1225 if (!cpl_propertylist_has(properties, GIALIAS_RON)) {
1226 cpl_msg_error(fctid,
"Missing detector read-out noise "
1227 "property (%s)!", GIALIAS_RON);
1228 cpl_error_set(fctid, CPL_ERROR_DATA_NOT_FOUND);
1239 cpl_msg_warning(fctid,
"Missing bias RMS property (%s)! "
1240 "Using detector read-out noise property (%s).",
1241 GIALIAS_BIASSIGMA, GIALIAS_RON);
1242 ron = cpl_propertylist_get_double(properties, GIALIAS_RON);
1247 cxdouble conad = 0.;
1255 if (!cpl_propertylist_has(properties, GIALIAS_CONAD)) {
1256 cpl_msg_error(fctid,
"Missing detector gain property (%s)! ",
1258 cpl_error_set(fctid, CPL_ERROR_DATA_NOT_FOUND);
1263 conad = cpl_propertylist_get_double(properties, GIALIAS_CONAD);
1267 cpl_msg_error(fctid,
"Invalid conversion factor (%s) %.3g "
1268 "[e-/ADU]", GIALIAS_CONAD, conad);
1269 cpl_error_set(fctid, CPL_ERROR_ILLEGAL_INPUT);
1274 ron = cpl_propertylist_get_double(properties, GIALIAS_BIASSIGMA) *