30#include "irplib_framelist.h"
31#include "irplib_utils.h"
46struct _irplib_framelist_ {
49 cpl_propertylist ** propertylist;
58static void irplib_framelist_set_size(irplib_framelist *)
59#if defined __GNUC__ && __GNUC__ >= 4
60 __attribute__((nonnull))
64static cpl_boolean irplib_property_equal(
const cpl_propertylist *,
65 const cpl_propertylist *,
66 const char *, cpl_type,
double,
68#if defined __GNUC__ && __GNUC__ >= 4
69 __attribute__((nonnull))
172 return (irplib_framelist *) cpl_calloc(1,
sizeof(irplib_framelist));
202 irplib_framelist * self;
205 cpl_ensure(frameset != NULL, CPL_ERROR_NULL_INPUT, NULL);
210 for (i = 0; i < cpl_frameset_get_size(frameset); i++)
212 const cpl_frame * frame = cpl_frameset_get_position_const(frameset, i);
214 cpl_frame * copy = cpl_frame_duplicate(frame);
217 const cpl_error_code error =
221 assert(error == CPL_ERROR_NONE);
225 assert(self->size == cpl_frameset_get_size(frameset));
247 cpl_ensure(self != NULL, CPL_ERROR_NULL_INPUT, NULL);
250 new = cpl_frameset_new();
252 for (i = 0; i < self->size; i++) {
253 cpl_frame * frame = cpl_frame_duplicate(self->frame[i]);
255 const cpl_error_code error =
257 cpl_frameset_insert(
new, frame);
259 assert(error == CPL_ERROR_NONE);
263 assert(self->size == cpl_frameset_get_size(
new));
287 irplib_framelist *
new;
291 cpl_ensure(self != NULL, CPL_ERROR_NULL_INPUT, NULL);
292 cpl_ensure(tag != NULL, CPL_ERROR_NULL_INPUT, NULL);
297 for (i = 0; i < self->size; i++) {
298 const cpl_frame * frame = self->frame[i];
299 const char * ftag = cpl_frame_get_tag(frame);
306 (void)cpl_error_set(cpl_func, CPL_ERROR_ILLEGAL_INPUT);
310 if (strcmp(tag, ftag))
continue;
312 copy = cpl_frame_duplicate(frame);
315 if (code != CPL_ERROR_NONE)
break;
317 if (self->propertylist[i] != NULL)
new->propertylist[newsize]
318 = cpl_propertylist_duplicate(self->propertylist[i]);
323 assert( newsize == new->size );
326#if defined CPL_HAVE_VA_ARGS && CPL_HAVE_VA_ARGS != 0
327 cpl_error_set_message(cpl_func, CPL_ERROR_DATA_NOT_FOUND,
328 "The list of %d frame(s) has no frames "
329 "with tag: %s", self->size, tag);
331 cpl_error_set_message(cpl_func, CPL_ERROR_DATA_NOT_FOUND,
332 "The list of frame(s) has no frames "
333 "with the given tag");
359 irplib_framelist *
new;
362 const int xor_val = (invert == CPL_FALSE ? 0 : 1);
366 cpl_ensure(self != NULL, CPL_ERROR_NULL_INPUT, NULL);
367 cpl_ensure(regexp != NULL, CPL_ERROR_NULL_INPUT, NULL);
369 error = regcomp(&re, regexp, REG_EXTENDED | REG_NOSUB);
370 cpl_ensure(!error, CPL_ERROR_ILLEGAL_INPUT, NULL);
375 for (i = 0; i < self->size; i++) {
376 const cpl_frame * frame = self->frame[i];
377 const char * tag = cpl_frame_get_tag(frame);
384 cpl_ensure(0, CPL_ERROR_ILLEGAL_INPUT, NULL);
387 if ((regexec(&re, tag, (
size_t)0, NULL, 0) == REG_NOMATCH ? 1 : 0)
390 copy = cpl_frame_duplicate(frame);
393 assert(error == CPL_ERROR_NONE);
395 if (self->propertylist[i] != NULL)
new->propertylist[newsize]
396 = cpl_propertylist_duplicate(self->propertylist[i]);
404 assert( newsize == new->size );
407#if defined CPL_HAVE_VA_ARGS && CPL_HAVE_VA_ARGS != 0
408 cpl_error_set_message(cpl_func, CPL_ERROR_DATA_NOT_FOUND,
409 "The list of %d frame(s) has no frames "
410 "that match: %s", self->size, regexp);
412 cpl_error_set_message(cpl_func, CPL_ERROR_DATA_NOT_FOUND,
413 "The list of frames has no frames "
414 "that match the regular expression");
435 cpl_ensure(self != NULL, CPL_ERROR_NULL_INPUT, -1);
452 cpl_ensure(self != NULL, CPL_ERROR_NULL_INPUT, NULL);
453 cpl_ensure(pos >= 0, CPL_ERROR_ILLEGAL_INPUT, NULL);
454 cpl_ensure(pos < self->size, CPL_ERROR_ACCESS_OUT_OF_RANGE, NULL);
456 return self->frame[pos];
474 cpl_ensure(self != NULL, CPL_ERROR_NULL_INPUT, NULL);
475 cpl_ensure(pos >= 0, CPL_ERROR_ILLEGAL_INPUT, NULL);
476 cpl_ensure(pos < self->size, CPL_ERROR_ACCESS_OUT_OF_RANGE, NULL);
478 return self->frame[pos];
494 const cpl_propertylist * list)
497 cpl_ensure_code(self != NULL, CPL_ERROR_NULL_INPUT);
498 cpl_ensure_code(list != NULL, CPL_ERROR_NULL_INPUT);
499 cpl_ensure_code(pos >= 0, CPL_ERROR_ILLEGAL_INPUT);
500 cpl_ensure_code(pos < self->size, CPL_ERROR_ACCESS_OUT_OF_RANGE);
502 cpl_propertylist_delete(self->propertylist[pos]);
504 self->propertylist[pos] = cpl_propertylist_duplicate(list);
506 cpl_ensure_code(self->propertylist[pos] != NULL, cpl_error_get_code());
508 return CPL_ERROR_NONE;
528 cpl_ensure(self != NULL, CPL_ERROR_NULL_INPUT, NULL);
529 cpl_ensure(pos >= 0, CPL_ERROR_ILLEGAL_INPUT, NULL);
530 cpl_ensure(pos < self->size, CPL_ERROR_ACCESS_OUT_OF_RANGE, NULL);
532 cpl_ensure(self->propertylist[pos] != NULL,
533 CPL_ERROR_DATA_NOT_FOUND, NULL);
535 return self->propertylist[pos];
553 const irplib_framelist * self,
557 cpl_ensure(self != NULL, CPL_ERROR_NULL_INPUT, NULL);
558 cpl_ensure(pos >= 0, CPL_ERROR_ILLEGAL_INPUT, NULL);
559 cpl_ensure(pos < self->size, CPL_ERROR_ACCESS_OUT_OF_RANGE, NULL);
561 cpl_ensure(self->propertylist[pos] != NULL,
562 CPL_ERROR_DATA_NOT_FOUND, NULL);
564 return self->propertylist[pos];
590 const char * filename;
593 cpl_ensure_code(self != NULL, CPL_ERROR_NULL_INPUT);
594 cpl_ensure_code(regexp != NULL, CPL_ERROR_NULL_INPUT);
595 cpl_ensure_code(pos >= 0, CPL_ERROR_ILLEGAL_INPUT);
596 cpl_ensure_code(pos < self->size, CPL_ERROR_ACCESS_OUT_OF_RANGE);
598 filename = cpl_frame_get_filename(self->frame[pos]);
600 cpl_ensure_code(filename != NULL, cpl_error_get_code());
602 cpl_propertylist_delete(self->propertylist[pos]);
604 self->propertylist[pos] = cpl_propertylist_load_regexp(filename, ind,
608 if (self->propertylist[pos] == NULL) {
609#if defined CPL_HAVE_VA_ARGS && CPL_HAVE_VA_ARGS != 0
610 return cpl_error_set_message(cpl_func, cpl_error_get_code(),
"Could "
611 "not load FITS header from '%s' using "
612 "regexp '%s'", filename, regexp);
614 return cpl_error_set_message(cpl_func, cpl_error_get_code(),
615 "Could not load FITS header");
619 return CPL_ERROR_NONE;
649 cpl_ensure_code(self != NULL, CPL_ERROR_NULL_INPUT);
650 cpl_ensure_code(regexp != NULL, CPL_ERROR_NULL_INPUT);
652 for (i=0; i < self->size; i++) {
653 if (self->propertylist[i] == NULL)
658 cpl_error_get_code());
661 nprops += cpl_propertylist_get_size(self->propertylist[i]);
665 cpl_msg_info(cpl_func,
"List of %d frames has %d properties", nfiles,
668 return CPL_ERROR_NONE;
689 cpl_ensure_code(self != NULL, CPL_ERROR_NULL_INPUT);
690 cpl_ensure_code(tag != NULL, CPL_ERROR_NULL_INPUT);
692 for (i=0; i < self->size; i++)
693 cpl_ensure_code(!cpl_frame_set_tag(self->frame[i], tag),
694 cpl_error_get_code());
696 return CPL_ERROR_NONE;
719 cpl_ensure_code(self != NULL, CPL_ERROR_NULL_INPUT);
720 cpl_ensure_code(frame != NULL, CPL_ERROR_NULL_INPUT);
721 cpl_ensure_code(pos >= 0, CPL_ERROR_ILLEGAL_INPUT);
723 if (pos == self->size) {
727 irplib_framelist_set_size(self);
731 cpl_ensure_code(pos < self->size, CPL_ERROR_ACCESS_OUT_OF_RANGE);
733 cpl_frame_delete(self->frame[pos]);
734 cpl_propertylist_delete(self->propertylist[pos]);
737 self->frame[pos] = frame;
738 self->propertylist[pos] = NULL;
740 return CPL_ERROR_NONE;
759 cpl_ensure_code(self != NULL, CPL_ERROR_NULL_INPUT);
760 cpl_ensure_code(pos >= 0, CPL_ERROR_ILLEGAL_INPUT);
761 cpl_ensure_code(pos < self->size, CPL_ERROR_ACCESS_OUT_OF_RANGE);
765 cpl_frame_delete(self->frame[pos]);
766 cpl_propertylist_delete(self->propertylist[pos]);
769 for (i = pos+1; i < self->size; i++) {
771 self->frame[i-1] = self->frame[i];
773 self->propertylist[i-1] = self->propertylist[i];
779 irplib_framelist_set_size(self);
781 return CPL_ERROR_NONE;
805 cpl_propertylist ** plist)
812 cpl_ensure(self != NULL, CPL_ERROR_NULL_INPUT, NULL);
813 cpl_ensure(pos >= 0, CPL_ERROR_ILLEGAL_INPUT, NULL);
814 cpl_ensure(pos < self->size, CPL_ERROR_ACCESS_OUT_OF_RANGE, NULL);
817 frame = self->frame[pos];
820 *plist = self->propertylist[pos];
822 cpl_propertylist_delete(self->propertylist[pos]);
826 for (i = pos+1; i < self->size; i++) {
828 self->frame[i-1] = self->frame[i];
830 self->propertylist[i-1] = self->propertylist[i];
836 irplib_framelist_set_size(self);
856 while (self->size > 0) {
858 cpl_frame_delete(self->frame[self->size]);
859 cpl_propertylist_delete(self->propertylist[self->size]);
864 irplib_framelist_set_size(self);
911 const char * key, cpl_type type,
912 cpl_boolean is_equal,
double fp_tol)
915 char * value_0 = NULL;
916 char * value_i = NULL;
917 cpl_type type_0 = CPL_TYPE_INVALID;
921 cpl_ensure_code(self != NULL, CPL_ERROR_NULL_INPUT);
922 cpl_ensure_code(key != NULL, CPL_ERROR_NULL_INPUT);
923 cpl_ensure_code(fp_tol >= 0.0, CPL_ERROR_ILLEGAL_INPUT);
925 for (i=0; i < self->size; i++) {
929 if (self->propertylist[i] == NULL)
continue;
930 if (ifirst < 0) ifirst = i;
932 type_i = cpl_propertylist_get_type(self->propertylist[i], key);
934 if (type_i == CPL_TYPE_INVALID) {
935 if (type == CPL_TYPE_INVALID)
936#if defined CPL_HAVE_VA_ARGS && CPL_HAVE_VA_ARGS != 0
937 cpl_error_set_message(cpl_func, cpl_error_get_code(),
"FITS "
938 "key '%s' is missing from file %s", key,
939 cpl_frame_get_filename(self->frame[i]));
941 cpl_error_set_message(cpl_func, cpl_error_get_code(),
942 "FITS key '%s' [%s] is missing from file "
943 "%s", key, cpl_type_get_name(type),
944 cpl_frame_get_filename(self->frame[i]));
946 cpl_error_set_message(cpl_func, cpl_error_get_code(),
947 "A FITS key is missing from a file");
949 cpl_error_set_message(cpl_func, cpl_error_get_code(),
950 "A FITS key is missing from a file");
952 return cpl_error_get_code();
955 if (type != CPL_TYPE_INVALID && type_i != type) {
956#if defined CPL_HAVE_VA_ARGS && CPL_HAVE_VA_ARGS != 0
957 return cpl_error_set_message(cpl_func, CPL_ERROR_INVALID_TYPE,
958 "FITS key '%s' has type %s instead of "
959 "%s in file %s", key,
960 cpl_type_get_name(type_i),
961 cpl_type_get_name(type),
962 cpl_frame_get_filename(self->frame[i]));
964 return cpl_error_set_message(cpl_func, CPL_ERROR_INVALID_TYPE,
965 "A FITS key had an unexpected type");
970 if (!is_equal)
continue;
972 if (type_0 == CPL_TYPE_INVALID) {
977 if (type_i != type_0) {
978 assert( type == CPL_TYPE_INVALID );
979#if defined CPL_HAVE_VA_ARGS && CPL_HAVE_VA_ARGS != 0
980 return cpl_error_set_message(cpl_func, CPL_ERROR_TYPE_MISMATCH,
981 "FITS key '%s' has different types "
982 "(%s <=> %s) in files %s and %s", key,
983 cpl_type_get_name(type_0),
984 cpl_type_get_name(type_i),
985 cpl_frame_get_filename(self->frame[0]),
986 cpl_frame_get_filename(self->frame[i]));
988 return cpl_error_set_message(cpl_func, CPL_ERROR_TYPE_MISMATCH,
989 "A FITS key has different types in "
994 if (irplib_property_equal(self->propertylist[ifirst],
995 self->propertylist[i],
996 key, type_0, fp_tol, &value_0, &value_i))
999 if ((type_0 == CPL_TYPE_FLOAT || type_0 == CPL_TYPE_DOUBLE)
1001#if defined CPL_HAVE_VA_ARGS && CPL_HAVE_VA_ARGS != 0
1002 cpl_error_set_message(cpl_func, CPL_ERROR_INCOMPATIBLE_INPUT,
"FITS"
1003 " key '%s' [%s] has values that differ by "
1004 "more than %g (%s <=> %s) in files %s and %s",
1005 key, cpl_type_get_name(type_0), fp_tol,
1007 cpl_frame_get_filename(self->frame[0]),
1008 cpl_frame_get_filename(self->frame[i]));
1010 cpl_error_set_message(cpl_func, CPL_ERROR_INCOMPATIBLE_INPUT,
"A "
1011 "FITS key has values that differ by more "
1012 "than the allowed tolerance in two file");
1015#if defined CPL_HAVE_VA_ARGS && CPL_HAVE_VA_ARGS != 0
1016 cpl_error_set_message(cpl_func, CPL_ERROR_INCOMPATIBLE_INPUT,
1017 "FITS key '%s' [%s] has different values "
1018 "(%s <=> %s) in files %s and %s", key,
1019 cpl_type_get_name(type_0),
1021 cpl_frame_get_filename(self->frame[0]),
1022 cpl_frame_get_filename(self->frame[i]));
1024 cpl_error_set_message(cpl_func, CPL_ERROR_INCOMPATIBLE_INPUT,
"A "
1025 "FITS key has different values in two files");
1031 return cpl_error_get_code();
1034 return CPL_ERROR_NONE;
1059 cpl_imagelist * list = NULL;
1060 cpl_image * image = NULL;
1064 cpl_ensure(self != NULL, CPL_ERROR_NULL_INPUT, NULL);
1065 cpl_ensure(extnum >= 0, CPL_ERROR_ACCESS_OUT_OF_RANGE, NULL);
1066 cpl_ensure(planenum >= 0, CPL_ERROR_ACCESS_OUT_OF_RANGE, NULL);
1068 list = cpl_imagelist_new();
1070 for (i=0; i < self->size; i++, image = NULL) {
1071 const char * filename = cpl_frame_get_filename(self->frame[i]);
1072 cpl_error_code code;
1074 if (filename == NULL)
break;
1076 image = cpl_image_load(filename, pixeltype, planenum, extnum);
1077 if (image == NULL) {
1078#if defined CPL_HAVE_VA_ARGS && CPL_HAVE_VA_ARGS != 0
1079 (void)cpl_error_set_message(cpl_func, cpl_error_get_code(),
1080 "Could not load FITS-image from plane "
1081 "%d in extension %d in file %s",
1082 planenum, extnum, filename);
1084 (void)cpl_error_set_message(cpl_func, cpl_error_get_code(),
1085 "Could not load FITS-image");
1090 code = cpl_imagelist_set(list, image, i);
1091 if (code != CPL_ERROR_NONE)
break;
1094 cpl_image_delete(image);
1096 if (cpl_imagelist_get_size(list) != self->size) {
1097 cpl_imagelist_delete(list);
1099 (void)cpl_error_set_where(cpl_func);
1123static void irplib_framelist_set_size(irplib_framelist * self)
1127 assert( self != NULL);
1129 if (self->size == 0) {
1131 cpl_free(self->frame);
1132 cpl_free(self->propertylist);
1134 self->propertylist = NULL;
1135 }
else if (self->size > 0) {
1138 self->frame = cpl_realloc(self->frame, (
size_t)self->size *
sizeof(cpl_frame*));
1139 self->propertylist =
1140 cpl_realloc(self->propertylist,
1141 (
size_t)self->size *
sizeof(cpl_propertylist*));
1143 (void)cpl_error_set(cpl_func, CPL_ERROR_ILLEGAL_INPUT);
1173static cpl_boolean irplib_property_equal(
const cpl_propertylist * self,
1174 const cpl_propertylist * other,
1175 const char * key, cpl_type type,
1177 char ** sstring,
char ** ostring)
1183 assert(self != NULL);
1184 assert(other != NULL);
1185 assert(key != NULL);
1186 assert(sstring != NULL);
1187 assert(ostring != NULL);
1190 assert(cpl_propertylist_get_type(other, key) == type);
1191 assert(fp_tol >= 0.0);
1193 if (self == other)
return CPL_TRUE;
1197 case CPL_TYPE_CHAR: {
1198 const char svalue = cpl_propertylist_get_char(self, key);
1199 const char ovalue = cpl_propertylist_get_char(other, key);
1201 equal = svalue == ovalue ? CPL_TRUE : CPL_FALSE;
1203 *sstring = cpl_sprintf(
"%c", svalue);
1204 *ostring = cpl_sprintf(
"%c", ovalue);
1209 case CPL_TYPE_BOOL: {
1210 const int svalue = cpl_propertylist_get_bool(self, key);
1211 const int ovalue = cpl_propertylist_get_bool(other, key);
1213 equal = svalue == ovalue ? CPL_TRUE : CPL_FALSE;
1215 *sstring = cpl_strdup(svalue == 0 ?
"F" :
"T");
1216 *ostring = cpl_strdup(ovalue == 0 ?
"F" :
"T");
1221 case CPL_TYPE_INT: {
1222 const int svalue = cpl_propertylist_get_int(self, key);
1223 const int ovalue = cpl_propertylist_get_int(other, key);
1225 equal = svalue == ovalue ? CPL_TRUE : CPL_FALSE;
1227 *sstring = cpl_sprintf(
"%d", svalue);
1228 *ostring = cpl_sprintf(
"%d", ovalue);
1233 case CPL_TYPE_LONG: {
1234 const long svalue = cpl_propertylist_get_long(self, key);
1235 const long ovalue = cpl_propertylist_get_long(other, key);
1237 equal = svalue == ovalue ? CPL_TRUE : CPL_FALSE;
1239 *sstring = cpl_sprintf(
"%ld", svalue);
1240 *ostring = cpl_sprintf(
"%ld", ovalue);
1245 case CPL_TYPE_FLOAT: {
1246 const double svalue = (double)cpl_propertylist_get_float(self, key);
1247 const double ovalue = (double)cpl_propertylist_get_float(other, key);
1249 equal = (fabs(svalue - ovalue) <= fp_tol) ? CPL_TRUE : CPL_FALSE;
1251 *sstring = cpl_sprintf(
"%f", svalue);
1252 *ostring = cpl_sprintf(
"%f", ovalue);
1257 case CPL_TYPE_DOUBLE: {
1258 const double svalue = cpl_propertylist_get_double(self, key);
1259 const double ovalue = cpl_propertylist_get_double(other, key);
1261 equal = (fabs(svalue - ovalue) <= fp_tol) ? CPL_TRUE : CPL_FALSE;
1263 *sstring = cpl_sprintf(
"%g", svalue);
1264 *ostring = cpl_sprintf(
"%g", ovalue);
1268 case CPL_TYPE_STRING: {
1269 const char * svalue = cpl_propertylist_get_string(self, key);
1270 const char * ovalue = cpl_propertylist_get_string(other, key);
1272 equal = strcmp(svalue, ovalue) == 0 ? CPL_TRUE : CPL_FALSE;
1274 *sstring = cpl_strdup(svalue);
1275 *ostring = cpl_strdup(ovalue);
1289 assert( *sstring != NULL );
1290 assert( *ostring != NULL );
int irplib_framelist_get_size(const irplib_framelist *self)
Get the size of a framelist.
cpl_frame * irplib_framelist_unset(irplib_framelist *self, int pos, cpl_propertylist **plist)
Erase a frame from a framelist and return it to the caller.
cpl_error_code irplib_framelist_set(irplib_framelist *self, cpl_frame *frame, int pos)
Add a frame to a framelist.
cpl_frameset * irplib_frameset_cast(const irplib_framelist *self)
Create a CPL frameset from an irplib_framelist.
irplib_framelist * irplib_framelist_extract(const irplib_framelist *self, const char *tag)
Extract the frames with the given tag from a framelist.
irplib_framelist * irplib_framelist_extract_regexp(const irplib_framelist *self, const char *regexp, cpl_boolean invert)
Extract the frames with the given tag from a framelist.
cpl_error_code irplib_framelist_load_propertylist(irplib_framelist *self, int pos, int ind, const char *regexp, cpl_boolean invert)
Load the propertylist of the specified frame in the framelist.
cpl_frame * irplib_framelist_get(irplib_framelist *self, int pos)
Get the specified frame from the framelist.
irplib_framelist * irplib_framelist_cast(const cpl_frameset *frameset)
Create an irplib_framelist from a cpl_framelist.
void irplib_framelist_delete(irplib_framelist *self)
Deallocate an irplib_framelist with its frames and properties.
void irplib_framelist_empty(irplib_framelist *self)
Erase all frames from a framelist.
cpl_error_code irplib_framelist_set_tag_all(irplib_framelist *self, const char *tag)
Set the tag of all frames in the list.
cpl_error_code irplib_framelist_erase(irplib_framelist *self, int pos)
Erase a frame from a framelist and delete it and its propertylist.
cpl_error_code irplib_framelist_set_propertylist(irplib_framelist *self, int pos, const cpl_propertylist *list)
Duplicate a propertylist to the specified position in the framelist.
cpl_propertylist * irplib_framelist_get_propertylist(irplib_framelist *self, int pos)
Get the propertylist of the specified frame in the framelist.
irplib_framelist * irplib_framelist_new(void)
Create an empty framelist.
const cpl_propertylist * irplib_framelist_get_propertylist_const(const irplib_framelist *self, int pos)
Get the propertylist of the specified frame in the framelist.
const cpl_frame * irplib_framelist_get_const(const irplib_framelist *self, int pos)
Get the specified frame from the framelist.
cpl_error_code irplib_framelist_load_propertylist_all(irplib_framelist *self, int ind, const char *regexp, cpl_boolean invert)
Load the propertylists of all frames in the framelist.
cpl_imagelist * irplib_imagelist_load_framelist(const irplib_framelist *self, cpl_type pixeltype, int planenum, int extnum)
Load an imagelist from a framelist.
cpl_error_code irplib_framelist_contains(const irplib_framelist *self, const char *key, cpl_type type, cpl_boolean is_equal, double fp_tol)
Verify that a property is present for all frames.