36 #include <cxmessages.h>
38 #include <cxstrutils.h>
40 #include <cpl_error.h>
41 #include <cpl_image.h>
46 #include "gilinedata.h"
76 _giraffe_linedata_compare(cxcptr s, cxcptr t)
79 return strcmp(s, t) < 0 ? TRUE : FALSE;
85 _giraffe_linedata_get_data(cx_map* map,
const cxchar* name)
89 cpl_image* data = cx_map_get(map, name);
95 return cpl_image_get_data(data);
101 _giraffe_linedata_clear(GiLineData*
self)
108 cx_free((cxptr)self->model);
113 cx_free(self->ignore);
117 if (self->wavelength) {
118 cx_free(self->wavelength);
119 self->wavelength = NULL;
123 cpl_image_delete(self->status);
128 cx_map_clear(self->values);
131 cx_assert(cx_map_empty(self->values));
138 _giraffe_linedata_assign(GiLineData*
self, cx_map* map,
const cxchar* name,
139 const cpl_image* values)
142 cx_map_iterator position = cx_map_find(map, name);
145 if (cpl_image_get_size_x(values) != self->nfibers) {
149 if (cpl_image_get_size_y(values) != self->nlines) {
153 if (position == cx_map_end(map)) {
154 cx_map_insert(map, cx_strdup(name), values);
158 cpl_image* previous = cx_map_assign(map, position, values);
160 if (previous != NULL) {
161 cpl_image_delete(previous);
173 _giraffe_linedata_set(GiLineData*
self, cx_map* map,
const cxchar* name,
174 cxint i, cxint j, cxdouble value)
177 cxdouble* data = NULL;
179 cx_map_const_iterator position = cx_map_find(map, name);
182 if (position == cx_map_end(map)) {
184 cpl_image* buffer = cpl_image_new(self->nfibers, self->nlines,
186 cx_map_insert(map, cx_strdup(name), buffer);
187 data = cpl_image_get_data(buffer);
192 data = cpl_image_get_data(cx_map_get_value(map, position));
196 data[
self->nfibers * j + i] = value;
204 _giraffe_linedata_get(
const GiLineData*
self,
const cx_map* map,
205 const cxchar* name, cxint i, cxint j, cxdouble* value)
208 cxdouble* data = NULL;
210 cx_map_const_iterator position = cx_map_find(map, name);
212 if (position == cx_map_end(map)) {
216 data = cpl_image_get_data(cx_map_get_value(map, position));
217 *value = data[
self->nfibers * j + i];
225 giraffe_linedata_new(
void)
228 GiLineData*
self = cx_calloc(1,
sizeof *
self);
236 self->wavelength = NULL;
239 self->values = cx_map_new(_giraffe_linedata_compare, cx_free,
240 (cx_free_func)cpl_image_delete);
241 cx_assert(cx_map_empty(self->values));
249 giraffe_linedata_create(
const cpl_table* lines,
const cpl_table* fibers,
254 GiLineData*
self = NULL;
261 if (!cpl_table_has_column(lines,
"WLEN")) {
265 if (fibers == NULL) {
273 self = cx_malloc(
sizeof(GiLineData));
276 self->nfibers = cpl_table_get_nrow(fibers);
277 self->nlines = cpl_table_get_nrow(lines);
279 self->model = cx_strdup(model);
280 self->ignore = cx_calloc(self->nlines,
sizeof(cxint));
282 self->wavelength = cx_calloc(self->nlines,
sizeof(cxdouble));
284 for (i = 0; i <
self->nlines; i++) {
285 self->wavelength[i] = cpl_table_get(lines,
"WLEN", i, NULL);
291 self->values = cx_map_new(_giraffe_linedata_compare, cx_free,
292 (cx_free_func)cpl_image_delete);
293 cx_assert(cx_map_empty(self->values));
301 giraffe_linedata_delete(GiLineData*
self)
305 _giraffe_linedata_clear(
self);
307 if (self->values != NULL) {
308 cx_map_delete(self->values);
320 giraffe_linedata_reset(GiLineData*
self,
const cpl_table* lines,
321 const cpl_table* fibers,
const cxchar* model)
327 cx_assert(
self != NULL);
333 if (!cpl_table_has_column(lines,
"WLEN")) {
337 if (fibers == NULL) {
346 self->nfibers = cpl_table_get_nrow(fibers);
347 self->nlines = cpl_table_get_nrow(lines);
349 if (self->model != NULL) {
350 cx_free((cxchar*)self->model);
352 self->model = cx_strdup(model);
354 if (self->ignore != NULL) {
355 cx_free(self->ignore);
357 self->ignore = cx_calloc(self->nlines,
sizeof(cxint));
359 self->wavelength = cx_realloc(self->wavelength,
360 self->nlines *
sizeof(cxdouble));
362 for (i = 0; i <
self->nlines; i++) {
364 self->wavelength[i] = cpl_table_get(lines,
"WLEN", i,
369 if (self->status != NULL) {
370 cpl_image_delete(self->status);
374 if (!cx_map_empty(self->values)) {
375 cx_map_clear(self->values);
384 giraffe_linedata_model(
const GiLineData*
self)
387 cx_assert(
self != NULL);
395 giraffe_linedata_lines(
const GiLineData*
self)
398 cx_assert(
self != NULL);
406 giraffe_linedata_fibers(
const GiLineData*
self)
409 cx_assert(
self != NULL);
411 return self->nfibers;
417 giraffe_linedata_contains(GiLineData*
self,
const cxchar* name)
420 cx_map_const_iterator position;
423 cx_assert(
self != NULL);
429 position = cx_map_find(self->values, name);
431 if (position == cx_map_end(self->values)) {
441 giraffe_linedata_rejected(
const GiLineData*
self)
450 cx_assert(
self != NULL);
452 if (self->status != NULL) {
454 status = cpl_image_get_data(self->status);
456 for (i = 0; i <
self->nfibers *
self->nlines; i++) {
470 giraffe_linedata_accepted(
const GiLineData*
self)
476 cx_assert(
self != NULL);
478 count =
self->nfibers *
self->nlines;
480 return count - giraffe_linedata_rejected(
self);
486 giraffe_linedata_status(
const GiLineData*
self)
489 cx_assert(
self != NULL);
491 if (self->status == NULL) {
492 return cpl_image_new(self->nfibers, self->nlines, CPL_TYPE_INT);
495 return cpl_image_duplicate(self->status);
501 giraffe_linedata_set_status(GiLineData*
self, cxint fiber, cxint line,
508 cx_assert(
self != NULL);
510 if (fiber >= self->nfibers) {
514 if (line >= self->nlines) {
518 if (self->status == NULL) {
519 self->status = cpl_image_new(self->nfibers, self->nlines,
521 if (self->status == NULL) {
526 data = cpl_image_get_data(self->status);
528 data[
self->nfibers * line + fiber] = status;
531 self->ignore[line] += 1;
540 giraffe_linedata_get_status(
const GiLineData*
self, cxint fiber, cxint line)
546 cx_assert(
self != NULL);
548 if (fiber >= self->nfibers) {
552 if (line >= self->nlines) {
556 if (self->status == NULL) {
560 data = cpl_image_get_data(self->status);
562 return data[
self->nfibers * line + fiber];
568 giraffe_linedata_set_wavelength(GiLineData*
self, cxint line, cxdouble lambda)
571 cx_assert(
self != NULL);
573 if (line < 0 || line >= self->nlines) {
577 self->wavelength[line] = lambda;
585 giraffe_linedata_get_wavelength(
const GiLineData*
self, cxint line)
588 const cxchar*
const fctid =
"giraffe_linedata_get_wavelength";
591 cx_assert(
self != NULL);
593 if (line < 0 || line >= self->nlines) {
594 cpl_error_set(fctid, CPL_ERROR_ILLEGAL_INPUT);
598 return self->wavelength[line];
604 giraffe_linedata_set(GiLineData*
self,
const cxchar* name, cxint fiber,
605 cxint line, cxdouble value)
610 cx_assert(
self != NULL);
616 if (fiber >= self->nfibers) {
620 if (line >= self->nlines) {
624 status = _giraffe_linedata_set(
self, self->values, name, fiber, line,
637 giraffe_linedata_get(
const GiLineData*
self,
const cxchar* name, cxint fiber,
641 const cxchar*
const fctid =
"giraffe_linedata_get";
648 cx_assert(
self != NULL);
654 if (fiber >= self->nfibers) {
658 if (line >= self->nlines) {
662 status = _giraffe_linedata_get(
self, self->values, name, fiber, line,
666 cpl_error_set(fctid, CPL_ERROR_DATA_NOT_FOUND);
676 giraffe_linedata_set_data(GiLineData*
self,
const cxchar* name,
677 const cpl_image* data)
683 cx_assert(
self != NULL);
693 status = _giraffe_linedata_assign(
self, self->values, name, data);
705 giraffe_linedata_get_data(
const GiLineData*
self,
const cxchar* name)
708 cx_assert(
self != NULL);
714 return cx_map_get(self->values, name);
720 giraffe_linedata_load(GiLineData*
self,
const cxchar* filename)
723 cxsize extension = 1;
725 cpl_table* lines = NULL;
727 cpl_propertylist* p = NULL;
730 if (
self == NULL || filename == NULL) {
734 _giraffe_linedata_clear(
self);
737 giraffe_error_push();
739 p = cpl_propertylist_load(filename, 0);
745 if (cpl_propertylist_has(p, GIALIAS_WSOL_LMNAME) == 0) {
750 self->model = cx_strdup(cpl_propertylist_get_string(p,
751 GIALIAS_WSOL_LMNAME));
755 if (cpl_error_get_code() != CPL_ERROR_NONE) {
758 cpl_propertylist_delete(p);
768 cpl_propertylist_delete(p);
776 lines = cpl_table_load(filename, extension, 0);
779 _giraffe_linedata_clear(
self);
783 if (cpl_table_has_column(lines,
"WLEN") == FALSE) {
784 _giraffe_linedata_clear(
self);
789 const cxdouble* lambda = cpl_table_get_data_double(lines,
"WLEN");
791 self->nlines = cpl_table_get_nrow(lines);
793 self->ignore = cx_calloc(self->nlines,
sizeof(cxint));
794 self->wavelength = cx_malloc(self->nlines *
sizeof(cxdouble));
796 memcpy(self->wavelength, lambda, self->nlines *
sizeof(cxdouble));
801 self->status = cpl_image_load(filename, CPL_TYPE_INT, 0, extension);
803 if (self->status == NULL) {
804 _giraffe_linedata_clear(
self);
808 self->nfibers = cpl_image_get_size_x(self->status);
819 p = cpl_propertylist_load(filename, extension);
825 while ((p != NULL) && (extension < 22)) {
827 const cxchar* name = cpl_propertylist_get_string(p, GIALIAS_EXTNAME);
830 cpl_propertylist_delete(p);
833 _giraffe_linedata_clear(
self);
839 cpl_image* buffer = cpl_image_load(filename, CPL_TYPE_DOUBLE,
842 if ((cpl_image_get_size_x(buffer) != self->nfibers) ||
843 (cpl_image_get_size_y(buffer) != self->nlines)) {
845 cpl_image_delete(buffer);
848 cpl_propertylist_delete(p);
851 _giraffe_linedata_clear(
self);
857 cx_map_insert(self->values, cx_strdup(name), buffer);
863 cpl_propertylist_delete(p);
864 p = cpl_propertylist_load(filename, extension);
868 cpl_propertylist_delete(p);
877 giraffe_linedata_save(GiLineData*
self,
const cpl_propertylist* properties,
878 const cxchar* filename)
883 cpl_propertylist* p = NULL;
886 if (
self == NULL || properties == NULL || filename == NULL) {
890 p = cpl_propertylist_duplicate(properties);
892 status = giraffe_linedata_writer(
self, p, filename, NULL);
894 cpl_propertylist_delete(p);
903 giraffe_linedata_writer(
const GiLineData*
self, cpl_propertylist* properties,
904 const cxchar* filename, cxcptr data)
907 const cxchar*
const fctid =
"giraffe_linedata_writer";
909 cx_map_const_iterator position;
911 cpl_propertylist* p = NULL;
913 cpl_table* lines = NULL;
919 if (
self == NULL || properties == NULL || filename == NULL) {
923 lines = cpl_table_new(self->nlines);
929 giraffe_error_push();
931 cpl_table_new_column(lines,
"WLEN", CPL_TYPE_DOUBLE);
932 cpl_table_copy_data_double(lines,
"WLEN", self->wavelength);
934 if (cpl_error_get_code() != CPL_ERROR_NONE) {
935 cpl_table_delete(lines);
948 cpl_propertylist_erase_regexp(properties,
"^CRPIX[0-9]$", 0);
949 cpl_propertylist_erase_regexp(properties,
"^CRVAL[0-9]$", 0);
950 cpl_propertylist_erase_regexp(properties,
"^CDELT[0-9]$", 0);
951 cpl_propertylist_erase_regexp(properties,
"^CTYPE[0-9]$", 0);
954 cpl_propertylist_update_string(properties, GIALIAS_WSOL_LMNAME,
956 cpl_propertylist_set_comment(properties, GIALIAS_WSOL_LMNAME,
957 "Line profile model");
959 p = cpl_propertylist_new();
960 cpl_propertylist_append_string(p, GIALIAS_EXTNAME,
"LINES");
961 cpl_propertylist_set_comment(p, GIALIAS_EXTNAME,
"FITS Extension name");
963 giraffe_error_push();
965 cpl_table_save(lines, properties, p, filename, CPL_IO_CREATE);
967 if (cpl_error_get_code() != CPL_ERROR_NONE) {
969 cpl_propertylist_delete(p);
972 cpl_table_delete(lines);
978 cpl_table_delete(lines);
983 cpl_propertylist_set_string(p, GIALIAS_EXTNAME,
"LINE_FLAGS");
985 giraffe_error_push();
987 if (self->status == NULL) {
989 cpl_image* status = cpl_image_new(self->nfibers, self->nlines,
992 cpl_image_save(status, filename, CPL_BPP_16_SIGNED, p,
994 cpl_image_delete(status);
999 cpl_image_save(self->status, filename, CPL_BPP_16_SIGNED, p,
1003 if (cpl_error_get_code() != CPL_ERROR_NONE) {
1004 cpl_propertylist_delete(p);
1010 position = cx_map_begin(self->values);
1011 while (position != cx_map_end(self->values)) {
1015 const cpl_image* ldata = cx_map_get_value(self->values, position);
1018 switch (cpl_image_get_type(ldata)) {
1020 format = CPL_BPP_32_SIGNED;
1023 case CPL_TYPE_FLOAT:
1024 format = CPL_BPP_IEEE_FLOAT;
1027 case CPL_TYPE_DOUBLE:
1028 format = CPL_BPP_IEEE_FLOAT;
1032 cpl_propertylist_delete(p);
1035 cpl_error_set(fctid, CPL_ERROR_TYPE_MISMATCH);
1041 cpl_propertylist_set_string(p, GIALIAS_EXTNAME,
1042 cx_map_get_key(self->values, position));
1044 cpl_image_save(ldata, filename, format, p, CPL_IO_EXTEND);
1046 if (cpl_error_get_code() != CPL_ERROR_NONE) {
1047 cpl_propertylist_delete(p);
1053 position = cx_map_next(self->values, position);
1057 giraffe_error_pop();
1059 cpl_propertylist_delete(p);