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 
57 static 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 
77 inline 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 
163 inline 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 
266 inline 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 
417 const cxchar *
419 {
420 
421  return _giraffe_license;
422 
423 }
424 
425 
439 GiInstrumentMode
440 giraffe_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 
517 cxchar *
518 giraffe_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 
579 cxchar *
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 
622 cxint
623 giraffe_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 
781 cxint
782 giraffe_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 
1012 cxint
1013 giraffe_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 
1103 cxint
1104 giraffe_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 
1258 cxint
1259 giraffe_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 
1387 cxint
1388 giraffe_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 
1469 cxdouble 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 
1552 cxdouble
1553 giraffe_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
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
cxchar * giraffe_localtime_iso8601(void)
Get the current date and time in ISO 8601 format.
Definition: giutils.c:580
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
cxint giraffe_propertylist_update(cpl_propertylist *self, cpl_propertylist *properties, const cxchar *regexp)
Update a property list.
Definition: giutils.c:1013
const cxchar * giraffe_get_license(void)
Get the pipeline copyright and license.
Definition: giutils.c:418
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.10.
Documentation copyright © 2002-2006 European Southern Observatory.
Generated on Thu Dec 15 2022 21:18:51 by doxygen 1.9.1 written by Dimitri van Heesch, © 1997-2004