33 #include <sys/types.h>
36 #include "irplib_sdp_spectrum.h"
38 #ifdef IRPLIB_USE_FITS_UPDATE_CHECKSUM
47 #ifndef cpl_error_set_regex
50 cpl_error_set_regex_macro(
const char *, cpl_error_code,
int,
51 const regex_t *,
const char *,
52 unsigned,
const char *, ...) CPL_ATTR_PRINTF(7,8);
54 #define cpl_error_set_regex(code, regcode, preg, ...) \
55 cpl_error_set_regex_macro(cpl_func, code, regcode, preg, \
56 __FILE__, __LINE__, __VA_ARGS__)
61 #define KEY_ARCFILE "ARCFILE"
62 #define KEY_ORIGFILE "ORIGFILE"
64 #define KEY_RA_COMMENT "[deg] Spectroscopic target position (J2000)"
66 #define KEY_DEC_COMMENT "[deg] Spectroscopic target position (J2000)"
67 #define KEY_EXPTIME "EXPTIME"
68 #define KEY_EXPTIME_COMMENT "[s] Total integration time per pixel"
69 #define KEY_TEXPTIME "TEXPTIME"
70 #define KEY_TEXPTIME_COMMENT "[s] Total integration time of all exposures"
71 #define KEY_TIMESYS "TIMESYS"
72 #define KEY_TIMESYS_COMMENT "Time system used"
73 #define KEY_MJDOBS "MJD-OBS"
74 #define KEY_MJDOBS_COMMENT "[d] Start of observations (days)"
75 #define KEY_MJDEND "MJD-END"
76 #define KEY_MJDEND_COMMENT "[d] End of observations (days)"
77 #define KEY_PRODLVL "PRODLVL"
78 #define KEY_PRODLVL_VALUE 2
79 #define KEY_PRODLVL_COMMENT "Phase 3 product level: 1-raw, 2-science grade, 3-advanced"
80 #define KEY_PROCSOFT "PROCSOFT"
81 #define KEY_PROCSOFT_COMMENT "ESO pipeline version"
82 #define KEY_PRODCATG "PRODCATG"
83 #define KEY_PRODCATG_COMMENT "Data product category"
84 #define KEY_ORIGIN "ORIGIN"
85 #define KEY_ORIGIN_VALUE "ESO"
86 #define KEY_ORIGIN_COMMENT "European Southern Observatory"
87 #define KEY_EXT_OBJ "EXT_OBJ"
88 #define KEY_EXT_OBJ_COMMENT "TRUE if extended"
89 #define KEY_DISPELEM "DISPELEM"
90 #define KEY_DISPELEM_COMMENT "Dispersive element name"
91 #define KEY_SPECSYS "SPECSYS"
92 #define KEY_SPECSYS_VALUE "TOPOCENT"
93 #define KEY_SPECSYS_COMMENT "Reference frame for spectral coordinates"
94 #define KEY_PROG_ID "PROG_ID"
95 #define KEY_PROG_ID_COMMENT "ESO programme identification"
96 #define KEY_OBID "OBID"
97 #define KEY_OBID_COMMENT "Observation block ID"
98 #define KEY_M_EPOCH "M_EPOCH"
99 #define KEY_M_EPOCH_COMMENT "TRUE if resulting from multiple epochs"
100 #define KEY_OBSTECH "OBSTECH"
101 #define KEY_OBSTECH_COMMENT "Technique for observation"
102 #define KEY_FLUXCAL "FLUXCAL"
103 #define KEY_FLUXCAL_COMMENT "Type of flux calibration (ABSOLUTE or UNCALIBRATED)"
104 #define KEY_CONTNORM "CONTNORM"
105 #define KEY_CONTNORM_COMMENT "TRUE if normalised to the continuum"
106 #define KEY_WAVELMIN "WAVELMIN"
107 #define KEY_WAVELMIN_COMMENT "[nm] Minimum wavelength"
108 #define KEY_WAVELMAX "WAVELMAX"
109 #define KEY_WAVELMAX_COMMENT "[nm] Maximum wavelength"
110 #define KEY_SPEC_BIN "SPEC_BIN"
111 #define KEY_SPEC_BIN_COMMENT "[nm] Wavelength bin size"
112 #define KEY_TOT_FLUX "TOT_FLUX"
113 #define KEY_TOT_FLUX_COMMENT "TRUE if photometric conditions and all source flux is captured"
114 #define KEY_FLUXERR "FLUXERR"
115 #define KEY_FLUXERR_VALUE -2
116 #define KEY_FLUXERR_COMMENT "Uncertainty in flux scale (%)"
117 #define KEY_REFERENC "REFERENC"
118 #define KEY_REFERENC_VALUE " "
119 #define KEY_REFERENC_COMMENT "Reference publication"
120 #define KEY_SPEC_RES "SPEC_RES"
121 #define KEY_SPEC_RES_COMMENT "Reference spectral resolving power"
122 #define KEY_SPEC_ERR "SPEC_ERR"
123 #define KEY_SPEC_ERR_COMMENT "[nm] Statistical error in spectral coordinate"
124 #define KEY_SPEC_SYE "SPEC_SYE"
125 #define KEY_SPEC_SYE_COMMENT "[nm] Systematic error in spectral coordinate"
126 #define KEY_LAMNLIN "LAMNLIN"
127 #define KEY_LAMNLIN_COMMENT "Number of arc lines used for the wavel. solution"
128 #define KEY_LAMRMS "LAMRMS"
129 #define KEY_LAMRMS_COMMENT "[nm] RMS of the residuals of the wavel. solution"
130 #define KEY_GAIN "GAIN"
131 #define KEY_GAIN_COMMENT "Conversion factor (e-/ADU) electrons per data unit"
132 #define KEY_DETRON "DETRON"
133 #define KEY_DETRON_COMMENT "Readout noise per output (e-)"
134 #define KEY_EFFRON "EFFRON"
135 #define KEY_EFFRON_COMMENT "Median effective readout noise (e-)"
136 #define KEY_SNR "SNR"
137 #define KEY_SNR_COMMENT "Median signal to noise ratio per order"
138 #define KEY_NCOMBINE "NCOMBINE"
139 #define KEY_NCOMBINE_COMMENT "No. of combined raw science data files"
140 #define KEY_PROV "PROV"
141 #define KEY_PROV_COMMENT "Originating raw science file"
142 #define KEY_ASSON "ASSON"
143 #define KEY_ASSON_COMMENT "Associated file name"
144 #define KEY_ASSOC "ASSOC"
145 #define KEY_ASSOC_COMMENT "Associated file category"
146 #define KEY_ASSOM "ASSOM"
147 #define KEY_ASSOM_COMMENT "Associated file md5sum"
148 #define KEY_VOCLASS "VOCLASS"
149 #define KEY_VOCLASS_VALUE "SPECTRUM V2.0"
150 #define KEY_VOCLASS_COMMENT "VO Data Model"
151 #define KEY_VOPUB "VOPUB"
152 #define KEY_VOPUB_VALUE "ESO/SAF"
153 #define KEY_VOPUB_COMMENT "VO Publishing Authority"
154 #define KEY_TITLE "TITLE"
155 #define KEY_TITLE_COMMENT "Dataset title"
156 #define KEY_OBJECT "OBJECT"
157 #define KEY_OBJECT_COMMENT "Target designation"
158 #define KEY_OBJECT_PHDU_COMMENT "Original target."
159 #define KEY_APERTURE "APERTURE"
160 #define KEY_APERTURE_COMMENT "[deg] Aperture diameter"
161 #define KEY_TELAPSE "TELAPSE"
162 #define KEY_TELAPSE_COMMENT "[s] Total elapsed time"
163 #define KEY_TMID "TMID"
164 #define KEY_TMID_COMMENT "[d] MJD mid exposure"
165 #define KEY_SPEC_VAL "SPEC_VAL"
166 #define KEY_SPEC_VAL_COMMENT "[nm] Mean wavelength"
167 #define KEY_SPEC_BW "SPEC_BW"
168 #define KEY_SPEC_BW_COMMENT "[nm] Bandpass width = Wmax - Wmin"
169 #define KEY_TDMIN(n) "TDMIN"#n
170 #define KEY_TDMIN1_COMMENT "Start in spectral coordinate"
171 #define KEY_TDMAX(n) "TDMAX"#n
172 #define KEY_TDMAX1_COMMENT "Stop in spectral coordinate"
173 #define KEY_TUTYP "TUTYP"
174 #define KEY_TUTYP_COMMENT "IVOA data model element for field "
175 #define KEY_TUCD "TUCD"
176 #define KEY_TUCD_COMMENT "UCD for field "
177 #define KEY_TCOMM "TCOMM"
178 #define KEY_TCOMM_COMMENT "Description for field "
179 #define KEY_NELEM "NELEM"
180 #define KEY_NELEM_COMMENT "Length of the data arrays"
181 #define KEY_EXTNAME "EXTNAME"
182 #define KEY_EXTNAME_VALUE "SPECTRUM"
183 #define KEY_EXTNAME_COMMENT "Extension name"
184 #define KEY_INHERIT "INHERIT"
185 #define KEY_INHERIT_VALUE CPL_TRUE
186 #define KEY_INHERIT_COMMENT "Primary header keywords are inherited"
189 #define ALL_KEYS_REGEXP \
227 KEY_ASSON "[0-9]+|" \
228 KEY_ASSOC "[0-9]+|" \
229 KEY_ASSOM "[0-9]+|" \
241 KEY_TUTYP "[0-9]+|" \
243 KEY_TCOMM "[0-9]+|" \
250 #define PRIMARY_HDU_KEYS_REGEXP \
288 KEY_ASSON "[0-9]+|" \
289 KEY_ASSOC "[0-9]+|" \
290 KEY_ASSOM "[0-9]+|" \
295 #define EXTENSION_HDU_KEYS_REGEXP \
309 KEY_TUTYP "[0-9]+|" \
311 KEY_TCOMM "[0-9]+|" \
317 #define GET_SET_METHODS(param, keyname, type, rettype, defaultval, comment) \
318 rettype irplib_sdp_spectrum_get_##param(const irplib_sdp_spectrum *self) \
320 cpl_ensure(self != NULL, CPL_ERROR_NULL_INPUT, defaultval); \
321 assert(self->proplist != NULL); \
322 if (cpl_propertylist_has(self->proplist, keyname)) { \
323 return cpl_propertylist_get_##type(self->proplist, keyname); \
328 cpl_error_code irplib_sdp_spectrum_reset_##param(irplib_sdp_spectrum *self) \
330 cpl_ensure_code(self != NULL, CPL_ERROR_NULL_INPUT); \
331 assert(self->proplist != NULL); \
332 (void) cpl_propertylist_erase(self->proplist, keyname); \
333 return CPL_ERROR_NONE; \
335 cpl_error_code irplib_sdp_spectrum_set_##param(irplib_sdp_spectrum *self, \
338 cpl_error_code error; \
339 cpl_ensure_code(self != NULL, CPL_ERROR_NULL_INPUT); \
340 assert(self->proplist != NULL); \
341 if (cpl_propertylist_has(self->proplist, keyname)) { \
342 error = cpl_propertylist_set_##type(self->proplist, keyname, value); \
344 error = cpl_propertylist_append_##type(self->proplist, keyname, value); \
346 error = cpl_propertylist_set_comment(self->proplist, keyname, comment);\
350 cpl_errorstate prestate = cpl_errorstate_get(); \
351 (void) cpl_propertylist_erase(self->proplist, keyname); \
352 cpl_errorstate_set(prestate); \
358 cpl_error_code irplib_sdp_spectrum_copy_##param(irplib_sdp_spectrum *self, \
359 const cpl_propertylist *plist, const char *name) \
362 cpl_ensure_code(self != NULL, CPL_ERROR_NULL_INPUT); \
363 assert(self->proplist != NULL); \
364 if (cpl_propertylist_has(plist, name)) { \
365 cpl_errorstate prestate = cpl_errorstate_get(); \
366 rettype value = cpl_propertylist_get_##type(plist, name); \
367 if (cpl_errorstate_is_equal(prestate)) { \
368 return irplib_sdp_spectrum_set_##param(self, value); \
370 return cpl_error_set_message(cpl_func, cpl_error_get_code(), \
371 "Could not set '%s'. Likely the source '%s' keyword has a" \
372 " different format or type.", keyname, name); \
375 return cpl_error_set_message(cpl_func, CPL_ERROR_DATA_NOT_FOUND, \
376 "Could not set '%s' since the '%s' keyword was not found.", \
381 #define GET_SET_ARRAY_METHODS(param, keyname, type, rettype, defaultval, \
383 rettype irplib_sdp_spectrum_get_##param(const irplib_sdp_spectrum *self, \
387 cpl_ensure(self != NULL, CPL_ERROR_NULL_INPUT, defaultval); \
388 assert(self->proplist != NULL); \
389 name = cpl_sprintf("%s%"CPL_SIZE_FORMAT, keyname, index); \
390 rettype result = defaultval; \
391 if (cpl_propertylist_has(self->proplist, name)) { \
392 result = cpl_propertylist_get_##type(self->proplist, name); \
397 cpl_error_code irplib_sdp_spectrum_reset_##param(irplib_sdp_spectrum *self, \
401 cpl_ensure_code(self != NULL, CPL_ERROR_NULL_INPUT); \
402 assert(self->proplist != NULL); \
403 name = cpl_sprintf("%s%"CPL_SIZE_FORMAT, keyname, index); \
404 (void) cpl_propertylist_erase(self->proplist, name); \
406 return CPL_ERROR_NONE; \
408 cpl_error_code irplib_sdp_spectrum_set_##param(irplib_sdp_spectrum *self, \
409 cpl_size index, rettype value)\
411 cpl_error_code error; \
413 cpl_ensure_code(self != NULL, CPL_ERROR_NULL_INPUT); \
414 assert(self->proplist != NULL); \
415 name = cpl_sprintf("%s%"CPL_SIZE_FORMAT, keyname, index); \
416 if (cpl_propertylist_has(self->proplist, name)) { \
417 error = cpl_propertylist_set_##type(self->proplist, name, value); \
419 error = cpl_propertylist_append_##type(self->proplist, name, value); \
421 error = cpl_propertylist_set_comment(self->proplist, name, comment);\
425 cpl_errorstate prestate = cpl_errorstate_get(); \
426 (void) cpl_propertylist_erase(self->proplist, name); \
427 cpl_errorstate_set(prestate); \
434 cpl_error_code irplib_sdp_spectrum_copy_##param(\
435 irplib_sdp_spectrum *self, cpl_size index, \
436 const cpl_propertylist *plist, const char *name) \
439 cpl_ensure_code(self != NULL, CPL_ERROR_NULL_INPUT); \
440 assert(self->proplist != NULL); \
441 if (cpl_propertylist_has(plist, name)) { \
442 cpl_errorstate prestate = cpl_errorstate_get(); \
443 rettype value = cpl_propertylist_get_##type(plist, name); \
444 if (cpl_errorstate_is_equal(prestate)) { \
445 return irplib_sdp_spectrum_set_##param(self, index, value); \
447 return cpl_error_set_message(cpl_func, cpl_error_get_code(), \
448 "Could not set '%s%"CPL_SIZE_FORMAT"'. Likely the source" \
449 " '%s' keyword has a different format or type.", \
450 keyname, index, name); \
453 return cpl_error_set_message(cpl_func, CPL_ERROR_DATA_NOT_FOUND, \
454 "Could not set '%s%"CPL_SIZE_FORMAT"' since the '%s'" \
455 " keyword was not found.", keyname, index, name); \
460 #define GET_SET_METHODS_TYPE_BOOL(param, keyname, comment) \
461 GET_SET_METHODS(param, keyname, bool, cpl_boolean, CPL_FALSE, comment)
463 #define GET_SET_METHODS_TYPE_DOUBLE(param, keyname, comment) \
464 GET_SET_METHODS(param, keyname, double, double, NAN, comment)
466 #define GET_SET_METHODS_TYPE_INT(param, keyname, comment) \
467 GET_SET_METHODS(param, keyname, int, int, -1, comment)
469 #define GET_SET_METHODS_TYPE_STRING(param, keyname, comment) \
470 GET_SET_METHODS(param, keyname, string, const char *, NULL, comment)
472 #define GET_SET_ARRAY_METHODS_TYPE_INT(param, keyname, comment) \
473 GET_SET_ARRAY_METHODS(param, keyname, int, int, -1, comment)
475 #define GET_SET_ARRAY_METHODS_TYPE_STRING(param, keyname, comment) \
476 GET_SET_ARRAY_METHODS(param, keyname, string, const char *, NULL, comment)
479 #define IRPLIB_TYPE_NELEM CPL_TYPE_LONG_LONG | CPL_TYPE_UNSPECIFIED
500 struct _irplib_sdp_spectrum_ {
505 cpl_propertylist *proplist;
516 typedef struct _irplib_keyword_record_ {
527 cpl_boolean is_array_key;
529 } irplib_keyword_record;
536 _irplib_property_equal(
const cpl_property *a,
const cpl_property *b);
539 _irplib_array_equal(
const cpl_array *a,
const cpl_array *b, cpl_size n);
542 _irplib_table_column_equal(
const cpl_table *a,
const cpl_table *b,
543 const char *name, cpl_boolean only_intersect);
545 static cpl_error_code
547 const cpl_table* table,
const char *from_name);
559 const char *name,
const char *keyword);
561 static cpl_error_code
566 const char *comment);
572 static char * _irplib_make_regexp(
const cpl_propertylist *plist,
576 static cpl_boolean _irplib_keyword_table_is_sorted(
577 const irplib_keyword_record *table,
size_t entries);
580 static const irplib_keyword_record *
581 _irplib_sdp_spectrum_get_keyword_record(
const char *name);
596 obj->proplist = cpl_propertylist_new();
597 obj->table = cpl_table_new(1);
611 cpl_ensure(other != NULL, CPL_ERROR_NULL_INPUT, NULL);
613 assert(other->proplist != NULL);
614 assert(other->table != NULL);
617 obj->nelem = other->nelem;
618 obj->proplist = cpl_propertylist_duplicate(other->proplist);
619 obj->table = cpl_table_duplicate(other->table);
631 assert(self->proplist != NULL);
632 assert(self->table != NULL);
633 cpl_propertylist_delete(self->proplist);
634 cpl_table_delete(self->table);
646 _irplib_property_equal(
const cpl_property *a,
const cpl_property *b)
656 type = cpl_property_get_type(a);
657 if (cpl_property_get_type(b) != type)
return CPL_FALSE;
662 value_not_equal = cpl_property_get_char(a) != cpl_property_get_char(b);
665 value_not_equal = cpl_property_get_bool(a) != cpl_property_get_bool(b);
668 value_not_equal = cpl_property_get_int(a) != cpl_property_get_int(b);
671 value_not_equal = cpl_property_get_long(a) != cpl_property_get_long(b);
673 case CPL_TYPE_LONG_LONG:
675 cpl_property_get_long_long(a) != cpl_property_get_long_long(b);
678 value_not_equal = cpl_property_get_float(a) != cpl_property_get_float(b);
680 case CPL_TYPE_DOUBLE:
681 value_not_equal = cpl_property_get_double(a) != cpl_property_get_double(b);
683 case CPL_TYPE_STRING:
684 sa = cpl_property_get_string(a);
685 sb = cpl_property_get_string(b);
686 if (sa == NULL && sb == NULL) {
688 }
else if (sa != NULL && sb != NULL) {
689 value_not_equal = strcmp(sa, sb) != 0;
695 case CPL_TYPE_FLOAT_COMPLEX:
697 cpl_property_get_float_complex(a) != cpl_property_get_float_complex(b);
699 case CPL_TYPE_DOUBLE_COMPLEX:
701 cpl_property_get_double_complex(a) != cpl_property_get_double_complex(b);
705 cpl_error_set_message(cpl_func, CPL_ERROR_INVALID_TYPE,
706 "Unsupported data type found in property '%s'.",
707 cpl_property_get_name(a));
710 if (value_not_equal)
return CPL_FALSE;
730 _irplib_array_equal(
const cpl_array *a,
const cpl_array *b, cpl_size n)
736 assert(n <= cpl_array_get_size(a));
737 assert(n <= cpl_array_get_size(b));
739 type = cpl_array_get_type(a);
740 if (type != cpl_array_get_type(b))
return CPL_FALSE;
742 if (type == CPL_TYPE_STRING) {
745 const char **stra = cpl_array_get_data_string_const(a);
746 const char **strb = cpl_array_get_data_string_const(b);
747 cpl_error_ensure(stra != NULL && strb != NULL, cpl_error_get_code(),
748 return CPL_FALSE,
"Failed to get %s data for array.",
749 cpl_type_get_name(type));
750 for (i = 0; i < n; ++i) {
751 if (stra[i] == NULL && strb[i] == NULL)
continue;
752 if (stra[i] == NULL || strb[i] == NULL)
return CPL_FALSE;
753 if (strcmp(stra[i], strb[i]) != 0)
return CPL_FALSE;
764 va = cpl_array_get_data_int_const(a);
765 vb = cpl_array_get_data_int_const(b);
767 case CPL_TYPE_LONG_LONG:
768 size =
sizeof(
long long);
769 va = cpl_array_get_data_long_long_const(a);
770 vb = cpl_array_get_data_long_long_const(b);
773 size =
sizeof(float);
774 va = cpl_array_get_data_float_const(a);
775 vb = cpl_array_get_data_float_const(b);
777 case CPL_TYPE_DOUBLE:
778 size =
sizeof(double);
779 va = cpl_array_get_data_double_const(a);
780 vb = cpl_array_get_data_double_const(b);
783 case CPL_TYPE_FLOAT_COMPLEX:
784 size =
sizeof(_Complex float);
785 va = cpl_array_get_data_float_complex_const(a);
786 vb = cpl_array_get_data_float_complex_const(b);
788 case CPL_TYPE_DOUBLE_COMPLEX:
789 size =
sizeof(_Complex double);
790 va = cpl_array_get_data_double_complex_const(a);
791 vb = cpl_array_get_data_double_complex_const(b);
795 cpl_error_set_message(cpl_func, CPL_ERROR_INVALID_TYPE,
796 "Unsupported data type.");
799 cpl_error_ensure(va != NULL && vb != NULL, cpl_error_get_code(),
800 return CPL_FALSE,
"Failed to get %s data for array.",
801 cpl_type_get_name(type));
802 for (i = 0; i < n; ++i) {
803 int valid_a = cpl_array_is_valid(a, i);
804 int valid_b = cpl_array_is_valid(b, i);
805 if (! valid_a && ! valid_b)
continue;
806 if (! valid_a || ! valid_b)
return CPL_FALSE;
807 const void *vai = (
const char *)va + (size * i);
808 const void *vbi = (
const char *)vb + (size * i);
809 if (memcmp(vai, vbi, size) != 0)
return CPL_FALSE;
832 _irplib_table_column_equal(
const cpl_table *a,
const cpl_table *b,
833 const char *name, cpl_boolean only_intersect)
836 cpl_size nrows, na, nb, i;
842 nrows = cpl_table_get_nrow(a);
843 if (only_intersect) {
844 cpl_size nrows2 = cpl_table_get_nrow(b);
845 if (nrows2 < nrows) nrows = nrows2;
847 if (cpl_table_get_nrow(b) != nrows)
return CPL_FALSE;
851 type = cpl_table_get_column_type(a, name);
852 if (cpl_table_get_column_type(b, name) != type)
return CPL_FALSE;
855 na = cpl_table_get_column_dimensions(a, name);
856 nb = cpl_table_get_column_dimensions(b, name);
857 if (na != nb)
return CPL_FALSE;
860 sa = cpl_table_get_column_unit(a, name);
861 sb = cpl_table_get_column_unit(b, name);
862 cpl_error_ensure(sa != NULL && sb != NULL, cpl_error_get_code(),
864 "Failed to get unit strings for column '%s'.", name);
865 if (strcmp(sa, sb) != 0)
return CPL_FALSE;
869 if (type & CPL_TYPE_POINTER) {
870 cpl_errorstate prestate;
872 const cpl_array **va = cpl_table_get_data_array_const(a, name);
873 const cpl_array **vb = cpl_table_get_data_array_const(b, name);
874 cpl_error_ensure(va != NULL && vb != NULL,
875 cpl_error_get_code(),
return CPL_FALSE,
876 "Failed to get %s data for column '%s'.",
877 cpl_type_get_name(type), name);
878 if (only_intersect) {
879 for (i = 0; i < nrows; ++i) {
882 if (va[i] == NULL && vb[i] == NULL)
continue;
883 if (va[i] == NULL || vb[i] == NULL)
return CPL_FALSE;
884 prestate = cpl_errorstate_get();
885 cpl_size n1 = cpl_array_get_size(va[i]);
886 cpl_size n2 = cpl_array_get_size(vb[i]);
887 cpl_size n = n1 < n2 ? n1 : n2;
888 if (! _irplib_array_equal(va[i], vb[i], n))
return CPL_FALSE;
889 cpl_error_ensure(cpl_errorstate_is_equal(prestate),
890 cpl_error_get_code(),
return CPL_FALSE,
891 "Failed when trying to match %s data for column '%s'.",
892 cpl_type_get_name(type), name);
895 for (i = 0; i < nrows; ++i) {
898 if (va[i] == NULL && vb[i] == NULL)
continue;
899 if (va[i] == NULL || vb[i] == NULL)
return CPL_FALSE;
900 prestate = cpl_errorstate_get();
901 cpl_size n = cpl_array_get_size(va[i]);
902 if (n != cpl_array_get_size(vb[i]))
return CPL_FALSE;
903 if (! _irplib_array_equal(va[i], vb[i], n))
return CPL_FALSE;
904 cpl_error_ensure(cpl_errorstate_is_equal(prestate),
905 cpl_error_get_code(),
return CPL_FALSE,
906 "Failed when trying to match %s data for column '%s'.",
907 cpl_type_get_name(type), name);
911 }
else if (type == CPL_TYPE_STRING) {
913 const char **va = cpl_table_get_data_string_const(a, name);
914 const char **vb = cpl_table_get_data_string_const(b, name);
915 cpl_error_ensure(va != NULL && vb != NULL,
916 cpl_error_get_code(),
return CPL_FALSE,
917 "Failed to get %s data for column '%s'.",
918 cpl_type_get_name(type), name);
919 if (only_intersect) {
920 for (i = 0; i < nrows; ++i) {
921 if (va[i] == NULL && vb[i] == NULL)
continue;
922 if (va[i] == NULL || vb[i] == NULL)
return CPL_FALSE;
923 size_t n1 = strlen(va[i]);
924 size_t n2 = strlen(vb[i]);
925 size_t n = n1 < n2 ? n1 : n2;
926 if (strncmp(va[i], vb[i], (cpl_size)n) != 0)
return CPL_FALSE;
929 for (i = 0; i < nrows; ++i) {
930 if (va[i] == NULL && vb[i] == NULL)
continue;
931 if (va[i] == NULL || vb[i] == NULL)
return CPL_FALSE;
932 if (strcmp(va[i], vb[i]) != 0)
return CPL_FALSE;
944 va = cpl_table_get_data_int_const(a, name);
945 vb = cpl_table_get_data_int_const(b, name);
947 case CPL_TYPE_LONG_LONG:
948 size =
sizeof(
long long);
949 va = cpl_table_get_data_long_long_const(a, name);
950 vb = cpl_table_get_data_long_long_const(b, name);
953 size =
sizeof(float);
954 va = cpl_table_get_data_float_const(a, name);
955 vb = cpl_table_get_data_float_const(b, name);
957 case CPL_TYPE_DOUBLE:
958 size =
sizeof(double);
959 va = cpl_table_get_data_double_const(a, name);
960 vb = cpl_table_get_data_double_const(b, name);
963 case CPL_TYPE_FLOAT_COMPLEX:
964 size =
sizeof(_Complex float);
965 va = cpl_table_get_data_float_complex_const(a, name);
966 vb = cpl_table_get_data_float_complex_const(b, name);
968 case CPL_TYPE_DOUBLE_COMPLEX:
969 size =
sizeof(_Complex double);
970 va = cpl_table_get_data_double_complex_const(a, name);
971 vb = cpl_table_get_data_double_complex_const(b, name);
975 cpl_error_set_message(cpl_func, CPL_ERROR_INVALID_TYPE,
976 "Unsupported data type found in column '%s'.", name);
979 cpl_error_ensure(va != NULL && vb != NULL,
980 cpl_error_get_code(),
return CPL_FALSE,
981 "Failed to get %s data for column '%s'.",
982 cpl_type_get_name(type), name);
983 for (i = 0; i < nrows; ++i) {
984 int valid_a = cpl_table_is_valid(a, name, i);
985 int valid_b = cpl_table_is_valid(b, name, i);
986 if (! valid_a && ! valid_b)
continue;
987 if (! valid_a || ! valid_b)
return CPL_FALSE;
988 const void *vai = (
const char *)va + (size * i);
989 const void *vbi = (
const char *)vb + (size * i);
990 if (memcmp(vai, vbi, size) != 0)
return CPL_FALSE;
1017 cpl_boolean only_intersect)
1019 cpl_errorstate prestate;
1021 cpl_boolean no_match = CPL_FALSE;
1024 const cpl_property *pa, *pb;
1026 cpl_ensure(a != NULL && b != NULL, CPL_ERROR_NULL_INPUT, CPL_FALSE);
1028 assert(a->proplist != NULL);
1029 assert(a->table != NULL);
1030 assert(b->proplist != NULL);
1031 assert(b->table != NULL);
1033 na = cpl_propertylist_get_size(a->proplist);
1035 if (only_intersect) {
1038 for (i = 0; i < na; ++i) {
1039 pa = cpl_propertylist_get_const(a->proplist, i);
1040 cpl_error_ensure(pa != NULL, cpl_error_get_code(),
return CPL_FALSE,
1041 "Failed to get property structure %"CPL_SIZE_FORMAT
".", i);
1042 name = cpl_property_get_name(pa);
1043 cpl_error_ensure(name != NULL, cpl_error_get_code(),
return CPL_FALSE,
1044 "Failed to get the name for property %"CPL_SIZE_FORMAT
".", i);
1045 pb = cpl_propertylist_get_property_const(b->proplist, name);
1047 prestate = cpl_errorstate_get();
1048 if (! _irplib_property_equal(pa, pb))
return CPL_FALSE;
1049 if (! cpl_errorstate_is_equal(prestate))
return CPL_FALSE;
1055 prestate = cpl_errorstate_get();
1056 na = cpl_table_get_ncol(a->table);
1057 names = cpl_table_get_column_names(a->table);
1058 for (i = 0; i < na; ++i) {
1059 name = cpl_array_get_string(names, i);
1060 cpl_error_ensure(name != NULL, cpl_error_get_code(),
break,
1061 "Failed to get the name for column %"CPL_SIZE_FORMAT
".", i);
1062 if (cpl_table_has_column(b->table, name)) {
1063 if (! _irplib_table_column_equal(a->table, b->table, name, CPL_TRUE)) {
1064 no_match = CPL_TRUE;
1069 cpl_array_delete(names);
1071 if (no_match || ! cpl_errorstate_is_equal(prestate))
return CPL_FALSE;
1075 if (a->nelem != b->nelem)
return CPL_FALSE;
1078 nb = cpl_propertylist_get_size(b->proplist);
1079 if (na != nb)
return CPL_FALSE;
1080 for (i = 0; i < na; ++i) {
1081 pa = cpl_propertylist_get_const(a->proplist, i);
1082 cpl_error_ensure(pa != NULL, cpl_error_get_code(),
return CPL_FALSE,
1083 "Failed to get property structure %"CPL_SIZE_FORMAT
".", i);
1084 name = cpl_property_get_name(pa);
1085 cpl_error_ensure(name != NULL, cpl_error_get_code(),
return CPL_FALSE,
1086 "Failed to get the name for property %"CPL_SIZE_FORMAT
".", i);
1087 pb = cpl_propertylist_get_property_const(b->proplist, name);
1088 if (pb == NULL)
return CPL_FALSE;
1089 prestate = cpl_errorstate_get();
1090 if (! _irplib_property_equal(pa, pb))
return CPL_FALSE;
1091 if (! cpl_errorstate_is_equal(prestate))
return CPL_FALSE;
1095 prestate = cpl_errorstate_get();
1096 na = cpl_table_get_ncol(a->table);
1097 nb = cpl_table_get_ncol(b->table);
1098 if (na != nb)
return CPL_FALSE;
1099 names = cpl_table_get_column_names(a->table);
1100 for (i = 0; i < na; ++i) {
1101 name = cpl_array_get_string(names, i);
1102 cpl_error_ensure(name != NULL, cpl_error_get_code(),
break,
1103 "Failed to get the name for column %"CPL_SIZE_FORMAT
".", i);
1104 if (! cpl_table_has_column(b->table, name)
1105 || ! _irplib_table_column_equal(a->table, b->table, name, CPL_FALSE))
1107 no_match = CPL_TRUE;
1111 cpl_array_delete(names);
1113 if (no_match || ! cpl_errorstate_is_equal(prestate))
return CPL_FALSE;
1130 cpl_error_code error;
1131 cpl_size result = 0;
1132 cpl_propertylist *list = cpl_propertylist_new();
1134 assert(
self != NULL);
1135 assert(self->proplist != NULL);
1137 error = cpl_propertylist_copy_property_regexp(list, self->proplist, regexp,
1140 result = cpl_propertylist_get_size(list);
1142 cpl_propertylist_delete(list);
1149 cpl_ensure(
self != NULL, CPL_ERROR_NULL_INPUT, 0);
1150 return _irplib_sdp_spectrum_count_keywords(
self,
"^OBID[0-9]+$");
1155 cpl_ensure(
self != NULL, CPL_ERROR_NULL_INPUT, 0);
1156 return _irplib_sdp_spectrum_count_keywords(
self,
"^PROV[0-9]+$");
1161 cpl_ensure(
self != NULL, CPL_ERROR_NULL_INPUT, 0);
1162 return _irplib_sdp_spectrum_count_keywords(
self,
"^ASSON[0-9]+$");
1167 cpl_ensure(
self != NULL, CPL_ERROR_NULL_INPUT, 0);
1168 return _irplib_sdp_spectrum_count_keywords(
self,
"^ASSOC[0-9]+$");
1173 cpl_ensure(
self != NULL, CPL_ERROR_NULL_INPUT, 0);
1174 return _irplib_sdp_spectrum_count_keywords(
self,
"^ASSOM[0-9]+$");
1184 static cpl_boolean _irplib_keyword_table_is_sorted(
1185 const irplib_keyword_record *table,
size_t entries)
1188 if (entries < 2)
return CPL_TRUE;
1189 for (i = 0; i < entries-1; ++i) {
1190 if (strcmp(table[i].name, table[i+1].name) >= 0) {
1200 static const irplib_keyword_record *
1201 _irplib_sdp_spectrum_get_keyword_record(
const char *name)
1206 static const irplib_keyword_record keyword_table[] = {
1208 {KEY_APERTURE, KEY_APERTURE_COMMENT, CPL_TYPE_DOUBLE, CPL_FALSE},
1209 {KEY_ASSOC, KEY_ASSOC_COMMENT, CPL_TYPE_STRING, CPL_TRUE},
1210 {KEY_ASSOM, KEY_ASSOM_COMMENT, CPL_TYPE_STRING, CPL_TRUE},
1211 {KEY_ASSON, KEY_ASSON_COMMENT, CPL_TYPE_STRING, CPL_TRUE},
1212 {KEY_CONTNORM, KEY_CONTNORM_COMMENT, CPL_TYPE_BOOL, CPL_FALSE},
1213 {KEY_DEC, KEY_DEC_COMMENT, CPL_TYPE_DOUBLE, CPL_FALSE},
1214 {KEY_DETRON, KEY_DETRON_COMMENT, CPL_TYPE_DOUBLE, CPL_FALSE},
1215 {KEY_DISPELEM, KEY_DISPELEM_COMMENT, CPL_TYPE_STRING, CPL_FALSE},
1216 {KEY_EFFRON, KEY_EFFRON_COMMENT, CPL_TYPE_DOUBLE, CPL_FALSE},
1217 {KEY_EXPTIME, KEY_EXPTIME_COMMENT, CPL_TYPE_DOUBLE, CPL_FALSE},
1218 {KEY_EXTNAME, KEY_EXTNAME_COMMENT, CPL_TYPE_STRING, CPL_FALSE},
1219 {KEY_EXT_OBJ, KEY_EXT_OBJ_COMMENT, CPL_TYPE_BOOL, CPL_FALSE},
1220 {KEY_FLUXCAL, KEY_FLUXCAL_COMMENT, CPL_TYPE_STRING, CPL_FALSE},
1221 {KEY_FLUXERR, KEY_FLUXERR_COMMENT, CPL_TYPE_DOUBLE, CPL_FALSE},
1222 {KEY_GAIN, KEY_GAIN_COMMENT, CPL_TYPE_DOUBLE, CPL_FALSE},
1223 {KEY_INHERIT, KEY_INHERIT_COMMENT, CPL_TYPE_BOOL, CPL_FALSE},
1224 {KEY_LAMNLIN, KEY_LAMNLIN_COMMENT, CPL_TYPE_INT, CPL_FALSE},
1225 {KEY_LAMRMS, KEY_LAMRMS_COMMENT, CPL_TYPE_DOUBLE, CPL_FALSE},
1226 {KEY_MJDEND, KEY_MJDEND_COMMENT, CPL_TYPE_DOUBLE, CPL_FALSE},
1227 {KEY_MJDOBS, KEY_MJDOBS_COMMENT, CPL_TYPE_DOUBLE, CPL_FALSE},
1228 {KEY_M_EPOCH, KEY_M_EPOCH_COMMENT, CPL_TYPE_BOOL, CPL_FALSE},
1229 {KEY_NCOMBINE, KEY_NCOMBINE_COMMENT, CPL_TYPE_INT, CPL_FALSE},
1230 {KEY_NELEM, KEY_NELEM_COMMENT, IRPLIB_TYPE_NELEM, CPL_FALSE},
1231 {KEY_OBID, KEY_OBID_COMMENT, CPL_TYPE_INT, CPL_TRUE},
1232 {KEY_OBJECT, KEY_OBJECT_COMMENT, CPL_TYPE_STRING, CPL_FALSE},
1233 {KEY_OBSTECH, KEY_OBSTECH_COMMENT, CPL_TYPE_STRING, CPL_FALSE},
1234 {KEY_ORIGIN, KEY_ORIGIN_COMMENT, CPL_TYPE_STRING, CPL_FALSE},
1235 {KEY_PROCSOFT, KEY_PROCSOFT_COMMENT, CPL_TYPE_STRING, CPL_FALSE},
1236 {KEY_PRODCATG, KEY_PRODCATG_COMMENT, CPL_TYPE_STRING, CPL_FALSE},
1237 {KEY_PRODLVL, KEY_PRODLVL_COMMENT, CPL_TYPE_INT, CPL_FALSE},
1238 {KEY_PROG_ID, KEY_PROG_ID_COMMENT, CPL_TYPE_STRING, CPL_FALSE},
1239 {KEY_PROV, KEY_PROV_COMMENT, CPL_TYPE_STRING, CPL_TRUE},
1240 {KEY_RA, KEY_RA_COMMENT, CPL_TYPE_DOUBLE, CPL_FALSE},
1241 {KEY_REFERENC, KEY_REFERENC_COMMENT, CPL_TYPE_STRING, CPL_FALSE},
1242 {KEY_SNR, KEY_SNR_COMMENT, CPL_TYPE_DOUBLE, CPL_FALSE},
1243 {KEY_SPECSYS, KEY_SPECSYS_COMMENT, CPL_TYPE_DOUBLE, CPL_FALSE},
1244 {KEY_SPEC_BIN, KEY_SPEC_BIN_COMMENT, CPL_TYPE_DOUBLE, CPL_FALSE},
1245 {KEY_SPEC_BW, KEY_SPEC_BW_COMMENT, CPL_TYPE_DOUBLE, CPL_FALSE},
1246 {KEY_SPEC_ERR, KEY_SPEC_ERR_COMMENT, CPL_TYPE_DOUBLE, CPL_FALSE},
1247 {KEY_SPEC_RES, KEY_SPEC_RES_COMMENT, CPL_TYPE_DOUBLE, CPL_FALSE},
1248 {KEY_SPEC_SYE, KEY_SPEC_SYE_COMMENT, CPL_TYPE_DOUBLE, CPL_FALSE},
1249 {KEY_SPEC_VAL, KEY_SPEC_VAL_COMMENT, CPL_TYPE_DOUBLE, CPL_FALSE},
1250 {KEY_TCOMM, KEY_TCOMM_COMMENT, CPL_TYPE_STRING, CPL_TRUE},
1251 {KEY_TDMAX(1), KEY_TDMAX1_COMMENT, CPL_TYPE_DOUBLE, CPL_FALSE},
1252 {KEY_TDMIN(1), KEY_TDMIN1_COMMENT, CPL_TYPE_DOUBLE, CPL_FALSE},
1253 {KEY_TELAPSE, KEY_TELAPSE_COMMENT, CPL_TYPE_DOUBLE, CPL_FALSE},
1254 {KEY_TEXPTIME, KEY_TEXPTIME_COMMENT, CPL_TYPE_DOUBLE, CPL_FALSE},
1255 {KEY_TIMESYS, KEY_TIMESYS_COMMENT, CPL_TYPE_STRING, CPL_FALSE},
1256 {KEY_TITLE, KEY_TITLE_COMMENT, CPL_TYPE_STRING, CPL_FALSE},
1257 {KEY_TMID, KEY_TMID_COMMENT, CPL_TYPE_DOUBLE, CPL_FALSE},
1258 {KEY_TOT_FLUX, KEY_TOT_FLUX_COMMENT, CPL_TYPE_BOOL, CPL_FALSE},
1259 {KEY_TUCD, KEY_TUCD_COMMENT, CPL_TYPE_STRING, CPL_TRUE},
1260 {KEY_TUTYP, KEY_TUTYP_COMMENT, CPL_TYPE_STRING, CPL_TRUE},
1261 {KEY_VOCLASS, KEY_VOCLASS_COMMENT, CPL_TYPE_STRING, CPL_FALSE},
1262 {KEY_VOPUB, KEY_VOPUB_COMMENT, CPL_TYPE_STRING, CPL_FALSE},
1263 {KEY_WAVELMAX, KEY_WAVELMAX_COMMENT, CPL_TYPE_DOUBLE, CPL_FALSE},
1264 {KEY_WAVELMIN, KEY_WAVELMIN_COMMENT, CPL_TYPE_DOUBLE, CPL_FALSE}
1267 static const size_t tablesize =
1268 sizeof(keyword_table) /
sizeof(irplib_keyword_record);
1270 size_t high = tablesize-1;
1271 const irplib_keyword_record *record = NULL;
1273 assert(_irplib_keyword_table_is_sorted(keyword_table, tablesize));
1274 assert(name != NULL);
1282 size_t mid = (low + high) >> 1;
1283 size_t keylen = strlen(keyword_table[mid].name);
1284 int result = strncmp(name, keyword_table[mid].name, keylen);
1286 record = &keyword_table[mid];
1288 }
else if (result < 0) {
1296 if (low > high)
return NULL;
1300 assert(record != NULL);
1302 if (strlen(record->name) != strlen(name)) {
1303 if (! record->is_array_key)
return NULL;
1306 const char *c = name + strlen(record->name);
1307 while (*c !=
'\0') {
1308 if (! isdigit(*c))
return NULL;
1318 const cpl_propertylist *plist,
1321 const irplib_keyword_record *key;
1322 cpl_errorstate prestate = cpl_errorstate_get();
1323 cpl_boolean spectrum_has_keyword;
1325 cpl_ensure_code(
self != NULL && plist != NULL && name != NULL,
1326 CPL_ERROR_NULL_INPUT);
1328 assert(self->proplist != NULL);
1330 if (! cpl_propertylist_has(plist, name)) {
1331 return cpl_error_set_message(cpl_func, cpl_error_get_code(),
1332 "Could not set '%s' since the keyword was not found in the"
1333 " source list.", name);
1336 key = _irplib_sdp_spectrum_get_keyword_record(name);
1338 return cpl_error_set_message(cpl_func, CPL_ERROR_ILLEGAL_INPUT,
1339 "The keyword name '%s' is not valid for an SPD spectrum.",
1343 spectrum_has_keyword = cpl_propertylist_has(self->proplist, name);
1345 switch ((
int) key->type) {
1351 cpl_boolean value = cpl_propertylist_get_bool(plist, name);
1352 cpl_propertylist_update_bool(self->proplist, name, value);
1357 int value = cpl_propertylist_get_int(plist, name);
1358 cpl_propertylist_update_int(self->proplist, name, value);
1361 case CPL_TYPE_DOUBLE:
1363 double value = cpl_propertylist_get_double(plist, name);
1364 cpl_propertylist_update_double(self->proplist, name, value);
1367 case CPL_TYPE_STRING:
1369 const char *value = cpl_propertylist_get_string(plist, name);
1370 cpl_propertylist_update_string(self->proplist, name, value);
1373 case IRPLIB_TYPE_NELEM:
1376 spectrum_has_keyword = CPL_TRUE;
1377 cpl_size value = (cpl_size) cpl_propertylist_get_long_long(plist, name);
1378 if (cpl_errorstate_is_equal(prestate)) {
1379 irplib_sdp_spectrum_set_nelem(
self, value);
1384 return cpl_error_set_message(cpl_func, CPL_ERROR_INVALID_TYPE,
1385 "Cannot handle type '%s'.", cpl_type_get_name(key->type));
1388 if (! spectrum_has_keyword) {
1389 cpl_propertylist_set_comment(self->proplist, name, key->comment);
1392 if (! cpl_errorstate_is_equal(prestate)) {
1393 if (! spectrum_has_keyword) {
1396 prestate = cpl_errorstate_get();
1397 (void) cpl_propertylist_erase(self->proplist, name);
1398 cpl_errorstate_set(prestate);
1400 return cpl_error_set_message(cpl_func, cpl_error_get_code(),
1401 "Could not set '%s'. Likely the keyword from the source list"
1402 " has a different format or type.", name);
1405 return CPL_ERROR_NONE;
1410 const cpl_property *prop)
1413 const irplib_keyword_record *key;
1414 cpl_errorstate prestate = cpl_errorstate_get();
1415 cpl_boolean spectrum_has_keyword;
1417 cpl_ensure_code(
self != NULL, CPL_ERROR_NULL_INPUT);
1419 assert(self->proplist != NULL);
1421 name = cpl_property_get_name(prop);
1422 if (name == NULL)
return cpl_error_get_code();
1424 key = _irplib_sdp_spectrum_get_keyword_record(name);
1426 return cpl_error_set_message(cpl_func, CPL_ERROR_ILLEGAL_INPUT,
1427 "The keyword name '%s' is not valid for an SPD spectrum.",
1431 spectrum_has_keyword = cpl_propertylist_has(self->proplist, name);
1433 switch ((
int) key->type) {
1436 cpl_boolean value = cpl_property_get_bool(prop);
1437 cpl_propertylist_update_bool(self->proplist, name, value);
1442 int value = cpl_property_get_int(prop);
1443 cpl_propertylist_update_int(self->proplist, name, value);
1446 case CPL_TYPE_DOUBLE:
1448 double value = cpl_property_get_double(prop);
1449 cpl_propertylist_update_double(self->proplist, name, value);
1452 case CPL_TYPE_STRING:
1454 const char *value = cpl_property_get_string(prop);
1455 cpl_propertylist_update_string(self->proplist, name, value);
1458 case IRPLIB_TYPE_NELEM:
1461 spectrum_has_keyword = CPL_TRUE;
1462 cpl_size value = (cpl_size) cpl_property_get_long_long(prop);
1463 if (cpl_errorstate_is_equal(prestate)) {
1464 irplib_sdp_spectrum_set_nelem(
self, value);
1469 return cpl_error_set_message(cpl_func, CPL_ERROR_INVALID_TYPE,
1470 "Cannot handle type '%s'.", cpl_type_get_name(key->type));
1473 if (! spectrum_has_keyword) {
1474 cpl_propertylist_set_comment(self->proplist, name, key->comment);
1477 if (! cpl_errorstate_is_equal(prestate)) {
1478 if (! spectrum_has_keyword) {
1481 prestate = cpl_errorstate_get();
1482 (void) cpl_propertylist_erase(self->proplist, name);
1483 cpl_errorstate_set(prestate);
1485 return cpl_error_set_message(cpl_func, cpl_error_get_code(),
1486 "Could not set '%s'. Likely the source property has a"
1487 " different format or type.", name);
1490 return CPL_ERROR_NONE;
1494 cpl_error_code irplib_sdp_spectrum_copy_property_regexp(
1496 const cpl_propertylist *plist,
1500 cpl_propertylist *sublist = NULL;
1501 cpl_propertylist *origlist = NULL;
1502 cpl_errorstate prestate = cpl_errorstate_get();
1505 cpl_ensure_code(
self != NULL, CPL_ERROR_NULL_INPUT);
1507 assert(self->proplist != NULL);
1509 sublist = cpl_propertylist_new();
1510 origlist = cpl_propertylist_new();
1511 cpl_propertylist_copy_property_regexp(origlist, self->proplist, regexp,
1513 cpl_propertylist_copy_property_regexp(sublist, plist, regexp, invert);
1514 if (cpl_propertylist_has(sublist, KEY_NELEM)) {
1517 cpl_propertylist_erase(sublist, KEY_NELEM);
1518 cpl_propertylist_copy_property(sublist, plist, KEY_NELEM);
1520 if (! cpl_errorstate_is_equal(prestate))
goto cleanup;
1522 for (i = 0; i < cpl_propertylist_get_size(sublist); ++i) {
1523 const cpl_property *p = cpl_propertylist_get_const(sublist, i);
1524 const char *name = cpl_property_get_name(p);
1525 irplib_sdp_spectrum_copy_keyword(
self, sublist, name);
1526 if (! cpl_errorstate_is_equal(prestate))
goto cleanup;
1529 cpl_propertylist_delete(sublist);
1530 cpl_propertylist_delete(origlist);
1531 return CPL_ERROR_NONE;
1536 prestate = cpl_errorstate_get();
1537 (void) cpl_propertylist_copy_property_regexp(self->proplist, origlist,
1539 cpl_errorstate_set(prestate);
1540 cpl_propertylist_delete(sublist);
1541 cpl_propertylist_delete(origlist);
1542 return cpl_error_get_code();
1546 GET_SET_METHODS_TYPE_DOUBLE(ra, KEY_RA, KEY_RA_COMMENT)
1547 GET_SET_METHODS_TYPE_DOUBLE(dec, KEY_DEC, KEY_DEC_COMMENT)
1548 GET_SET_METHODS_TYPE_DOUBLE(exptime, KEY_EXPTIME, KEY_EXPTIME_COMMENT)
1549 GET_SET_METHODS_TYPE_DOUBLE(texptime, KEY_TEXPTIME, KEY_TEXPTIME_COMMENT)
1550 GET_SET_METHODS_TYPE_STRING(timesys, KEY_TIMESYS, KEY_TIMESYS_COMMENT)
1551 GET_SET_METHODS_TYPE_DOUBLE(mjdobs, KEY_MJDOBS, KEY_MJDOBS_COMMENT)
1552 GET_SET_METHODS_TYPE_DOUBLE(mjdend, KEY_MJDEND, KEY_MJDEND_COMMENT)
1553 GET_SET_METHODS_TYPE_INT(prodlvl, KEY_PRODLVL, KEY_PRODLVL_COMMENT)
1554 GET_SET_METHODS_TYPE_STRING(procsoft, KEY_PROCSOFT, KEY_PROCSOFT_COMMENT)
1555 GET_SET_METHODS_TYPE_STRING(prodcatg, KEY_PRODCATG, KEY_PRODCATG_COMMENT)
1556 GET_SET_METHODS_TYPE_STRING(origin, KEY_ORIGIN, KEY_ORIGIN_COMMENT)
1557 GET_SET_METHODS_TYPE_BOOL(extobj, KEY_EXT_OBJ, KEY_EXT_OBJ_COMMENT)
1558 GET_SET_METHODS_TYPE_STRING(dispelem, KEY_DISPELEM, KEY_DISPELEM_COMMENT)
1559 GET_SET_METHODS_TYPE_STRING(specsys, KEY_SPECSYS, KEY_SPECSYS_COMMENT)
1560 GET_SET_METHODS_TYPE_STRING(progid, KEY_PROG_ID, KEY_PROG_ID_COMMENT)
1561 GET_SET_ARRAY_METHODS_TYPE_INT(obid, KEY_OBID, KEY_OBID_COMMENT)
1562 GET_SET_METHODS_TYPE_BOOL(mepoch, KEY_M_EPOCH, KEY_M_EPOCH_COMMENT)
1563 GET_SET_METHODS_TYPE_STRING(obstech, KEY_OBSTECH, KEY_OBSTECH_COMMENT)
1564 GET_SET_METHODS_TYPE_STRING(fluxcal, KEY_FLUXCAL, KEY_FLUXCAL_COMMENT)
1565 GET_SET_METHODS_TYPE_BOOL(contnorm, KEY_CONTNORM, KEY_CONTNORM_COMMENT)
1566 GET_SET_METHODS_TYPE_DOUBLE(wavelmin, KEY_WAVELMIN, KEY_WAVELMIN_COMMENT)
1567 GET_SET_METHODS_TYPE_DOUBLE(wavelmax, KEY_WAVELMAX, KEY_WAVELMAX_COMMENT)
1568 GET_SET_METHODS_TYPE_DOUBLE(specbin, KEY_SPEC_BIN, KEY_SPEC_BIN_COMMENT)
1569 GET_SET_METHODS_TYPE_BOOL(totflux, KEY_TOT_FLUX, KEY_TOT_FLUX_COMMENT)
1570 GET_SET_METHODS_TYPE_DOUBLE(fluxerr, KEY_FLUXERR, KEY_FLUXERR_COMMENT)
1571 GET_SET_METHODS_TYPE_STRING(referenc, KEY_REFERENC, KEY_REFERENC_COMMENT)
1572 GET_SET_METHODS_TYPE_DOUBLE(specres, KEY_SPEC_RES, KEY_SPEC_RES_COMMENT)
1573 GET_SET_METHODS_TYPE_DOUBLE(specerr, KEY_SPEC_ERR, KEY_SPEC_ERR_COMMENT)
1574 GET_SET_METHODS_TYPE_DOUBLE(specsye, KEY_SPEC_SYE, KEY_SPEC_SYE_COMMENT)
1575 GET_SET_METHODS_TYPE_INT(lamnlin, KEY_LAMNLIN, KEY_LAMNLIN_COMMENT)
1576 GET_SET_METHODS_TYPE_DOUBLE(lamrms, KEY_LAMRMS, KEY_LAMRMS_COMMENT)
1577 GET_SET_METHODS_TYPE_DOUBLE(gain, KEY_GAIN, KEY_GAIN_COMMENT)
1578 GET_SET_METHODS_TYPE_DOUBLE(detron, KEY_DETRON, KEY_DETRON_COMMENT)
1579 GET_SET_METHODS_TYPE_DOUBLE(effron, KEY_EFFRON, KEY_EFFRON_COMMENT)
1580 GET_SET_METHODS_TYPE_DOUBLE(snr, KEY_SNR, KEY_SNR_COMMENT)
1581 GET_SET_METHODS_TYPE_INT(ncombine, KEY_NCOMBINE, KEY_NCOMBINE_COMMENT)
1582 GET_SET_ARRAY_METHODS_TYPE_STRING(prov, KEY_PROV, KEY_PROV_COMMENT)
1583 GET_SET_ARRAY_METHODS_TYPE_STRING(asson, KEY_ASSON, KEY_ASSON_COMMENT)
1584 GET_SET_ARRAY_METHODS_TYPE_STRING(assoc, KEY_ASSOC, KEY_ASSOC_COMMENT)
1585 GET_SET_ARRAY_METHODS_TYPE_STRING(assom, KEY_ASSOM, KEY_ASSOM_COMMENT)
1586 GET_SET_METHODS_TYPE_STRING(voclass, KEY_VOCLASS, KEY_VOCLASS_COMMENT)
1587 GET_SET_METHODS_TYPE_STRING(vopub, KEY_VOPUB, KEY_VOPUB_COMMENT)
1588 GET_SET_METHODS_TYPE_STRING(title, KEY_TITLE, KEY_TITLE_COMMENT)
1589 GET_SET_METHODS_TYPE_STRING(
object, KEY_OBJECT, KEY_OBJECT_COMMENT)
1590 GET_SET_METHODS_TYPE_DOUBLE(aperture, KEY_APERTURE, KEY_APERTURE_COMMENT)
1591 GET_SET_METHODS_TYPE_DOUBLE(telapse, KEY_TELAPSE, KEY_TELAPSE_COMMENT)
1592 GET_SET_METHODS_TYPE_DOUBLE(tmid, KEY_TMID, KEY_TMID_COMMENT)
1593 GET_SET_METHODS_TYPE_DOUBLE(specval, KEY_SPEC_VAL, KEY_SPEC_VAL_COMMENT)
1594 GET_SET_METHODS_TYPE_DOUBLE(specbw, KEY_SPEC_BW, KEY_SPEC_BW_COMMENT)
1595 GET_SET_METHODS_TYPE_STRING(extname, KEY_EXTNAME, KEY_EXTNAME_COMMENT)
1596 GET_SET_METHODS_TYPE_BOOL(inherit, KEY_INHERIT, KEY_INHERIT_COMMENT)
1597 GET_SET_METHODS_TYPE_DOUBLE(tdmin, KEY_TDMIN(1), KEY_TDMIN1_COMMENT)
1598 GET_SET_METHODS_TYPE_DOUBLE(tdmax, KEY_TDMAX(1), KEY_TDMAX1_COMMENT)
1602 cpl_size firstindex,
1603 const cpl_frameset *frames)
1605 cpl_frameset_iterator* iter = NULL;
1606 cpl_propertylist* keywords = NULL;
1607 const cpl_frame* frame;
1608 cpl_size index = firstindex;
1611 assert(
self != NULL);
1612 assert(self->proplist != NULL);
1614 iter = cpl_frameset_iterator_new(frames);
1615 frame = cpl_frameset_iterator_get_const(iter);
1616 while (frame != NULL) {
1617 cpl_error_code error;
1618 const char* value = NULL;
1621 const char* filename = cpl_frame_get_filename(frame);
1622 cpl_error_ensure(filename != NULL, cpl_error_get_code(),
goto cleanup,
1623 "%s", cpl_error_get_message());
1624 keywords = cpl_propertylist_load(filename, 0);
1625 cpl_error_ensure(filename != NULL, cpl_error_get_code(),
goto cleanup,
1626 "Could not load keywords from primary HDU in '%s'.",
1631 if (cpl_propertylist_has(keywords, KEY_ARCFILE)) {
1632 value = cpl_propertylist_get_string(keywords, KEY_ARCFILE);
1633 cpl_error_ensure(value != NULL, cpl_error_get_code(),
goto cleanup,
1634 "Could not extract the '%s' keyword value from '%s'.",
1635 KEY_ARCFILE, filename);
1636 }
else if (cpl_propertylist_has(keywords, KEY_ORIGFILE)) {
1637 value = cpl_propertylist_get_string(keywords, KEY_ORIGFILE);
1638 cpl_error_ensure(value != NULL, cpl_error_get_code(),
goto cleanup,
1639 "Could not extract the '%s' keyword value from '%s'.",
1640 KEY_ORIGFILE, filename);
1646 error = irplib_sdp_spectrum_set_prov(
self, index, value);
1647 cpl_error_ensure(! error, error,
goto cleanup,
1648 "%s", cpl_error_get_message());
1649 cpl_propertylist_delete(keywords);
1653 cpl_errorstate status = cpl_errorstate_get();
1654 cpl_frameset_iterator_advance(iter, 1);
1655 if (cpl_error_get_code() == CPL_ERROR_ACCESS_OUT_OF_RANGE) {
1656 cpl_errorstate_set(status);
1658 frame = cpl_frameset_iterator_get_const(iter);
1662 cpl_frameset_iterator_delete(iter);
1663 return CPL_ERROR_NONE;
1667 cpl_frameset_iterator_delete(iter);
1668 cpl_propertylist_delete(keywords);
1669 return cpl_error_get_code();
1675 cpl_ensure(
self != NULL, CPL_ERROR_NULL_INPUT, 0);
1682 return irplib_sdp_spectrum_set_nelem(
self, 0);
1690 cpl_error_code error = CPL_ERROR_NONE;
1692 cpl_ensure(
self != NULL, CPL_ERROR_NULL_INPUT, 0);
1694 assert(self->table != NULL);
1696 ncol = cpl_table_get_ncol(self->table);
1700 cpl_array *names = cpl_table_get_column_names(self->table);
1701 for (i = 0; i < ncol; ++i) {
1702 const char *name = cpl_array_get_string(names, i);
1703 error = cpl_table_set_column_depth(self->table, name, value);
1708 cpl_errorstate prestate = cpl_errorstate_get();
1709 for (j = 0; j < i; ++j) {
1710 (void) cpl_table_set_column_depth(self->table, name, self->nelem);
1712 cpl_errorstate_set(prestate);
1716 cpl_array_delete(names);
1719 self->nelem = value;
1726 const cpl_propertylist *plist,
1730 cpl_ensure_code(
self != NULL, CPL_ERROR_NULL_INPUT);
1732 assert(self->proplist != NULL);
1734 if (cpl_propertylist_has(plist, name)) {
1735 cpl_errorstate prestate = cpl_errorstate_get();
1736 cpl_size value = (cpl_size) cpl_propertylist_get_long_long(plist, name);
1737 if (cpl_errorstate_is_equal(prestate)) {
1738 return irplib_sdp_spectrum_set_nelem(
self, value);
1740 return cpl_error_set_message(cpl_func, cpl_error_get_code(),
1741 "Could not set '%s'. Likely the source '%s' keyword has a"
1742 " different format or type.", KEY_NELEM, name);
1745 return cpl_error_set_message(cpl_func, CPL_ERROR_DATA_NOT_FOUND,
1746 "Could not set '%s' since the '%s' keyword was not found.",
1754 cpl_ensure(
self != NULL, CPL_ERROR_NULL_INPUT, 0);
1755 assert(self->table != NULL);
1756 return cpl_table_get_ncol(self->table);
1763 cpl_ensure(
self != NULL, CPL_ERROR_NULL_INPUT, 0);
1764 assert(self->table != NULL);
1765 return cpl_table_has_column(self->table, name);
1772 cpl_ensure(
self != NULL, CPL_ERROR_NULL_INPUT, NULL);
1773 assert(self->table != NULL);
1774 return cpl_table_get_column_names(self->table);
1782 cpl_error_code error;
1783 cpl_ensure_code(
self != NULL, CPL_ERROR_NULL_INPUT);
1784 assert(self->table != NULL);
1785 error = cpl_table_new_column_array(self->table, name, type, self->nelem);
1787 cpl_error_set_message(cpl_func, cpl_error_get_code(),
1788 "Failed to create a new column called '%s'.", name);
1796 cpl_type type,
const char *unit,
1797 const char *format,
const char *tutyp,
1798 const char *tucd,
const cpl_array *data)
1800 cpl_error_code error;
1803 cpl_ensure_code(
self != NULL, CPL_ERROR_NULL_INPUT);
1805 assert(self->table != NULL);
1809 error = cpl_table_new_column_array(self->table, name, type, self->nelem);
1810 if (unit != NULL && *unit !=
'\0') {
1811 error |= cpl_table_set_column_unit(self->table, name, unit);
1813 error |= cpl_table_set_column_unit(self->table, name,
" ");
1815 if (format != NULL) {
1816 error |= cpl_table_set_column_format(self->table, name, format);
1818 if (tutyp != NULL) {
1819 error |= irplib_sdp_spectrum_set_column_tutyp(
self, name, tutyp);
1821 error |= irplib_sdp_spectrum_set_column_tutyp(
self, name,
"");
1824 error |= irplib_sdp_spectrum_set_column_tucd(
self, name, tucd);
1826 error |= irplib_sdp_spectrum_set_column_tucd(
self, name,
"");
1833 error = cpl_table_set_array(self->table, name, 0, data);
1835 cpl_array *array = cpl_array_new(self->nelem, type);
1836 if (array != NULL) {
1837 error = cpl_table_set_array(self->table, name, 0, array);
1838 cpl_array_delete(array);
1840 error = cpl_error_get_code();
1850 cpl_errorstate prestate = cpl_errorstate_get();
1851 _irplib_sdp_spectrum_erase_column_keywords(
self, name);
1852 (void) cpl_table_erase_column(self->table, name);
1853 cpl_errorstate_set(prestate);
1854 error = cpl_error_set_message(cpl_func, cpl_error_get_code(),
1855 "Failed to create a new column called '%s'.", name);
1865 cpl_errorstate prestate = cpl_errorstate_get();
1866 cpl_error_code error = CPL_ERROR_NONE;
1868 cpl_ensure_code(
self != NULL && name != NULL, CPL_ERROR_NULL_INPUT);
1870 assert(self->table != NULL);
1872 _irplib_sdp_spectrum_erase_column_keywords(
self, name);
1873 if (! cpl_errorstate_is_equal(prestate)) {
1874 error |= cpl_error_get_code();
1876 error |= cpl_table_erase_column(self->table, name);
1878 return cpl_error_get_code();
1880 return CPL_ERROR_NONE;
1885 static cpl_error_code
1887 const cpl_table* table,
const char *from_name)
1889 cpl_error_code error;
1891 assert(
self != NULL);
1892 assert(self->table != NULL);
1894 error = cpl_table_duplicate_column(self->table, to_name, table, from_name);
1895 if (error)
return error;
1896 error |= irplib_sdp_spectrum_set_column_tutyp(
self, to_name,
"");
1897 error |= irplib_sdp_spectrum_set_column_tucd(
self, to_name,
"");
1900 cpl_errorstate prestate = cpl_errorstate_get();
1901 _irplib_sdp_spectrum_erase_column_keywords(
self, to_name);
1902 (void) cpl_table_erase_column(self->table, to_name);
1903 cpl_errorstate_set(prestate);
1904 return cpl_error_get_code();
1906 return CPL_ERROR_NONE;
1912 const cpl_table* table,
const char *name)
1916 cpl_ensure_code(
self != NULL, CPL_ERROR_NULL_INPUT);
1917 return _irplib_sdp_spectrum_copy_column(
self, name, table, name);
1923 const cpl_table* table,
1924 const char *regexp,
int invert)
1927 cpl_array *names = NULL;
1932 cpl_ensure_code(
self != NULL && regexp != NULL, CPL_ERROR_NULL_INPUT);
1934 assert(self->table != NULL);
1936 reg_error_code = regcomp(&re, regexp, REG_EXTENDED | REG_NOSUB);
1937 if (reg_error_code != 0) {
1938 return cpl_error_set_regex(CPL_ERROR_ILLEGAL_INPUT, reg_error_code, &re,
1939 "regexp='%s', invert=%d", regexp, invert);
1944 names = cpl_table_get_column_names(table);
1945 n = cpl_array_get_size(names);
1946 for (i = 0; i < n; ++i) {
1948 const char *namei = cpl_array_get_string(names, i);
1949 cpl_error_ensure(! cpl_table_has_column(self->table, namei),
1950 CPL_ERROR_ILLEGAL_OUTPUT,
goto cleanup,
1951 "The column '%s' already exists in the spectrum.", namei);
1952 match = (regexec(&re, namei, 0, NULL, 0) == 0);
1953 if ((! match && ! invert) || (match && invert)) {
1954 cpl_array_set_invalid(names, i);
1958 for (i = 0; i < n; ++i) {
1959 if (cpl_array_is_valid(names, i)) {
1960 const char *namei = cpl_array_get_string(names, i);
1961 cpl_error_code error = _irplib_sdp_spectrum_copy_column(
self, namei,
1964 cpl_errorstate prestate;
1966 cpl_error_set_message(cpl_func, error,
"Could not copy column '%s'.",
1970 prestate = cpl_errorstate_get();
1971 for (j = 0; j < i; ++j) {
1972 namei = cpl_array_get_string(names, i);
1973 _irplib_sdp_spectrum_erase_column_keywords(
self, namei);
1974 (void) cpl_table_erase_column(self->table, namei);
1976 cpl_errorstate_set(prestate);
1981 cpl_array_delete(names);
1983 return CPL_ERROR_NONE;
1987 cpl_array_delete(names);
1989 return cpl_error_get_code();
1995 const cpl_table* table,
const char *colname,
1998 char *orig_unit = NULL;
1999 char *orig_format = NULL;
2000 cpl_errorstate prestate = cpl_errorstate_get();
2004 cpl_ensure_code(
self != NULL && table != NULL, CPL_ERROR_NULL_INPUT);
2006 assert(self->table != NULL);
2008 if (! cpl_table_has_column(self->table, name)) {
2010 return _irplib_sdp_spectrum_copy_column(
self, name, table, colname);
2014 if (! cpl_table_has_column(table, colname)) {
2015 return cpl_error_set_message(cpl_func, CPL_ERROR_DATA_NOT_FOUND,
2016 "Column '%s' not found in table.", colname);
2021 if (flags & IRPLIB_COLUMN_UNIT) {
2022 const char* unit = cpl_table_get_column_unit(table, colname);
2025 if (unit != NULL && *unit ==
'\0') {
2028 orig_unit = cpl_strdup(cpl_table_get_column_unit(self->table, name));
2029 cpl_table_set_column_unit(self->table, name, unit);
2030 if (! cpl_errorstate_is_equal(prestate))
goto cleanup;
2032 if (flags & IRPLIB_COLUMN_FORMAT) {
2033 orig_format = cpl_strdup(cpl_table_get_column_format(self->table, name));
2034 cpl_table_set_column_format(self->table, name,
2035 cpl_table_get_column_format(table, colname));
2036 if (! cpl_errorstate_is_equal(prestate))
goto cleanup;
2042 if (flags & IRPLIB_COLUMN_DATA) {
2043 if (cpl_table_get_column_type(self->table, name) !=
2044 cpl_table_get_column_type(table, colname)) {
2045 cpl_error_set_message(cpl_func, CPL_ERROR_INCOMPATIBLE_INPUT,
2046 "The table column '%s' and spectrum column '%s' do not"
2047 " have the same types.", colname, name);
2050 if (cpl_table_get_column_depth(self->table, name) !=
2051 cpl_table_get_column_depth(table, colname)) {
2052 cpl_error_set_message(cpl_func, CPL_ERROR_INCOMPATIBLE_INPUT,
2053 "The table column '%s' and spectrum column '%s' do not"
2054 " have the same dimensions.", colname, name);
2057 const cpl_array* data = cpl_table_get_array(table, colname, 0);
2058 if (data == NULL)
goto cleanup;
2059 cpl_table_set_array(self->table, name, 0, data);
2060 if (! cpl_errorstate_is_equal(prestate))
goto cleanup;
2063 cpl_free(orig_unit);
2064 cpl_free(orig_format);
2065 return CPL_ERROR_NONE;
2069 prestate = cpl_errorstate_get();
2070 if (orig_unit != NULL) {
2071 (void) cpl_table_set_column_unit(self->table, name, orig_unit);
2072 cpl_free(orig_unit);
2074 if (orig_format != NULL) {
2075 (void) cpl_table_set_column_format(self->table, name, orig_format);
2076 cpl_free(orig_format);
2078 cpl_errorstate_set(prestate);
2079 return cpl_error_get_code();
2086 cpl_ensure(
self != NULL, CPL_ERROR_NULL_INPUT, CPL_TYPE_INVALID);
2087 assert(self->table != NULL);
2088 return cpl_table_get_column_type(self->table, name);
2096 cpl_ensure(
self != NULL, CPL_ERROR_NULL_INPUT, NULL);
2097 assert(self->table != NULL);
2098 return cpl_table_get_column_unit(self->table, name);
2119 const char *name,
const char *unit)
2121 cpl_ensure_code(
self != NULL, CPL_ERROR_NULL_INPUT);
2122 assert(self->table != NULL);
2125 if (unit != NULL && *unit ==
'\0') {
2128 return cpl_table_set_column_unit(self->table, name, unit);
2135 const cpl_propertylist *plist,
2138 cpl_ensure_code(
self != NULL, CPL_ERROR_NULL_INPUT);
2140 assert(self->table != NULL);
2142 if (cpl_propertylist_has(plist, key)) {
2143 cpl_errorstate prestate = cpl_errorstate_get();
2144 const char *value = cpl_propertylist_get_string(plist, key);
2145 if (cpl_errorstate_is_equal(prestate)) {
2148 if (value != NULL && *value ==
'\0') {
2151 return cpl_table_set_column_unit(self->table, name, value);
2153 return cpl_error_set_message(cpl_func, cpl_error_get_code(),
2154 "Could not set the unit for column '%s'. Likely the source '%s'"
2155 " keyword is not a string.", name, key);
2158 return cpl_error_set_message(cpl_func, CPL_ERROR_DATA_NOT_FOUND,
2159 "Could not set the unit for column '%s' since the '%s' keyword"
2160 " was not found.", name, key);
2169 cpl_ensure(
self != NULL, CPL_ERROR_NULL_INPUT, NULL);
2170 assert(self->table != NULL);
2171 return cpl_table_get_column_format(self->table, name);
2177 const char *name,
const char *format)
2179 cpl_ensure_code(
self != NULL, CPL_ERROR_NULL_INPUT);
2180 assert(self->table != NULL);
2181 return cpl_table_set_column_format(self->table, name, format);
2192 assert(
self != NULL);
2193 assert(self->table != NULL);
2194 assert(name != NULL);
2197 names = cpl_table_get_column_names(self->table);
2198 n = cpl_array_get_size(names);
2199 for (i = 0; i < n; ++i) {
2200 const char *namei = cpl_array_get_string(names, i);
2201 if (strcmp(namei, name) == 0) {
2202 cpl_array_delete(names);
2206 cpl_array_delete(names);
2207 return (cpl_size)-1;
2213 const char *name,
const char *keyword)
2216 const char *result = NULL;
2218 assert(
self != NULL);
2219 assert(self->proplist != NULL);
2220 assert(name != NULL);
2221 assert(keyword != NULL);
2223 index = _irplib_sdp_spectrum_get_column_index(
self, name);
2224 if (index != (cpl_size)-1) {
2226 char *propname = cpl_sprintf(
"%s%"CPL_SIZE_FORMAT, keyword, index+1);
2227 if (cpl_propertylist_has(self->proplist, propname)) {
2228 result = cpl_propertylist_get_string(self->proplist, propname);
2232 cpl_error_set_message(cpl_func, CPL_ERROR_DATA_NOT_FOUND,
2233 "Could not find '%s' keyword for column '%s'.", keyword, name);
2239 static cpl_error_code
2243 const char *keyword,
2244 const char *comment)
2247 char *propname, *pcomment;
2249 assert(
self != NULL);
2250 assert(self->proplist != NULL);
2251 assert(name != NULL);
2252 assert(keyword != NULL);
2253 assert(comment != NULL);
2255 index = _irplib_sdp_spectrum_get_column_index(
self, name);
2257 if (index == (cpl_size)-1) {
2258 return cpl_error_set_message(cpl_func, CPL_ERROR_DATA_NOT_FOUND,
2259 "Could not find '%s' keyword for column '%s'.", keyword, name);
2262 cpl_error_code error = CPL_ERROR_NONE;
2263 propname = cpl_sprintf(
"%s%"CPL_SIZE_FORMAT, keyword, index+1);
2264 pcomment = cpl_sprintf(
"%s%"CPL_SIZE_FORMAT, comment, index+1);
2265 if (cpl_propertylist_has(self->proplist, propname)) {
2266 if (value != NULL) {
2267 error = cpl_propertylist_set_string(self->proplist, propname, value);
2269 (void) cpl_propertylist_erase(self->proplist, propname);
2271 }
else if (value != NULL) {
2272 error = cpl_propertylist_append_string(self->proplist, propname, value);
2274 error = cpl_propertylist_set_comment(self->proplist, propname,
2279 cpl_errorstate prestate = cpl_errorstate_get();
2280 (void) cpl_propertylist_erase(self->proplist, propname);
2281 cpl_errorstate_set(prestate);
2297 assert(
self != NULL);
2298 assert(self->proplist != NULL);
2299 assert(name != NULL);
2301 index = _irplib_sdp_spectrum_get_column_index(
self, name);
2302 if (index != (cpl_size)-1) {
2303 char *propname = cpl_sprintf(
"%s%"CPL_SIZE_FORMAT, KEY_TUTYP, index+1);
2304 cpl_propertylist_erase(self->proplist, propname);
2306 propname = cpl_sprintf(
"%s%"CPL_SIZE_FORMAT, KEY_TUCD, index+1);
2307 cpl_propertylist_erase(self->proplist, propname);
2309 propname = cpl_sprintf(
"%s%"CPL_SIZE_FORMAT, KEY_TCOMM, index+1);
2310 cpl_propertylist_erase(self->proplist, propname);
2320 cpl_errorstate prestate = cpl_errorstate_get();
2322 cpl_ensure(
self != NULL && name != NULL, CPL_ERROR_NULL_INPUT, NULL);
2323 result = _irplib_sdp_spectrum_get_column_keyword(
self, name, KEY_TUTYP);
2324 if (! cpl_errorstate_is_equal(prestate)) {
2325 cpl_error_set_where(cpl_func);
2333 const char *name,
const char *tutyp)
2335 cpl_error_code error;
2336 cpl_ensure_code(
self != NULL && name != NULL, CPL_ERROR_NULL_INPUT);
2337 error = _irplib_sdp_spectrum_set_column_keyword(
self, name, tutyp,
2338 KEY_TUTYP, KEY_TUTYP_COMMENT);
2340 cpl_error_set_where(cpl_func);
2349 const cpl_propertylist *plist,
2352 cpl_ensure_code(
self != NULL, CPL_ERROR_NULL_INPUT);
2354 assert(self->table != NULL);
2356 if (cpl_propertylist_has(plist, key)) {
2357 cpl_errorstate prestate = cpl_errorstate_get();
2358 const char *value = cpl_propertylist_get_string(plist, key);
2359 if (cpl_errorstate_is_equal(prestate)) {
2360 return irplib_sdp_spectrum_set_column_tutyp(
self, name, value);
2362 cpl_size index = _irplib_sdp_spectrum_get_column_index(
self, name) + 1;
2363 return cpl_error_set_message(cpl_func, cpl_error_get_code(),
2364 "Could not set '%s%"CPL_SIZE_FORMAT
"' for column '%s'. Likely"
2365 " the source '%s' keyword is not a string.",
2366 KEY_TUTYP, index, name, key);
2369 cpl_size index = _irplib_sdp_spectrum_get_column_index(
self, name) + 1;
2370 return cpl_error_set_message(cpl_func, CPL_ERROR_DATA_NOT_FOUND,
2371 "Could not set '%s%"CPL_SIZE_FORMAT
"' for column '%s' since the"
2372 " '%s' keyword was not found.", KEY_TUTYP, index, name, key);
2381 cpl_errorstate prestate = cpl_errorstate_get();
2383 cpl_ensure(
self != NULL && name != NULL, CPL_ERROR_NULL_INPUT, NULL);
2384 result = _irplib_sdp_spectrum_get_column_keyword(
self, name, KEY_TUCD);
2385 if (! cpl_errorstate_is_equal(prestate)) {
2386 cpl_error_set_where(cpl_func);
2394 const char *name,
const char *tucd)
2396 cpl_error_code error;
2397 cpl_ensure_code(
self != NULL && name != NULL, CPL_ERROR_NULL_INPUT);
2398 error = _irplib_sdp_spectrum_set_column_keyword(
self, name, tucd,
2399 KEY_TUCD, KEY_TUCD_COMMENT);
2401 cpl_error_set_where(cpl_func);
2410 const cpl_propertylist *plist,
2413 cpl_ensure_code(
self != NULL, CPL_ERROR_NULL_INPUT);
2415 assert(self->table != NULL);
2417 if (cpl_propertylist_has(plist, key)) {
2418 cpl_errorstate prestate = cpl_errorstate_get();
2419 const char *value = cpl_propertylist_get_string(plist, key);
2420 if (cpl_errorstate_is_equal(prestate)) {
2421 return irplib_sdp_spectrum_set_column_tucd(
self, name, value);
2423 cpl_size index = _irplib_sdp_spectrum_get_column_index(
self, name) + 1;
2424 return cpl_error_set_message(cpl_func, cpl_error_get_code(),
2425 "Could not set '%s%"CPL_SIZE_FORMAT
"' for column '%s'. Likely"
2426 " the source '%s' keyword is not a string.",
2427 KEY_TUCD, index, name, key);
2430 cpl_size index = _irplib_sdp_spectrum_get_column_index(
self, name) + 1;
2431 return cpl_error_set_message(cpl_func, CPL_ERROR_DATA_NOT_FOUND,
2432 "Could not set '%s%"CPL_SIZE_FORMAT
"' for column '%s' since the"
2433 " '%s' keyword was not found.", KEY_TUCD, index, name, key);
2442 cpl_errorstate prestate = cpl_errorstate_get();
2444 cpl_ensure(
self != NULL && name != NULL, CPL_ERROR_NULL_INPUT, NULL);
2445 result = _irplib_sdp_spectrum_get_column_keyword(
self, name, KEY_TCOMM);
2446 if (! cpl_errorstate_is_equal(prestate)) {
2447 cpl_error_set_where(cpl_func);
2455 const char *name,
const char *tcomm)
2457 cpl_error_code error;
2458 cpl_ensure_code(
self != NULL && name != NULL, CPL_ERROR_NULL_INPUT);
2459 error = _irplib_sdp_spectrum_set_column_keyword(
self, name, tcomm,
2460 KEY_TCOMM, KEY_TCOMM_COMMENT);
2462 cpl_error_set_where(cpl_func);
2471 const cpl_propertylist *plist,
2474 cpl_ensure_code(
self != NULL, CPL_ERROR_NULL_INPUT);
2476 assert(self->table != NULL);
2478 if (cpl_propertylist_has(plist, key)) {
2479 cpl_errorstate prestate = cpl_errorstate_get();
2480 const char *value = cpl_propertylist_get_string(plist, key);
2481 if (cpl_errorstate_is_equal(prestate)) {
2482 return irplib_sdp_spectrum_set_column_tcomm(
self, name, value);
2484 cpl_size index = _irplib_sdp_spectrum_get_column_index(
self, name) + 1;
2485 return cpl_error_set_message(cpl_func, cpl_error_get_code(),
2486 "Could not set '%s%"CPL_SIZE_FORMAT
"' for column '%s'. Likely"
2487 " the source '%s' keyword is not a string.",
2488 KEY_TCOMM, index, name, key);
2491 cpl_size index = _irplib_sdp_spectrum_get_column_index(
self, name) + 1;
2492 return cpl_error_set_message(cpl_func, CPL_ERROR_DATA_NOT_FOUND,
2493 "Could not set '%s%"CPL_SIZE_FORMAT
"' for column '%s' since the"
2494 " '%s' keyword was not found.", KEY_TCOMM, index, name, key);
2503 cpl_ensure(
self != NULL, CPL_ERROR_NULL_INPUT, NULL);
2504 assert(self->table != NULL);
2505 return cpl_table_get_array(self->table, name, 0);
2511 const char *name,
const cpl_array *array)
2513 cpl_ensure_code(
self != NULL, CPL_ERROR_NULL_INPUT);
2514 assert(self->table != NULL);
2515 return cpl_table_set_array(self->table, name, 0, array);
2519 static char * _irplib_make_regexp(
const cpl_propertylist *plist,
2524 static const cpl_size min_chars_required = 6;
2528 static const char *start_fragment =
"^(";
2529 static const char *end_fragment =
")$";
2530 static const char *join_fragment =
"|";
2532 cpl_size extra_length = (extra != NULL ? (cpl_size) strlen(extra) : 0);
2533 cpl_size regexp_size, bytesleft, nkeys, i;
2535 char *regexp = NULL;
2537 assert(plist != NULL);
2539 nkeys = cpl_propertylist_get_size(plist);
2542 if (extra != NULL) {
2543 return cpl_sprintf(
"%s%s%s", start_fragment, extra, end_fragment);
2545 return cpl_strdup(
"");
2550 regexp_size = nkeys * 80 + min_chars_required + extra_length;
2551 regexp = cpl_malloc(regexp_size);
2553 bytesleft = regexp_size;
2555 for (i = 0; i < nkeys; ++i) {
2556 cpl_size name_length, fragment_length;
2557 const char *name, *fragment;
2560 const cpl_property *p = cpl_propertylist_get_const(plist, i);
2561 cpl_error_ensure(p != NULL, cpl_error_get_code(),
goto cleanup,
2562 "Unexpected error accessing property structure %"CPL_SIZE_FORMAT
".", i);
2563 name = cpl_property_get_name(p);
2564 cpl_error_ensure(name != NULL, cpl_error_get_code(),
goto cleanup,
2565 "Unexpected error accessing the name of property %"CPL_SIZE_FORMAT
".", i);
2566 name_length = (cpl_size) strlen(name);
2569 fragment = (i == 0) ? start_fragment : join_fragment;
2570 fragment_length = (cpl_size) strlen(fragment);
2573 fragment_length + name_length + extra_length + min_chars_required)
2577 bytesleft += regexp_size;
2578 regexp_size += regexp_size;
2579 regexp = cpl_realloc(regexp, regexp_size);
2580 writepos = regexp + (regexp_size - bytesleft);
2584 strncpy(writepos, fragment, bytesleft);
2585 bytesleft -= fragment_length;
2586 writepos += fragment_length;
2587 strncpy(writepos, name, bytesleft);
2588 bytesleft -= name_length;
2589 writepos += name_length;
2593 if (extra != NULL) {
2594 strncpy(writepos, join_fragment, bytesleft);
2595 bytesleft -= (cpl_size) strlen(join_fragment);
2596 writepos += (cpl_size) strlen(join_fragment);
2597 strncpy(writepos, extra, bytesleft);
2598 bytesleft -= extra_length;
2599 writepos += extra_length;
2601 strncpy(writepos, end_fragment, bytesleft);
2603 regexp[regexp_size-1] =
'\0';
2616 cpl_error_code error;
2618 cpl_propertylist *plist = NULL;
2619 cpl_propertylist *tmpplist = NULL;
2620 cpl_table *table = NULL;
2621 cpl_array *names = NULL;
2622 cpl_array *emptyarray = NULL;
2623 cpl_size nelem, ext, i;
2624 char *regexp = NULL;
2626 cpl_ensure(filename != NULL, CPL_ERROR_NULL_INPUT, NULL);
2631 plist = cpl_propertylist_load_regexp(filename, 0, ALL_KEYS_REGEXP, 0);
2632 cpl_error_ensure(plist != NULL, cpl_error_get_code(),
goto cleanup,
2633 "Could not load property list from primary HDU when loading file '%s'.",
2638 regexp = _irplib_make_regexp(plist, NULL);
2639 cpl_error_ensure(regexp != NULL, cpl_error_get_code(),
goto cleanup,
2640 "Could not create regular expression to filter keywords.");
2644 ext = cpl_fits_find_extension(filename, KEY_EXTNAME_VALUE);
2645 cpl_error_ensure(ext != (cpl_size)-1, cpl_error_get_code(),
goto cleanup,
2646 "Failed to get the extension '%s' from file '%s'.",
2647 KEY_EXTNAME_VALUE, filename);
2648 if (ext == 0) ext = 1;
2651 tmpplist = cpl_propertylist_load_regexp(filename, ext, ALL_KEYS_REGEXP, 0);
2652 cpl_error_ensure(tmpplist != NULL, cpl_error_get_code(),
goto cleanup,
2653 "Could not load property list from extension %"
2654 CPL_SIZE_FORMAT
" when loading file '%s'.", ext, filename);
2657 error = cpl_propertylist_copy_property_regexp(plist, tmpplist, regexp, 1);
2658 cpl_error_ensure(! error, error,
goto cleanup,
2659 "Failed to append keywords from file '%s' extension %"
2660 CPL_SIZE_FORMAT
".", filename, ext);
2663 cpl_propertylist_delete(tmpplist);
2668 table = cpl_table_load(filename, (
int)ext, CPL_TRUE);
2669 cpl_error_ensure(table != NULL, cpl_error_get_code(),
goto cleanup,
2670 "Could not load the spectrum table from extension %"
2671 CPL_SIZE_FORMAT
" when loading file '%s'.", ext, filename);
2674 if (cpl_propertylist_has(plist, KEY_NELEM)) {
2675 cpl_errorstate prestate = cpl_errorstate_get();
2676 nelem = (cpl_size) cpl_propertylist_get_long_long(plist, KEY_NELEM);
2678 cpl_propertylist_erase(plist, KEY_NELEM);
2679 cpl_error_ensure(cpl_errorstate_is_equal(prestate), cpl_error_get_code(),
2680 goto cleanup,
"Could not process the temporary '%s' keyword.",
2683 cpl_msg_warning(cpl_func,
2684 "Keyword '%s' not found in file '%s'. Possibly corrupted."
2685 " Will try find correct value from the table and continue.",
2686 KEY_NELEM, filename);
2688 if (cpl_table_get_nrow(table) > 0) {
2689 names = cpl_table_get_column_names(table);
2690 if (names != NULL) {
2691 if (cpl_array_get_size(names) > 0) {
2692 const char *name = cpl_array_get_string(names, 0);
2693 nelem = cpl_table_get_column_depth(table, name);
2695 cpl_array_delete(names);
2701 names = cpl_table_get_column_names(table);
2702 cpl_error_ensure(names != NULL, cpl_error_get_code(),
goto cleanup,
2703 "Could not get table column names when loading file '%s'.", filename);
2704 for (i = 0; i < cpl_array_get_size(names); ++i) {
2706 const char *name = cpl_array_get_string(names, 0);
2707 cpl_type type = cpl_table_get_column_type(table, name);
2708 if ((type & CPL_TYPE_POINTER) == 0)
continue;
2709 for (j = 0; j < cpl_table_get_nrow(table); ++j) {
2710 if (cpl_table_get_array(table, name, j) != NULL)
continue;
2711 emptyarray = cpl_array_new(nelem, type & (~CPL_TYPE_POINTER));
2712 cpl_error_ensure(emptyarray != NULL, cpl_error_get_code(),
goto cleanup,
2713 "Could not create empty array when spectrum table from file '%s'.",
2715 error = cpl_table_set_array(table, name, j, emptyarray);
2716 cpl_array_delete(emptyarray);
2720 cpl_array_delete(names);
2725 obj->proplist = plist;
2733 cpl_propertylist_delete(plist);
2734 cpl_propertylist_delete(tmpplist);
2735 cpl_table_delete(table);
2736 cpl_array_delete(names);
2737 cpl_array_delete(emptyarray);
2744 const char *filename,
2745 const cpl_propertylist *extra_pheader,
2746 const cpl_propertylist *extra_theader)
2748 cpl_error_code error;
2749 cpl_propertylist *primarykeys = NULL;
2750 cpl_propertylist *tablekeys = NULL;
2751 char *regexp = NULL;
2753 cpl_ensure_code(
self != NULL, CPL_ERROR_NULL_INPUT);
2755 assert(self->proplist != NULL);
2756 assert(self->table != NULL);
2760 regexp = _irplib_make_regexp(self->proplist, KEY_NELEM);
2761 cpl_error_ensure(regexp != NULL, cpl_error_get_code(),
goto cleanup,
2762 "Could not create regular expression to filter keywords.");
2766 primarykeys = cpl_propertylist_new();
2767 error = cpl_propertylist_copy_property_regexp(primarykeys, self->proplist,
2768 PRIMARY_HDU_KEYS_REGEXP, 0);
2769 cpl_error_ensure(! error, error,
goto cleanup,
2770 "Failed to extract keywords for primary HDU.");
2774 if (cpl_propertylist_has(primarykeys, KEY_OBJECT)) {
2775 error = cpl_propertylist_set_comment(primarykeys, KEY_OBJECT,
2776 KEY_OBJECT_PHDU_COMMENT);
2777 cpl_error_ensure(! error, error,
goto cleanup,
2778 "Could not update comment for '%s' in primary HDU.", KEY_OBJECT);
2782 if (extra_pheader != NULL) {
2783 error = cpl_propertylist_copy_property_regexp(primarykeys, extra_pheader,
2785 cpl_error_ensure(! error, error,
goto cleanup,
2786 "Could not add extra keywords for primary HDU.");
2790 tablekeys = cpl_propertylist_new();
2791 error = cpl_propertylist_copy_property_regexp(tablekeys, self->proplist,
2792 EXTENSION_HDU_KEYS_REGEXP, 0);
2793 cpl_error_ensure(! error, error,
goto cleanup,
2794 "Failed to extract keywords for extension HDU.");
2797 cpl_error_ensure(self->nelem <= INT_MAX, CPL_ERROR_INCOMPATIBLE_INPUT,
2799 "The value for the keyword '%s' is too big (> %d).",
2800 KEY_NELEM, INT_MAX);
2801 error = cpl_propertylist_append_int(tablekeys, KEY_NELEM,
2803 error |= cpl_propertylist_set_comment(tablekeys, KEY_NELEM,
2805 cpl_error_ensure(! error, error,
goto cleanup,
2806 "Could not add keyword '%s' to primary HDU or set the comment.",
2810 if (extra_theader != NULL) {
2811 error = cpl_propertylist_copy_property_regexp(tablekeys, extra_theader,
2813 cpl_error_ensure(! error, error,
goto cleanup,
2814 "Could not add extra keywords for extension HDU.");
2823 error = CPL_ERROR_NONE;
2824 if (! cpl_propertylist_has(primarykeys, KEY_ORIGIN)) {
2825 error |= cpl_propertylist_append_string(primarykeys, KEY_ORIGIN,
2827 error |= cpl_propertylist_set_comment(primarykeys, KEY_ORIGIN,
2828 KEY_ORIGIN_COMMENT);
2830 if (! cpl_propertylist_has(primarykeys, KEY_PRODLVL)) {
2831 error |= cpl_propertylist_append_int(primarykeys, KEY_PRODLVL,
2833 error |= cpl_propertylist_set_comment(primarykeys, KEY_PRODLVL,
2834 KEY_PRODLVL_COMMENT);
2836 if (! cpl_propertylist_has(primarykeys, KEY_SPECSYS)) {
2837 error |= cpl_propertylist_append_string(primarykeys, KEY_SPECSYS,
2839 error |= cpl_propertylist_set_comment(primarykeys, KEY_SPECSYS,
2840 KEY_SPECSYS_COMMENT);
2842 if (! cpl_propertylist_has(primarykeys, KEY_FLUXERR)) {
2843 error |= cpl_propertylist_append_int(primarykeys, KEY_FLUXERR,
2845 error |= cpl_propertylist_set_comment(primarykeys, KEY_FLUXERR,
2846 KEY_FLUXERR_COMMENT);
2848 if (! cpl_propertylist_has(tablekeys, KEY_VOCLASS)) {
2849 error |= cpl_propertylist_append_string(tablekeys, KEY_VOCLASS,
2851 error |= cpl_propertylist_set_comment(tablekeys, KEY_VOCLASS,
2852 KEY_VOCLASS_COMMENT);
2854 if (! cpl_propertylist_has(tablekeys, KEY_VOPUB)) {
2855 error |= cpl_propertylist_append_string(tablekeys, KEY_VOPUB,
2857 error |= cpl_propertylist_set_comment(tablekeys, KEY_VOPUB,
2860 if (! cpl_propertylist_has(tablekeys, KEY_EXTNAME)) {
2861 error |= cpl_propertylist_append_string(tablekeys, KEY_EXTNAME,
2863 error |= cpl_propertylist_set_comment(tablekeys, KEY_EXTNAME,
2864 KEY_EXTNAME_COMMENT);
2866 if (! cpl_propertylist_has(tablekeys, KEY_INHERIT)) {
2867 error |= cpl_propertylist_append_bool(tablekeys, KEY_INHERIT,
2869 error |= cpl_propertylist_set_comment(tablekeys, KEY_INHERIT,
2870 KEY_INHERIT_COMMENT);
2872 cpl_error_ensure(! error, cpl_error_get_code(),
goto cleanup,
2873 "Could not set default header keywords for file '%s'.",
2876 error = cpl_table_save(self->table, primarykeys, tablekeys, filename,
2878 cpl_error_ensure(! error, error,
goto cleanup,
2879 "Could not save the spectrum table to file '%s'.", filename);
2881 cpl_propertylist_delete(primarykeys);
2882 cpl_propertylist_delete(tablekeys);
2884 return CPL_ERROR_NONE;
2889 cpl_propertylist_delete(primarykeys);
2890 cpl_propertylist_delete(tablekeys);
2892 return cpl_error_get_code();
2896 cpl_error_code irplib_dfs_save_spectrum(cpl_frameset * allframes,
2897 cpl_propertylist * header,
2898 const cpl_parameterlist * parlist,
2899 const cpl_frameset * usedframes,
2900 const cpl_frame * inherit,
2902 const char * recipe,
2903 const cpl_propertylist * applist,
2904 const cpl_propertylist * tablelist,
2905 const char * remregexp,
2906 const char * pipe_id,
2907 const char * dict_id,
2908 const char * filename)
2910 const char * procat;
2911 cpl_propertylist * plist = NULL;
2912 cpl_frame * product_frame = NULL;
2913 cpl_error_code error;
2915 cpl_ensure_code(allframes != NULL, CPL_ERROR_NULL_INPUT);
2916 cpl_ensure_code(parlist != NULL, CPL_ERROR_NULL_INPUT);
2917 cpl_ensure_code(usedframes != NULL, CPL_ERROR_NULL_INPUT);
2918 cpl_ensure_code(spectrum != NULL, CPL_ERROR_NULL_INPUT);
2919 cpl_ensure_code(recipe != NULL, CPL_ERROR_NULL_INPUT);
2920 cpl_ensure_code(applist != NULL, CPL_ERROR_NULL_INPUT);
2921 cpl_ensure_code(pipe_id != NULL, CPL_ERROR_NULL_INPUT);
2922 cpl_ensure_code(dict_id != NULL, CPL_ERROR_NULL_INPUT);
2923 cpl_ensure_code(filename != NULL, CPL_ERROR_NULL_INPUT);
2925 procat = cpl_propertylist_get_string(applist, CPL_DFS_PRO_CATG);
2926 cpl_error_ensure(procat != NULL, cpl_error_get_code(),
goto cleanup,
2927 "Could not find keyword '%s' in 'applist'.", CPL_DFS_PRO_CATG);
2930 product_frame = cpl_frame_new();
2931 error = cpl_frame_set_filename(product_frame, filename);
2932 error |= cpl_frame_set_tag(product_frame, procat);
2933 error |= cpl_frame_set_type(product_frame, CPL_FRAME_TYPE_TABLE);
2934 error |= cpl_frame_set_group(product_frame, CPL_FRAME_GROUP_PRODUCT);
2935 error |= cpl_frame_set_level(product_frame, CPL_FRAME_LEVEL_FINAL);
2936 cpl_error_ensure(! error, cpl_error_get_code(),
goto cleanup,
2937 "Failed to setup the product frame.");
2941 if (header != NULL) {
2942 cpl_propertylist_empty(header);
2945 plist = cpl_propertylist_new();
2949 error = cpl_propertylist_append(plist, applist);
2950 cpl_error_ensure(! error, error,
goto cleanup,
2951 "Could not append extra keywords when writing file '%s'.", filename);
2954 error = cpl_dfs_setup_product_header(plist, product_frame, usedframes,
2955 parlist, recipe, pipe_id, dict_id,
2957 cpl_error_ensure(! error, error,
goto cleanup,
2958 "Failed to setup DFS keywords when writing file '%s'.", filename);
2966 error = cpl_propertylist_copy_property_regexp(plist, applist,
".*", 0);
2967 cpl_error_ensure(! error, error,
goto cleanup,
2968 "Could not update extra keywords when writing file '%s'.", filename);
2970 if (remregexp != NULL) {
2971 cpl_errorstate prestate = cpl_errorstate_get();
2972 (void) cpl_propertylist_erase_regexp(plist, remregexp, 0);
2973 cpl_error_ensure(cpl_errorstate_is_equal(prestate), cpl_error_get_code(),
2975 "Failed to filter keywords when writing file '%s'.",
2979 error = irplib_sdp_spectrum_save(spectrum, filename, plist, tablelist);
2980 cpl_error_ensure(! error, error,
goto cleanup,
2981 "Failed to save SPD spectrum to file '%s'.", filename);
2984 if (header != NULL) {
2985 error = cpl_propertylist_copy_property_regexp(header, spectrum->proplist,
2987 cpl_error_ensure(! error, error,
goto cleanup,
2988 "Could not return SDP keywords in header output.");
2992 error = cpl_frameset_insert(allframes, product_frame);
2993 cpl_error_ensure(! error, error,
goto cleanup,
2994 "Failed to insert new product frame when writing file '%s'.", filename);
2997 if (plist != header) cpl_propertylist_delete(plist);
2999 return CPL_ERROR_NONE;
3004 if (header != NULL) {
3005 cpl_errorstate prestate = cpl_errorstate_get();
3006 (void) cpl_propertylist_empty(header);
3007 cpl_errorstate_set(prestate);
3009 cpl_propertylist_delete(plist);
3011 cpl_frame_delete(product_frame);
3012 return cpl_error_get_code();
3018 if (stream == NULL) {
3022 fprintf(stream,
"NULL SDP spectrum\n\n");
3026 assert(self->proplist != NULL);
3027 assert(self->table != NULL);
3029 fprintf(stream,
"SDP spectrum at address %p\n", (
void*)
self);
3030 fprintf(stream,
"NELEM = %"CPL_SIZE_FORMAT
"\n", self->nelem);
3031 cpl_propertylist_dump(self->proplist, stream);
3032 cpl_table_dump_structure(self->table, stream);
3033 cpl_table_dump(self->table, 0, cpl_table_get_nrow(self->table), stream);
3037 #ifdef IRPLIB_USE_FITS_UPDATE_CHECKSUM
3050 cpl_error_code irplib_fits_update_checksums(
const char* filename)
3052 fitsfile* filehandle;
3055 if (fits_open_diskfile(&filehandle, filename, READWRITE, &error)) {
3056 return cpl_error_set_message(cpl_func, CPL_ERROR_FILE_IO,
3057 "Could not open file '%s' to update CHECKSUM keywords"
3058 " (error = %d).", filename, error);
3062 while (! fits_movabs_hdu(filehandle, ++i, NULL, &error)) {
3063 if (fits_write_chksum(filehandle, &error)) {
3064 return cpl_error_set_message(cpl_func, CPL_ERROR_FILE_IO,
3065 "Could not update the CHECKSUM keywords in '%s' HDU %d"
3066 " (error = %d).", filename, i, error);
3070 if (error == END_OF_FILE) error = 0;
3072 if (fits_close_file(filehandle, &error)) {
3073 return cpl_error_set_message(cpl_func, CPL_ERROR_FILE_IO,
3074 "There was a problem trying to close the file '%s'"
3075 " (error = %d).", filename, error);
3077 return CPL_ERROR_NONE;
struct _irplib_sdp_spectrum_ irplib_sdp_spectrum
Data type for a Science Data Product 1D spectrum.