28#include <cxmessages.h>
30#include <cxstrutils.h>
38#include "gilinedata.h"
68_giraffe_linedata_compare(cxcptr s, cxcptr t)
71 return strcmp(s, t) < 0 ? TRUE : FALSE;
76_giraffe_linedata_clear(GiLineData* self)
83 cx_free((cxptr)self->model);
88 cx_free(self->ignore);
92 if (self->wavelength) {
93 cx_free(self->wavelength);
94 self->wavelength = NULL;
98 cpl_image_delete(self->status);
103 cx_map_clear(self->values);
106 cx_assert(cx_map_empty(self->values));
113_giraffe_linedata_assign(GiLineData* self, cx_map* map,
const cxchar* name,
114 const cpl_image* values)
117 cx_map_iterator position = cx_map_find(map, name);
120 if (cpl_image_get_size_x(values) != self->nfibers) {
124 if (cpl_image_get_size_y(values) != self->nlines) {
128 if (position == cx_map_end(map)) {
129 cx_map_insert(map, cx_strdup(name), values);
133 cpl_image* previous = cx_map_assign(map, position, values);
135 if (previous != NULL) {
136 cpl_image_delete(previous);
148_giraffe_linedata_set(GiLineData* self, cx_map* map,
const cxchar* name,
149 cxint i, cxint j, cxdouble value)
152 cxdouble* data = NULL;
154 cx_map_const_iterator position = cx_map_find(map, name);
157 if (position == cx_map_end(map)) {
159 cpl_image* buffer = cpl_image_new(self->nfibers, self->nlines,
161 cx_map_insert(map, cx_strdup(name), buffer);
162 data = cpl_image_get_data(buffer);
167 data = cpl_image_get_data(cx_map_get_value(map, position));
171 data[self->nfibers * j + i] = value;
179_giraffe_linedata_get(
const GiLineData* self,
const cx_map* map,
180 const cxchar* name, cxint i, cxint j, cxdouble* value)
183 cxdouble* data = NULL;
185 cx_map_const_iterator position = cx_map_find(map, name);
187 if (position == cx_map_end(map)) {
191 data = cpl_image_get_data(cx_map_get_value(map, position));
192 *value = data[self->nfibers * j + i];
200giraffe_linedata_new(
void)
203 GiLineData* self = cx_calloc(1,
sizeof *self);
211 self->wavelength = NULL;
214 self->values = cx_map_new(_giraffe_linedata_compare, cx_free,
215 (cx_free_func)cpl_image_delete);
216 cx_assert(cx_map_empty(self->values));
224giraffe_linedata_create(
const cpl_table* lines,
const cpl_table* fibers,
229 GiLineData* self = NULL;
236 if (!cpl_table_has_column(lines,
"WLEN")) {
240 if (fibers == NULL) {
248 self = cx_malloc(
sizeof(GiLineData));
251 self->nfibers = cpl_table_get_nrow(fibers);
252 self->nlines = cpl_table_get_nrow(lines);
254 self->model = cx_strdup(model);
255 self->ignore = cx_calloc(self->nlines,
sizeof(cxint));
257 self->wavelength = cx_calloc(self->nlines,
sizeof(cxdouble));
259 for (i = 0; i < self->nlines; i++) {
260 self->wavelength[i] = cpl_table_get(lines,
"WLEN", i, NULL);
266 self->values = cx_map_new(_giraffe_linedata_compare, cx_free,
267 (cx_free_func)cpl_image_delete);
268 cx_assert(cx_map_empty(self->values));
276giraffe_linedata_delete(GiLineData* self)
280 _giraffe_linedata_clear(self);
282 if (self->values != NULL) {
283 cx_map_delete(self->values);
295giraffe_linedata_reset(GiLineData* self,
const cpl_table* lines,
296 const cpl_table* fibers,
const cxchar* model)
302 cx_assert(self != NULL);
308 if (!cpl_table_has_column(lines,
"WLEN")) {
312 if (fibers == NULL) {
321 self->nfibers = cpl_table_get_nrow(fibers);
322 self->nlines = cpl_table_get_nrow(lines);
324 if (self->model != NULL) {
325 cx_free((cxchar*)self->model);
327 self->model = cx_strdup(model);
329 if (self->ignore != NULL) {
330 cx_free(self->ignore);
332 self->ignore = cx_calloc(self->nlines,
sizeof(cxint));
334 self->wavelength = cx_realloc(self->wavelength,
335 self->nlines *
sizeof(cxdouble));
337 for (i = 0; i < self->nlines; i++) {
339 self->wavelength[i] = cpl_table_get(lines,
"WLEN", i,
344 if (self->status != NULL) {
345 cpl_image_delete(self->status);
349 if (!cx_map_empty(self->values)) {
350 cx_map_clear(self->values);
359giraffe_linedata_model(
const GiLineData* self)
362 cx_assert(self != NULL);
370giraffe_linedata_lines(
const GiLineData* self)
373 cx_assert(self != NULL);
381giraffe_linedata_fibers(
const GiLineData* self)
384 cx_assert(self != NULL);
386 return self->nfibers;
392giraffe_linedata_contains(GiLineData* self,
const cxchar* name)
395 cx_map_const_iterator position;
398 cx_assert(self != NULL);
404 position = cx_map_find(self->values, name);
406 if (position == cx_map_end(self->values)) {
416giraffe_linedata_rejected(
const GiLineData* self)
425 cx_assert(self != NULL);
427 if (self->status != NULL) {
429 status = cpl_image_get_data(self->status);
431 for (i = 0; i < self->nfibers * self->nlines; i++) {
445giraffe_linedata_accepted(
const GiLineData* self)
451 cx_assert(self != NULL);
453 count = self->nfibers * self->nlines;
455 return count - giraffe_linedata_rejected(self);
461giraffe_linedata_status(
const GiLineData* self)
464 cx_assert(self != NULL);
466 if (self->status == NULL) {
467 return cpl_image_new(self->nfibers, self->nlines, CPL_TYPE_INT);
470 return cpl_image_duplicate(self->status);
476giraffe_linedata_set_status(GiLineData* self, cxint fiber, cxint line,
483 cx_assert(self != NULL);
485 if (fiber >= self->nfibers) {
489 if (line >= self->nlines) {
493 if (self->status == NULL) {
494 self->status = cpl_image_new(self->nfibers, self->nlines,
496 if (self->status == NULL) {
501 data = cpl_image_get_data(self->status);
503 data[self->nfibers * line + fiber] = status;
506 self->ignore[line] += 1;
515giraffe_linedata_get_status(
const GiLineData* self, cxint fiber, cxint line)
521 cx_assert(self != NULL);
523 if (fiber >= self->nfibers) {
527 if (line >= self->nlines) {
531 if (self->status == NULL) {
535 data = cpl_image_get_data(self->status);
537 return data[self->nfibers * line + fiber];
543giraffe_linedata_set_wavelength(GiLineData* self, cxint line, cxdouble lambda)
546 cx_assert(self != NULL);
548 if (line < 0 || line >= self->nlines) {
552 self->wavelength[line] = lambda;
560giraffe_linedata_get_wavelength(
const GiLineData* self, cxint line)
563 const cxchar*
const fctid =
"giraffe_linedata_get_wavelength";
566 cx_assert(self != NULL);
568 if (line < 0 || line >= self->nlines) {
569 cpl_error_set(fctid, CPL_ERROR_ILLEGAL_INPUT);
573 return self->wavelength[line];
579giraffe_linedata_set(GiLineData* self,
const cxchar* name, cxint fiber,
580 cxint line, cxdouble value)
585 cx_assert(self != NULL);
591 if (fiber >= self->nfibers) {
595 if (line >= self->nlines) {
599 status = _giraffe_linedata_set(self, self->values, name, fiber, line,
612giraffe_linedata_get(
const GiLineData* self,
const cxchar* name, cxint fiber,
616 const cxchar*
const fctid =
"giraffe_linedata_get";
623 cx_assert(self != NULL);
629 if (fiber >= self->nfibers) {
633 if (line >= self->nlines) {
637 status = _giraffe_linedata_get(self, self->values, name, fiber, line,
641 cpl_error_set(fctid, CPL_ERROR_DATA_NOT_FOUND);
651giraffe_linedata_set_data(GiLineData* self,
const cxchar* name,
652 const cpl_image* data)
658 cx_assert(self != NULL);
668 status = _giraffe_linedata_assign(self, self->values, name, data);
680giraffe_linedata_get_data(
const GiLineData* self,
const cxchar* name)
683 cx_assert(self != NULL);
689 return cx_map_get(self->values, name);
695giraffe_linedata_load(GiLineData* self,
const cxchar* filename)
698 cxsize extension = 1;
700 cpl_table* lines = NULL;
702 cpl_propertylist* p = NULL;
705 if (self == NULL || filename == NULL) {
709 _giraffe_linedata_clear(self);
712 giraffe_error_push();
714 p = cpl_propertylist_load(filename, 0);
720 if (cpl_propertylist_has(p, GIALIAS_WSOL_LMNAME) == 0) {
725 self->model = cx_strdup(cpl_propertylist_get_string(p,
726 GIALIAS_WSOL_LMNAME));
730 if (cpl_error_get_code() != CPL_ERROR_NONE) {
733 cpl_propertylist_delete(p);
743 cpl_propertylist_delete(p);
751 lines = cpl_table_load(filename, extension, 0);
754 _giraffe_linedata_clear(self);
758 if (cpl_table_has_column(lines,
"WLEN") == FALSE) {
759 _giraffe_linedata_clear(self);
760 cpl_table_delete(lines);
765 const cxdouble* lambda = cpl_table_get_data_double(lines,
"WLEN");
767 self->nlines = cpl_table_get_nrow(lines);
769 self->ignore = cx_calloc(self->nlines,
sizeof(cxint));
770 self->wavelength = cx_malloc(self->nlines *
sizeof(cxdouble));
772 memcpy(self->wavelength, lambda, self->nlines *
sizeof(cxdouble));
775 cpl_table_delete(lines);
779 self->status = cpl_image_load(filename, CPL_TYPE_INT, 0, extension);
781 if (self->status == NULL) {
782 _giraffe_linedata_clear(self);
786 self->nfibers = cpl_image_get_size_x(self->status);
797 p = cpl_propertylist_load(filename, extension);
803 while ((p != NULL) && (extension < 22)) {
805 const cxchar* name = cpl_propertylist_get_string(p, GIALIAS_EXTNAME);
808 cpl_propertylist_delete(p);
811 _giraffe_linedata_clear(self);
817 cpl_image* buffer = cpl_image_load(filename, CPL_TYPE_DOUBLE,
820 if ((cpl_image_get_size_x(buffer) != self->nfibers) ||
821 (cpl_image_get_size_y(buffer) != self->nlines)) {
823 cpl_image_delete(buffer);
826 cpl_propertylist_delete(p);
829 _giraffe_linedata_clear(self);
835 cx_map_insert(self->values, cx_strdup(name), buffer);
841 cpl_propertylist_delete(p);
842 p = cpl_propertylist_load(filename, extension);
846 cpl_propertylist_delete(p);
855giraffe_linedata_save(GiLineData* self,
const cpl_propertylist* properties,
856 const cxchar* filename)
861 cpl_propertylist* p = NULL;
864 if (self == NULL || properties == NULL || filename == NULL) {
868 p = cpl_propertylist_duplicate(properties);
870 status = giraffe_linedata_writer(self, p, filename, NULL);
872 cpl_propertylist_delete(p);
881giraffe_linedata_writer(
const GiLineData* self, cpl_propertylist* properties,
882 const cxchar* filename, cxcptr data)
885 const cxchar*
const fctid =
"giraffe_linedata_writer";
887 cx_map_const_iterator position;
889 cpl_propertylist* p = NULL;
891 cpl_table* lines = NULL;
897 if (self == NULL || properties == NULL || filename == NULL) {
901 lines = cpl_table_new(self->nlines);
907 giraffe_error_push();
909 cpl_table_new_column(lines,
"WLEN", CPL_TYPE_DOUBLE);
910 cpl_table_copy_data_double(lines,
"WLEN", self->wavelength);
912 if (cpl_error_get_code() != CPL_ERROR_NONE) {
913 cpl_table_delete(lines);
922 cpl_propertylist_erase(properties,
"BSCALE");
923 cpl_propertylist_erase(properties,
"BZERO");
924 cpl_propertylist_erase(properties,
"BUNIT");
930 cpl_propertylist_erase_regexp(properties,
"^CRPIX[0-9]$", 0);
931 cpl_propertylist_erase_regexp(properties,
"^CRVAL[0-9]$", 0);
932 cpl_propertylist_erase_regexp(properties,
"^CDELT[0-9]$", 0);
933 cpl_propertylist_erase_regexp(properties,
"^CTYPE[0-9]$", 0);
935 cpl_propertylist_erase_regexp(properties,
"^DATA(MIN|MAX)", 0);
937 cpl_propertylist_erase(properties,
"EXTNAME");
940 cpl_propertylist_update_string(properties, GIALIAS_WSOL_LMNAME,
942 cpl_propertylist_set_comment(properties, GIALIAS_WSOL_LMNAME,
943 "Line profile model");
945 p = cpl_propertylist_new();
946 cpl_propertylist_append_string(p, GIALIAS_EXTNAME,
"LINES");
947 cpl_propertylist_set_comment(p, GIALIAS_EXTNAME,
"FITS Extension name");
949 giraffe_error_push();
951 cpl_table_save(lines, properties, p, filename, CPL_IO_CREATE);
953 if (cpl_error_get_code() != CPL_ERROR_NONE) {
955 cpl_propertylist_delete(p);
958 cpl_table_delete(lines);
964 cpl_table_delete(lines);
969 cpl_propertylist_set_string(p, GIALIAS_EXTNAME,
"LINE_FLAGS");
971 giraffe_error_push();
973 if (self->status == NULL) {
975 cpl_image* status = cpl_image_new(self->nfibers, self->nlines,
978 cpl_image_save(status, filename, CPL_BPP_16_SIGNED, p,
980 cpl_image_delete(status);
985 cpl_image_save(self->status, filename, CPL_BPP_16_SIGNED, p,
989 if (cpl_error_get_code() != CPL_ERROR_NONE) {
990 cpl_propertylist_delete(p);
996 position = cx_map_begin(self->values);
997 while (position != cx_map_end(self->values)) {
1001 const cpl_image* ldata = cx_map_get_value(self->values, position);
1004 switch (cpl_image_get_type(ldata)) {
1006 format = CPL_BPP_32_SIGNED;
1009 case CPL_TYPE_FLOAT:
1010 format = CPL_BPP_IEEE_FLOAT;
1013 case CPL_TYPE_DOUBLE:
1014 format = CPL_BPP_IEEE_FLOAT;
1018 cpl_propertylist_delete(p);
1021 cpl_error_set(fctid, CPL_ERROR_TYPE_MISMATCH);
1027 cpl_propertylist_set_string(p, GIALIAS_EXTNAME,
1028 cx_map_get_key(self->values, position));
1030 cpl_image_save(ldata, filename, format, p, CPL_IO_EXTEND);
1032 if (cpl_error_get_code() != CPL_ERROR_NONE) {
1033 cpl_propertylist_delete(p);
1039 position = cx_map_next(self->values, position);
1043 giraffe_error_pop();
1045 cpl_propertylist_delete(p);