28 #include <cxmessages.h>
30 #include <cxstrutils.h>
32 #include <cpl_error.h>
33 #include <cpl_image.h>
38 #include "gilinedata.h"
68 _giraffe_linedata_compare(cxcptr s, cxcptr t)
71 return strcmp(s, t) < 0 ? TRUE : FALSE;
77 _giraffe_linedata_get_data(cx_map* map,
const cxchar* name)
81 cpl_image* data = cx_map_get(map, name);
87 return cpl_image_get_data(data);
93 _giraffe_linedata_clear(GiLineData*
self)
100 cx_free((cxptr)self->model);
105 cx_free(self->ignore);
109 if (self->wavelength) {
110 cx_free(self->wavelength);
111 self->wavelength = NULL;
115 cpl_image_delete(self->status);
120 cx_map_clear(self->values);
123 cx_assert(cx_map_empty(self->values));
130 _giraffe_linedata_assign(GiLineData*
self, cx_map* map,
const cxchar* name,
131 const cpl_image* values)
134 cx_map_iterator position = cx_map_find(map, name);
137 if (cpl_image_get_size_x(values) != self->nfibers) {
141 if (cpl_image_get_size_y(values) != self->nlines) {
145 if (position == cx_map_end(map)) {
146 cx_map_insert(map, cx_strdup(name), values);
150 cpl_image* previous = cx_map_assign(map, position, values);
152 if (previous != NULL) {
153 cpl_image_delete(previous);
165 _giraffe_linedata_set(GiLineData*
self, cx_map* map,
const cxchar* name,
166 cxint i, cxint j, cxdouble value)
169 cxdouble* data = NULL;
171 cx_map_const_iterator position = cx_map_find(map, name);
174 if (position == cx_map_end(map)) {
176 cpl_image* buffer = cpl_image_new(self->nfibers, self->nlines,
178 cx_map_insert(map, cx_strdup(name), buffer);
179 data = cpl_image_get_data(buffer);
184 data = cpl_image_get_data(cx_map_get_value(map, position));
188 data[
self->nfibers * j + i] = value;
196 _giraffe_linedata_get(
const GiLineData*
self,
const cx_map* map,
197 const cxchar* name, cxint i, cxint j, cxdouble* value)
200 cxdouble* data = NULL;
202 cx_map_const_iterator position = cx_map_find(map, name);
204 if (position == cx_map_end(map)) {
208 data = cpl_image_get_data(cx_map_get_value(map, position));
209 *value = data[
self->nfibers * j + i];
217 giraffe_linedata_new(
void)
220 GiLineData*
self = cx_calloc(1,
sizeof *
self);
228 self->wavelength = NULL;
231 self->values = cx_map_new(_giraffe_linedata_compare, cx_free,
232 (cx_free_func)cpl_image_delete);
233 cx_assert(cx_map_empty(self->values));
241 giraffe_linedata_create(
const cpl_table* lines,
const cpl_table* fibers,
246 GiLineData*
self = NULL;
253 if (!cpl_table_has_column(lines,
"WLEN")) {
257 if (fibers == NULL) {
265 self = cx_malloc(
sizeof(GiLineData));
268 self->nfibers = cpl_table_get_nrow(fibers);
269 self->nlines = cpl_table_get_nrow(lines);
271 self->model = cx_strdup(model);
272 self->ignore = cx_calloc(self->nlines,
sizeof(cxint));
274 self->wavelength = cx_calloc(self->nlines,
sizeof(cxdouble));
276 for (i = 0; i <
self->nlines; i++) {
277 self->wavelength[i] = cpl_table_get(lines,
"WLEN", i, NULL);
283 self->values = cx_map_new(_giraffe_linedata_compare, cx_free,
284 (cx_free_func)cpl_image_delete);
285 cx_assert(cx_map_empty(self->values));
293 giraffe_linedata_delete(GiLineData*
self)
297 _giraffe_linedata_clear(
self);
299 if (self->values != NULL) {
300 cx_map_delete(self->values);
312 giraffe_linedata_reset(GiLineData*
self,
const cpl_table* lines,
313 const cpl_table* fibers,
const cxchar* model)
319 cx_assert(
self != NULL);
325 if (!cpl_table_has_column(lines,
"WLEN")) {
329 if (fibers == NULL) {
338 self->nfibers = cpl_table_get_nrow(fibers);
339 self->nlines = cpl_table_get_nrow(lines);
341 if (self->model != NULL) {
342 cx_free((cxchar*)self->model);
344 self->model = cx_strdup(model);
346 if (self->ignore != NULL) {
347 cx_free(self->ignore);
349 self->ignore = cx_calloc(self->nlines,
sizeof(cxint));
351 self->wavelength = cx_realloc(self->wavelength,
352 self->nlines *
sizeof(cxdouble));
354 for (i = 0; i <
self->nlines; i++) {
356 self->wavelength[i] = cpl_table_get(lines,
"WLEN", i,
361 if (self->status != NULL) {
362 cpl_image_delete(self->status);
366 if (!cx_map_empty(self->values)) {
367 cx_map_clear(self->values);
376 giraffe_linedata_model(
const GiLineData*
self)
379 cx_assert(
self != NULL);
387 giraffe_linedata_lines(
const GiLineData*
self)
390 cx_assert(
self != NULL);
398 giraffe_linedata_fibers(
const GiLineData*
self)
401 cx_assert(
self != NULL);
403 return self->nfibers;
409 giraffe_linedata_contains(GiLineData*
self,
const cxchar* name)
412 cx_map_const_iterator position;
415 cx_assert(
self != NULL);
421 position = cx_map_find(self->values, name);
423 if (position == cx_map_end(self->values)) {
433 giraffe_linedata_rejected(
const GiLineData*
self)
442 cx_assert(
self != NULL);
444 if (self->status != NULL) {
446 status = cpl_image_get_data(self->status);
448 for (i = 0; i <
self->nfibers *
self->nlines; i++) {
462 giraffe_linedata_accepted(
const GiLineData*
self)
468 cx_assert(
self != NULL);
470 count =
self->nfibers *
self->nlines;
472 return count - giraffe_linedata_rejected(
self);
478 giraffe_linedata_status(
const GiLineData*
self)
481 cx_assert(
self != NULL);
483 if (self->status == NULL) {
484 return cpl_image_new(self->nfibers, self->nlines, CPL_TYPE_INT);
487 return cpl_image_duplicate(self->status);
493 giraffe_linedata_set_status(GiLineData*
self, cxint fiber, cxint line,
500 cx_assert(
self != NULL);
502 if (fiber >= self->nfibers) {
506 if (line >= self->nlines) {
510 if (self->status == NULL) {
511 self->status = cpl_image_new(self->nfibers, self->nlines,
513 if (self->status == NULL) {
518 data = cpl_image_get_data(self->status);
520 data[
self->nfibers * line + fiber] = status;
523 self->ignore[line] += 1;
532 giraffe_linedata_get_status(
const GiLineData*
self, cxint fiber, cxint line)
538 cx_assert(
self != NULL);
540 if (fiber >= self->nfibers) {
544 if (line >= self->nlines) {
548 if (self->status == NULL) {
552 data = cpl_image_get_data(self->status);
554 return data[
self->nfibers * line + fiber];
560 giraffe_linedata_set_wavelength(GiLineData*
self, cxint line, cxdouble lambda)
563 cx_assert(
self != NULL);
565 if (line < 0 || line >= self->nlines) {
569 self->wavelength[line] = lambda;
577 giraffe_linedata_get_wavelength(
const GiLineData*
self, cxint line)
580 const cxchar*
const fctid =
"giraffe_linedata_get_wavelength";
583 cx_assert(
self != NULL);
585 if (line < 0 || line >= self->nlines) {
586 cpl_error_set(fctid, CPL_ERROR_ILLEGAL_INPUT);
590 return self->wavelength[line];
596 giraffe_linedata_set(GiLineData*
self,
const cxchar* name, cxint fiber,
597 cxint line, cxdouble value)
602 cx_assert(
self != NULL);
608 if (fiber >= self->nfibers) {
612 if (line >= self->nlines) {
616 status = _giraffe_linedata_set(
self, self->values, name, fiber, line,
629 giraffe_linedata_get(
const GiLineData*
self,
const cxchar* name, cxint fiber,
633 const cxchar*
const fctid =
"giraffe_linedata_get";
640 cx_assert(
self != NULL);
646 if (fiber >= self->nfibers) {
650 if (line >= self->nlines) {
654 status = _giraffe_linedata_get(
self, self->values, name, fiber, line,
658 cpl_error_set(fctid, CPL_ERROR_DATA_NOT_FOUND);
668 giraffe_linedata_set_data(GiLineData*
self,
const cxchar* name,
669 const cpl_image* data)
675 cx_assert(
self != NULL);
685 status = _giraffe_linedata_assign(
self, self->values, name, data);
697 giraffe_linedata_get_data(
const GiLineData*
self,
const cxchar* name)
700 cx_assert(
self != NULL);
706 return cx_map_get(self->values, name);
712 giraffe_linedata_load(GiLineData*
self,
const cxchar* filename)
715 cxsize extension = 1;
717 cpl_table* lines = NULL;
719 cpl_propertylist* p = NULL;
722 if (
self == NULL || filename == NULL) {
726 _giraffe_linedata_clear(
self);
729 giraffe_error_push();
731 p = cpl_propertylist_load(filename, 0);
737 if (cpl_propertylist_has(p, GIALIAS_WSOL_LMNAME) == 0) {
742 self->model = cx_strdup(cpl_propertylist_get_string(p,
743 GIALIAS_WSOL_LMNAME));
747 if (cpl_error_get_code() != CPL_ERROR_NONE) {
750 cpl_propertylist_delete(p);
760 cpl_propertylist_delete(p);
768 lines = cpl_table_load(filename, extension, 0);
771 _giraffe_linedata_clear(
self);
775 if (cpl_table_has_column(lines,
"WLEN") == FALSE) {
776 _giraffe_linedata_clear(
self);
781 const cxdouble* lambda = cpl_table_get_data_double(lines,
"WLEN");
783 self->nlines = cpl_table_get_nrow(lines);
785 self->ignore = cx_calloc(self->nlines,
sizeof(cxint));
786 self->wavelength = cx_malloc(self->nlines *
sizeof(cxdouble));
788 memcpy(self->wavelength, lambda, self->nlines *
sizeof(cxdouble));
793 self->status = cpl_image_load(filename, CPL_TYPE_INT, 0, extension);
795 if (self->status == NULL) {
796 _giraffe_linedata_clear(
self);
800 self->nfibers = cpl_image_get_size_x(self->status);
811 p = cpl_propertylist_load(filename, extension);
817 while ((p != NULL) && (extension < 22)) {
819 const cxchar* name = cpl_propertylist_get_string(p, GIALIAS_EXTNAME);
822 cpl_propertylist_delete(p);
825 _giraffe_linedata_clear(
self);
831 cpl_image* buffer = cpl_image_load(filename, CPL_TYPE_DOUBLE,
834 if ((cpl_image_get_size_x(buffer) != self->nfibers) ||
835 (cpl_image_get_size_y(buffer) != self->nlines)) {
837 cpl_image_delete(buffer);
840 cpl_propertylist_delete(p);
843 _giraffe_linedata_clear(
self);
849 cx_map_insert(self->values, cx_strdup(name), buffer);
855 cpl_propertylist_delete(p);
856 p = cpl_propertylist_load(filename, extension);
860 cpl_propertylist_delete(p);
869 giraffe_linedata_save(GiLineData*
self,
const cpl_propertylist* properties,
870 const cxchar* filename)
875 cpl_propertylist* p = NULL;
878 if (
self == NULL || properties == NULL || filename == NULL) {
882 p = cpl_propertylist_duplicate(properties);
884 status = giraffe_linedata_writer(
self, p, filename, NULL);
886 cpl_propertylist_delete(p);
895 giraffe_linedata_writer(
const GiLineData*
self, cpl_propertylist* properties,
896 const cxchar* filename, cxcptr data)
899 const cxchar*
const fctid =
"giraffe_linedata_writer";
901 cx_map_const_iterator position;
903 cpl_propertylist* p = NULL;
905 cpl_table* lines = NULL;
911 if (
self == NULL || properties == NULL || filename == NULL) {
915 lines = cpl_table_new(self->nlines);
921 giraffe_error_push();
923 cpl_table_new_column(lines,
"WLEN", CPL_TYPE_DOUBLE);
924 cpl_table_copy_data_double(lines,
"WLEN", self->wavelength);
926 if (cpl_error_get_code() != CPL_ERROR_NONE) {
927 cpl_table_delete(lines);
936 cpl_propertylist_erase(properties,
"BSCALE");
937 cpl_propertylist_erase(properties,
"BZERO");
938 cpl_propertylist_erase(properties,
"BUNIT");
944 cpl_propertylist_erase_regexp(properties,
"^CRPIX[0-9]$", 0);
945 cpl_propertylist_erase_regexp(properties,
"^CRVAL[0-9]$", 0);
946 cpl_propertylist_erase_regexp(properties,
"^CDELT[0-9]$", 0);
947 cpl_propertylist_erase_regexp(properties,
"^CTYPE[0-9]$", 0);
949 cpl_propertylist_erase_regexp(properties,
"^DATA(MIN|MAX)", 0);
951 cpl_propertylist_erase(properties,
"EXTNAME");
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);