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"
64 static const cxchar *_giraffe_license =
65 " This file is part of the GIRAFFE Instrument Pipeline\n"
66 " Copyright (C) 2002-2014 European Southern Observatory\n"
68 " This program is free software; you can redistribute it and/or modify\n"
69 " it under the terms of the GNU General Public License as published by\n"
70 " the Free Software Foundation; either version 2 of the License, or\n"
71 " (at your option) any later version.\n"
73 " This program is distributed in the hope that it will be useful,\n"
74 " but WITHOUT ANY WARRANTY; without even the implied warranty of\n"
75 " MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the\n"
76 " GNU General Public License for more details.\n"
78 " You should have received a copy of the GNU General Public License\n"
79 " along with this program; if not, write to the Free Software\n"
80 " Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301"
85 _giraffe_plist_append(cpl_propertylist *
self, cpl_property *p)
88 const cxchar *name = cpl_property_get_name(p);
89 const cxchar *comment = cpl_property_get_comment(p);
92 switch (cpl_property_get_type(p)) {
95 cxbool value = cpl_property_get_bool(p);
97 cpl_propertylist_append_bool(
self, name, value);
103 cxchar value = cpl_property_get_char(p);
105 cpl_propertylist_append_char(
self, name, value);
111 cxint value = cpl_property_get_int(p);
113 cpl_propertylist_append_int(
self, name, value);
119 cxlong value = cpl_property_get_long(p);
121 cpl_propertylist_append_long(
self, name, value);
127 cxfloat value = cpl_property_get_float(p);
129 cpl_propertylist_append_float(
self, name, value);
133 case CPL_TYPE_DOUBLE:
135 cxdouble value = cpl_property_get_double(p);
137 cpl_propertylist_append_double(
self, name, value);
141 case CPL_TYPE_STRING:
143 const cxchar *value = cpl_property_get_string(p);
145 cpl_propertylist_append_string(
self, name, value);
161 if (comment != NULL) {
162 cpl_propertylist_set_comment(
self, name, comment);
171 _giraffe_add_frame_info(cpl_propertylist *plist,
const cxchar *name,
172 const cxchar *tag, cxint sequence, cxint frame_index,
176 const cxchar *
id = NULL;
177 const cxchar *group = NULL;
181 cx_string *key = NULL;
182 cx_string *comment = NULL;
197 group =
"calibration";
205 key = cx_string_new();
206 comment = cx_string_new();
213 cx_string_sprintf(key,
"%s%-d %s%-d %s",
"ESO PRO REC", sequence,
id,
214 frame_index,
"NAME");
215 cx_string_sprintf(comment,
"%s %s %s",
"File name of", group,
"frame");
217 status = cpl_propertylist_update_string(plist, cx_string_get(key), name);
219 if (status != CPL_ERROR_NONE) {
220 cx_string_delete(key);
221 cx_string_delete(comment);
226 status = cpl_propertylist_set_comment(plist, cx_string_get(key),
227 cx_string_get(comment));
230 cx_string_delete(key);
231 cx_string_delete(comment);
241 cx_string_sprintf(key,
"%s%-d %s%-d %s",
"ESO PRO REC", sequence,
id,
242 frame_index,
"CATG");
243 cx_string_sprintf(comment,
"%s %s %s",
"Frame category of", group,
246 status = cpl_propertylist_update_string(plist, cx_string_get(key), tag);
248 if (status != CPL_ERROR_NONE) {
249 cx_string_delete(key);
250 cx_string_delete(comment);
255 status = cpl_propertylist_set_comment(plist, cx_string_get(key),
256 cx_string_get(comment));
259 cx_string_delete(key);
260 cx_string_delete(comment);
265 cx_string_delete(key);
266 cx_string_delete(comment);
287 return _giraffe_license;
309 const cxchar *fctid =
"giraffe_get_mode";
314 GiInstrumentMode insmode;
318 cpl_error_set(fctid, CPL_ERROR_NULL_INPUT);
323 if (!cpl_propertylist_has(properties, GIALIAS_INSMODE)) {
324 gi_warning(
"%s: Property (%s) not found\n", fctid, GIALIAS_INSMODE);
326 if (!cpl_propertylist_has(properties, GIALIAS_SLITNAME)) {
327 cx_warning(
"%s: Property (%s) not found\n", fctid,
332 mode = cpl_propertylist_get_string(properties, GIALIAS_SLITNAME);
336 mode = cpl_propertylist_get_string(properties, GIALIAS_SLITNAME);
339 if (!mode || strlen(mode) == 0) {
340 cpl_error_set(fctid, CPL_ERROR_ILLEGAL_INPUT);
345 s = cx_string_create(mode);
348 if (strncmp(cx_string_get(s),
"med", 3) == 0) {
349 insmode = GIMODE_MEDUSA;
351 else if (strncmp(cx_string_get(s),
"ifu", 3) == 0) {
352 insmode = GIMODE_IFU;
354 else if (strncmp(cx_string_get(s),
"arg", 3) == 0) {
355 insmode = GIMODE_ARGUS;
358 cpl_error_set(fctid, CPL_ERROR_UNSUPPORTED_MODE);
359 insmode = GIMODE_NONE;
387 register cxssize base;
388 register cxssize last_nonslash;
399 if (path[0] ==
'\0') {
400 return cx_strdup(
".");
403 last_nonslash = strlen(path) - 1;
405 while (last_nonslash >= 0 && path[last_nonslash] ==
'/') {
412 if (last_nonslash == -1) {
413 return cx_strdup(
"/");
416 base = last_nonslash;
418 while (base >=0 && path[base] !=
'/') {
422 len = last_nonslash - base;
424 result = cx_malloc(len + 1);
425 memcpy(result, path + base + 1, len);
451 time_t seconds = time(NULL);
453 cxchar *sdate = NULL;
455 cxulong milliseconds = 0;
457 cx_string *
self = cx_string_new();
460 cx_assert(
self != NULL);
462 ts = localtime(&seconds);
464 cx_string_sprintf(
self,
"%4d-%02d-%02dT%02d:%02d:%02d.%03ld",
473 sdate = cx_strdup(cx_string_get(
self));
474 cx_string_delete(
self);
500 cx_string *name = cx_string_new();
501 cx_string *value = cx_string_new();
504 cx_string_sprintf(name,
"%s%-d %s",
"ESO PRO REC", info->sequence,
506 cx_string_sprintf(value,
"%s/%s", PACKAGE, VERSION);
508 status = cpl_propertylist_update_string(plist, cx_string_get(name),
509 cx_string_get(value));
512 if (status != CPL_ERROR_NONE) {
513 cx_string_delete(name);
514 cx_string_delete(value);
519 status = cpl_propertylist_set_comment(plist, cx_string_get(name),
520 "Pipeline (unique) identifier");
523 cx_string_delete(name);
524 cx_string_delete(value);
529 if (info->start != NULL) {
530 cx_string_sprintf(name,
"%s%-d %s",
"ESO PRO REC",
531 info->sequence,
"START");
532 status = cpl_propertylist_update_string(plist,
536 if (status != CPL_ERROR_NONE) {
537 cx_string_delete(name);
538 cx_string_delete(value);
543 status = cpl_propertylist_set_comment(plist, cx_string_get(name),
544 "Date when recipe execution "
548 cx_string_delete(name);
549 cx_string_delete(value);
555 cx_string_delete(name);
556 cx_string_delete(value);
600 cx_string *key = cx_string_new();
602 const cpl_frame *frame = NULL;
604 cpl_frameset_iterator *it = cpl_frameset_iterator_new(set);
607 while ((frame = cpl_frameset_iterator_get_const(it)) != NULL) {
609 cpl_frame_group group = cpl_frame_get_group(frame);
611 const cxchar *name = cpl_frame_get_filename(frame);
612 const cxchar *tag = cpl_frame_get_tag(frame);
616 cx_assert(base != NULL);
619 case CPL_FRAME_GROUP_RAW:
632 if (!cpl_propertylist_has(plist, GIALIAS_ANCESTOR)) {
636 cpl_propertylist *_plist = cpl_propertylist_load(name, 0);
638 if (_plist == NULL) {
641 cx_free((cxchar *)base);
644 cpl_frameset_iterator_delete(it);
645 cx_string_delete(key);
651 if (cpl_propertylist_has(_plist, GIALIAS_ANCESTOR)) {
652 cpl_propertylist_copy_property(plist, _plist,
658 cpl_propertylist_get_string(_plist,
660 const cxchar *c =
"Inherited archive file name "
661 "of the first raw data frame";
664 cpl_propertylist_append_string(plist,
665 GIALIAS_ANCESTOR, s);
666 cpl_propertylist_set_comment(plist,
667 GIALIAS_ANCESTOR, c);
672 cpl_propertylist_delete(_plist);
679 status = _giraffe_add_frame_info(plist, base, tag,
684 cx_free((cxchar *)base);
687 cpl_frameset_iterator_delete(it);
688 cx_string_delete(key);
697 case CPL_FRAME_GROUP_CALIB:
700 cpl_propertylist *_plist = NULL;
704 cxint status = _giraffe_add_frame_info(plist, base, tag,
705 sequence, ncalib, 1);
709 cx_free((cxchar *)base);
712 cpl_frameset_iterator_delete(it);
713 cx_string_delete(key);
718 _plist = cpl_propertylist_load(name, 0);
720 if (_plist == NULL) {
722 cx_free((cxchar *)base);
725 cpl_frameset_iterator_delete(it);
726 cx_string_delete(key);
732 if (cpl_propertylist_has(_plist, GIALIAS_DATAMD5)) {
735 cpl_propertylist_get_string(_plist, GIALIAS_DATAMD5);
737 if (strcmp(s,
"Not computed") != 0) {
739 cx_string* md5 = cx_string_new();
741 cx_string_sprintf(md5,
"%s%d %s%"
742 CX_PRINTF_FORMAT_SIZE_TYPE
"%s",
743 "ESO PRO REC", sequence,
"CAL",
747 cpl_propertylist_update_string(plist,
751 if (status != CPL_ERROR_NONE) {
752 cx_string_delete(md5);
753 cpl_propertylist_delete(_plist);
756 cx_free((cxchar *)base);
759 cpl_frameset_iterator_delete(it);
760 cx_string_delete(key);
765 cx_string_delete(md5);
770 cpl_propertylist_delete(_plist);
780 cx_free((cxchar *)base);
783 cpl_frameset_iterator_advance(it, 1);
787 cpl_frameset_iterator_delete(it);
788 cx_string_delete(key);
819 cpl_propertylist *properties,
820 const cxchar *regexp)
823 const cxchar *fctid =
"giraffe_propertylist_update";
829 cx_assert(
self != NULL);
831 if (properties == NULL) {
832 cpl_error_set(fctid, CPL_ERROR_NULL_INPUT);
836 sz = cpl_propertylist_get_size(properties);
838 if (regexp == NULL || regexp[0] ==
'\0') {
840 for (i = 0; i < sz; i++) {
842 cpl_property *p = cpl_propertylist_get(properties, i);
843 const cxchar *name = cpl_property_get_name(p);
846 if (!cpl_propertylist_has(
self, name)) {
848 cxint status = _giraffe_plist_append(
self, p);
851 cpl_error_set(fctid, CPL_ERROR_INVALID_TYPE);
864 status = regcomp(&re, regexp, REG_EXTENDED | REG_NOSUB);
867 cpl_error_set(fctid, CPL_ERROR_ILLEGAL_INPUT);
871 for (i = 0; i < sz; i++) {
873 cpl_property *p = cpl_propertylist_get(properties, i);
874 const cxchar *name = cpl_property_get_name(p);
877 if (regexec(&re, name, (
size_t)0, NULL, 0) == REG_NOMATCH) {
881 if (!cpl_propertylist_has(
self, name)) {
883 status = _giraffe_plist_append(
self, p);
886 cpl_error_set(fctid, CPL_ERROR_INVALID_TYPE);
911 const cpl_propertylist *other,
912 const cxchar *othername)
915 const cxchar *fctid =
"giraffe_propertylist_copy";
919 const cxchar *comment;
925 cx_assert(
self != NULL);
931 if (othername == NULL) {
935 if (!cpl_propertylist_has(other, othername)) {
939 type = cpl_propertylist_get_type(other, othername);
946 s = name == NULL ? othername : name;
956 cxchar value = cpl_propertylist_get_char(other, othername);
958 if (cpl_propertylist_has(
self, s)) {
959 cpl_propertylist_set_char(
self, s, value);
962 cpl_propertylist_append_char(
self, s, value);
969 cxbool value = cpl_propertylist_get_bool(other, othername);
971 if (cpl_propertylist_has(
self, s)) {
972 cpl_propertylist_set_bool(
self, s, value);
975 cpl_propertylist_append_bool(
self, s, value);
982 cxint value = cpl_propertylist_get_int(other, othername);
984 if (cpl_propertylist_has(
self, s)) {
985 cpl_propertylist_set_int(
self, s, value);
988 cpl_propertylist_append_int(
self, s, value);
995 cxlong value = cpl_propertylist_get_long(other, othername);
997 if (cpl_propertylist_has(
self, s)) {
998 cpl_propertylist_set_long(
self, s, value);
1001 cpl_propertylist_append_long(
self, s, value);
1006 case CPL_TYPE_FLOAT:
1008 cxfloat value = cpl_propertylist_get_float(other, othername);
1010 if (cpl_propertylist_has(
self, s)) {
1011 cpl_propertylist_set_float(
self, s, value);
1014 cpl_propertylist_append_float(
self, s, value);
1019 case CPL_TYPE_DOUBLE:
1021 cxdouble value = cpl_propertylist_get_double(other, othername);
1023 if (cpl_propertylist_has(
self, s)) {
1024 cpl_propertylist_set_double(
self, s, value);
1027 cpl_propertylist_append_double(
self, s, value);
1032 case CPL_TYPE_STRING:
1034 const cxchar *value = cpl_propertylist_get_string(other,
1037 if (cpl_propertylist_has(
self, s)) {
1038 cpl_propertylist_set_string(
self, s, value);
1041 cpl_propertylist_append_string(
self, s, value);
1047 cpl_error_set(fctid, CPL_ERROR_INVALID_TYPE);
1052 comment = cpl_propertylist_get_comment(other, othername);
1054 if (comment != NULL) {
1055 cpl_propertylist_set_comment(
self, s, comment);
1064 giraffe_propertylist_update_wcs(cpl_propertylist* properties, cxsize naxis,
1065 const cxdouble* crpix,
const cxdouble* crval,
1066 const cxchar** ctype,
const cxchar** cunit,
1067 const cpl_matrix* cd)
1070 if (properties == NULL) {
1074 cpl_propertylist_erase_regexp(properties,
"^CRPIX[0-9]", 0);
1075 cpl_propertylist_erase_regexp(properties,
"^CRVAL[0-9]", 0);
1076 cpl_propertylist_erase_regexp(properties,
"^CDELT[0-9]", 0);
1077 cpl_propertylist_erase_regexp(properties,
"^CTYPE[0-9]", 0);
1078 cpl_propertylist_erase_regexp(properties,
"^CUNIT[0-9]", 0);
1079 cpl_propertylist_erase_regexp(properties,
"^CROTA[0-9]", 0);
1080 cpl_propertylist_erase_regexp(properties,
"^CD[0-9]*_[0-9]", 0);
1081 cpl_propertylist_erase_regexp(properties,
"^PC[0-9]*_[0-9]", 0);
1087 register cxsize i = 0;
1089 cx_string* keyword = cx_string_new();
1090 cx_string* comment = cx_string_new();
1093 cx_assert(cpl_matrix_get_nrow(cd) == cpl_matrix_get_ncol(cd));
1095 for (i = 0; i < naxis; i++) {
1097 cx_string_sprintf(keyword,
"CTYPE%-" CX_PRINTF_FORMAT_SIZE_TYPE,
1099 cx_string_sprintf(comment,
"Coordinate system of axis %"
1100 CX_PRINTF_FORMAT_SIZE_TYPE, i + 1);
1101 cpl_propertylist_append_string(properties,
1102 cx_string_get(keyword), ctype[i]);
1103 cpl_propertylist_set_comment(properties, cx_string_get(keyword),
1104 cx_string_get(comment));
1108 for (i = 0; i < naxis; i++) {
1110 cx_string_sprintf(keyword,
"CRPIX%-" CX_PRINTF_FORMAT_SIZE_TYPE,
1112 cx_string_sprintf(comment,
"Reference pixel of axis %"
1113 CX_PRINTF_FORMAT_SIZE_TYPE, i + 1);
1114 cpl_propertylist_append_double(properties,
1115 cx_string_get(keyword), crpix[i]);
1116 cpl_propertylist_set_comment(properties, cx_string_get(keyword),
1117 cx_string_get(comment));
1121 for (i = 0; i < naxis; i++) {
1123 cx_string_sprintf(keyword,
"CRVAL%-" CX_PRINTF_FORMAT_SIZE_TYPE,
1125 cx_string_sprintf(comment,
"Coordinate of axis %"
1126 CX_PRINTF_FORMAT_SIZE_TYPE
" at reference "
1128 cpl_propertylist_append_double(properties,
1129 cx_string_get(keyword), crval[i]);
1130 cpl_propertylist_set_comment(properties, cx_string_get(keyword),
1131 cx_string_get(comment));
1135 for (i = 0; i < naxis; i++) {
1137 if (cunit[i] != NULL) {
1138 cx_string_sprintf(keyword,
"CUNIT%-"
1139 CX_PRINTF_FORMAT_SIZE_TYPE, i + 1);
1140 cx_string_sprintf(comment,
"Unit of coordinate axis %"
1141 CX_PRINTF_FORMAT_SIZE_TYPE, i + 1);
1142 cpl_propertylist_append_string(properties,
1143 cx_string_get(keyword),
1145 cpl_propertylist_set_comment(properties,
1146 cx_string_get(keyword),
1147 cx_string_get(comment));
1157 for (i = 0; i < naxis; i++) {
1159 register cxsize j = 0;
1162 for (j = 0; j < naxis; j++) {
1164 cx_string_sprintf(keyword,
"CD%-" CX_PRINTF_FORMAT_SIZE_TYPE
1165 "_%-" CX_PRINTF_FORMAT_SIZE_TYPE, i + 1,
1167 cx_string_sprintf(comment,
"Coordinate transformation matrix "
1169 cpl_propertylist_append_double(properties,
1170 cx_string_get(keyword),
1171 cpl_matrix_get(cd, i, j));
1172 cpl_propertylist_set_comment(properties,
1173 cx_string_get(keyword),
1174 cx_string_get(comment));
1179 cx_string_delete(keyword);
1182 cx_string_delete(comment);
1193 giraffe_frameset_set_groups(cpl_frameset* set, GiGroupInfo *groups)
1196 cpl_frame* frame = NULL;
1198 cpl_frameset_iterator *it = NULL;
1205 if (groups == NULL || groups->tag == NULL) {
1209 it = cpl_frameset_iterator_new(set);
1211 while ((frame = cpl_frameset_iterator_get(it)) != NULL) {
1213 const cxchar* tag = cpl_frame_get_tag(frame);
1216 cpl_frame_get_group(frame) == CPL_FRAME_GROUP_NONE) {
1218 const GiGroupInfo* g = groups;
1220 while (g->tag != NULL) {
1221 if (strcmp(tag, g->tag) == 0) {
1222 cpl_frame_set_group(frame, g->group);
1230 cpl_frameset_iterator_advance(it, 1);
1234 cpl_frameset_iterator_delete(it);
1277 const cxchar*
const fctid =
"giraffe_propertylist_get_conad";
1279 const cxchar *names[2] = {GIALIAS_CONAD, GIALIAS_CONAD_LEGACY};
1280 const cxchar *name = NULL;
1282 cxdouble conad = 1.;
1285 cx_assert(properties != NULL);
1288 if (!cpl_propertylist_has(properties, GIALIAS_CONAD)) {
1290 if (!cpl_propertylist_has(properties, GIALIAS_CONAD_LEGACY)) {
1292 cpl_msg_error(fctid,
"Missing detector gain property (%s, %s)! ",
1293 GIALIAS_CONAD, GIALIAS_CONAD_LEGACY);
1294 cpl_error_set(fctid, CPL_ERROR_DATA_NOT_FOUND);
1309 conad = cpl_propertylist_get_double(properties, name);
1313 cpl_msg_error(fctid,
"Invalid conversion factor (%s) %.3g "
1314 "[e-/ADU]", name, conad);
1315 cpl_error_set(fctid, CPL_ERROR_ILLEGAL_INPUT);
1361 const cxchar*
const fctid =
"giraffe_propertylist_get_ron";
1367 cx_assert(properties != NULL);
1369 if (!cpl_propertylist_has(properties, GIALIAS_BIASSIGMA)) {
1370 if (!cpl_propertylist_has(properties, GIALIAS_RON)) {
1371 cpl_msg_error(fctid,
"Missing detector read-out noise "
1372 "property (%s)!", GIALIAS_RON);
1373 cpl_error_set(fctid, CPL_ERROR_DATA_NOT_FOUND);
1384 cpl_msg_warning(fctid,
"Missing bias RMS property (%s)! "
1385 "Using detector read-out noise property (%s).",
1386 GIALIAS_BIASSIGMA, GIALIAS_RON);
1387 ron = cpl_propertylist_get_double(properties, GIALIAS_RON);
1392 cxdouble conad = 0.;
1400 giraffe_error_push();
1404 if (cpl_error_get_code() != CPL_ERROR_NONE) {
1408 giraffe_error_pop();
1410 ron = cpl_propertylist_get_double(properties, GIALIAS_BIASSIGMA) *
void gi_warning(const cxchar *format,...)
Log a warning.
GiInstrumentMode giraffe_get_mode(cpl_propertylist *properties)
Determines the instrument mode from a property list.
cxint giraffe_add_frameset_info(cpl_propertylist *plist, const cpl_frameset *set, cxint sequence)
Add frameset specific information to a property list.
cxdouble giraffe_propertylist_get_conad(const cpl_propertylist *properties)
Retrieve the ADU to electrons conversion factor from the given properties.
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.
const cxchar * giraffe_get_license(void)
Get the pipeline copyright and license.
cxint giraffe_add_recipe_info(cpl_propertylist *plist, const GiRecipeInfo *info)
Add recipe specific information to a property list.
cxdouble giraffe_propertylist_get_ron(const cpl_propertylist *properties)
Retrieve the read-out noise from the given properties.
cxint giraffe_propertylist_update(cpl_propertylist *self, cpl_propertylist *properties, const cxchar *regexp)
Update a property list.
cxchar * giraffe_path_get_basename(const cxchar *path)
Gets the name of a file without any leading directory components.
cxchar * giraffe_localtime_iso8601(void)
Get the current date and time in ISO 8601 format.