GIRAFFE Pipeline Reference Manual

gipsfdata.c
1/*
2 * This file is part of the GIRAFFE Pipeline
3 * Copyright (C) 2002-2019 European Southern Observatory
4 *
5 * This program is free software; you can redistribute it and/or modify
6 * it under the terms of the GNU General Public License as published by
7 * the Free Software Foundation; either version 2 of the License, or
8 * (at your option) any later version.
9 *
10 * This program is distributed in the hope that it will be useful,
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 * GNU General Public License for more details.
14 *
15 * You should have received a copy of the GNU General Public License
16 * along with this program; if not, write to the Free Software
17 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
18 */
19
20#ifdef HAVE_CONFIG_H
21# include <config.h>
22#endif
23
24#include <string.h>
25
26#include <cxtypes.h>
27#include <cxmemory.h>
28#include <cxmessages.h>
29#include <cxstrutils.h>
30#include <cxmap.h>
31
32#include <cpl_type.h>
33
34#include "gialias.h"
35#include "gierror.h"
36#include "gipsfdata.h"
37
38
39/*
40 * @defgroup gipsfdata PSF Profile Data Storage
41 *
42 * TBD
43 */
44
47struct GiPsfData {
48
49 const cxchar* model;
50
51 cxint nfibers;
52 cxint nbins;
53 cxint width;
54 cxint height;
55
56 cpl_image* bins;
57 cx_map* values;
58
59};
60
61
62inline static cxbool
63_giraffe_psfdata_compare(cxcptr s, cxcptr t)
64{
65
66 return strcmp(s, t) < 0 ? TRUE : FALSE;
67
68}
69
70
71inline static void
72_giraffe_psfdata_clear(GiPsfData* self)
73{
74
75 if (self->model != NULL) {
76 cx_free((cxptr)self->model);
77 self->model = NULL;
78 }
79
80 if (self->bins != NULL) {
81 cpl_image_delete(self->bins);
82 self->bins = NULL;
83 }
84
85 if (self->values != NULL) {
86 cx_map_clear(self->values);
87 }
88
89 self->nfibers = 0;
90 self->nbins = 0;
91 self->width = 0;
92 self->height = 0;
93
94 return;
95
96}
97
98
99inline static void
100_giraffe_psfdata_resize(GiPsfData* self, cxint nfibers, cxint nbins,
101 cxint width, cxint height)
102{
103
104 cx_assert(self->values != NULL);
105
106 self->nfibers = nfibers;
107 self->nbins = nbins;
108 self->width = width;
109 self->height = height;
110
111 if (self->bins != NULL) {
112 cpl_image_delete(self->bins);
113 self->bins = NULL;
114 }
115
116 if (cx_map_empty(self->values) == FALSE) {
117 cx_map_clear(self->values);
118 cx_assert(cx_map_empty(self->values));
119 }
120
121 return;
122
123}
124
125
126inline static cxint
127_giraffe_psfdata_assign(GiPsfData* self, cx_map* map, const cxchar* name,
128 const cpl_image* values)
129{
130
131 cx_map_iterator position = cx_map_find(map, name);
132
133
134 if (cpl_image_get_size_x(values) != self->nfibers) {
135 return 1;
136 }
137
138 if (cpl_image_get_size_y(values) != self->nbins) {
139 return 2;
140 }
141
142 if (position == cx_map_end(map)) {
143 cx_map_insert(map, cx_strdup(name), values);
144 }
145 else {
146
147 cpl_image* previous = cx_map_assign(map, position, values);
148
149 if (previous != NULL) {
150 cpl_image_delete(previous);
151 previous = NULL;
152 }
153
154 }
155
156 return 0;
157
158}
159
160
161inline static cxint
162_giraffe_psfdata_set(GiPsfData* self, cx_map* map, const cxchar* name,
163 cxint i, cxint j, cxdouble value)
164{
165
166 cxdouble* data = NULL;
167
168 cx_map_const_iterator position = cx_map_find(map, name);
169
170
171 if (position == cx_map_end(map)) {
172
173 cpl_image* buffer = cpl_image_new(self->nfibers, self->nbins,
174 CPL_TYPE_DOUBLE);
175 cx_map_insert(map, cx_strdup(name), buffer);
176
177 data = cpl_image_get_data(buffer);
178
179 }
180 else {
181
182 data = cpl_image_get_data(cx_map_get_value(map, position));
183
184 }
185
186 data[self->nfibers * j + i] = value;
187
188 return 0;
189
190}
191
192
193inline static cxint
194_giraffe_psfdata_get(const GiPsfData* self, const cx_map* map,
195 const cxchar* name, cxint i, cxint j, cxdouble* value)
196{
197
198 cxdouble* data = NULL;
199
200 cx_map_const_iterator position = cx_map_find(map, name);
201
202 if (position == cx_map_end(map)) {
203 return 1;
204 }
205
206 data = cpl_image_get_data(cx_map_get_value(map, position));
207 *value = data[self->nfibers * j + i];
208
209 return 0;
210
211}
212
213
214GiPsfData*
215giraffe_psfdata_new(void)
216{
217
218 GiPsfData* self = cx_calloc(1, sizeof *self);
219
220 self->nfibers = 0;
221 self->nbins = 0;
222 self->width = 0;
223 self->height = 0;
224
225 self->model = NULL;
226
227 self->bins = NULL;
228 self->values = cx_map_new(_giraffe_psfdata_compare, cx_free,
229 (cx_free_func)cpl_image_delete);
230 cx_assert(cx_map_empty(self->values));
231
232 return self;
233
234}
235
236
237GiPsfData*
238giraffe_psfdata_create(cxint nfibers, cxint nbins, cxint width, cxint height)
239{
240
241 GiPsfData* self = giraffe_psfdata_new();
242
243 self->nfibers = nfibers;
244 self->nbins = nbins;
245 self->width = width;
246 self->height = height;
247
248 self->model = NULL;
249
250 self->bins = cpl_image_new(self->nfibers, self->nbins, CPL_TYPE_DOUBLE);
251
252 return self;
253
254}
255
256
257void
258giraffe_psfdata_delete(GiPsfData* self)
259{
260
261 if (self != NULL) {
262
263 if (self->model != NULL) {
264 cx_free((cxptr)self->model);
265 self->model = NULL;
266 }
267
268 if (self->bins != NULL) {
269 cpl_image_delete(self->bins);
270 self->bins = NULL;
271 }
272
273 if (self->values != NULL) {
274 cx_map_delete(self->values);
275 self->values = NULL;
276 }
277
278 cx_free(self);
279
280 }
281
282 return;
283
284}
285
286
287void
288giraffe_psfdata_clear(GiPsfData* self)
289{
290 _giraffe_psfdata_clear(self);
291 return;
292}
293
294
295void
296giraffe_psfdata_resize(GiPsfData* self, cxint nfibers, cxint nbins,
297 cxint width, cxint height)
298{
299
300 cx_assert(self != NULL);
301
302 _giraffe_psfdata_resize(self, nfibers, nbins, width, height);
303 self->bins = cpl_image_new(self->nfibers, self->nbins, CPL_TYPE_DOUBLE);
304
305 return;
306
307}
308
309
310cxsize
311giraffe_psfdata_fibers(const GiPsfData* self)
312{
313
314 cx_assert(self != NULL);
315 return self->nfibers;
316
317}
318
319
320cxsize
321giraffe_psfdata_bins(const GiPsfData* self)
322{
323
324 cx_assert(self != NULL);
325 return self->nbins;
326
327}
328
329
330cxsize
331giraffe_psfdata_xsize(const GiPsfData* self)
332{
333
334 cx_assert(self != NULL);
335 return self->width;
336
337}
338
339
340cxsize
341giraffe_psfdata_ysize(const GiPsfData* self)
342{
343
344 cx_assert(self != NULL);
345 return self->height;
346
347}
348
349
350cxsize
351giraffe_psfdata_parameters(const GiPsfData* self)
352{
353
354 cx_assert(self != NULL);
355 return cx_map_size(self->values);
356
357}
358
359
360cxbool
361giraffe_psfdata_contains(const GiPsfData* self, const cxchar* name)
362{
363
364 cx_map_const_iterator position;
365
366
367 cx_assert(self != NULL);
368
369 if (name == NULL) {
370 return FALSE;
371 }
372
373 position = cx_map_find(self->values, name);
374
375 if (position == cx_map_end(self->values)) {
376 return FALSE;
377 }
378
379 return TRUE;
380
381}
382
383
384const cxchar*
385giraffe_psfdata_get_name(const GiPsfData* self, cxsize position)
386{
387
388 const cxchar* name = NULL;
389
390
391 cx_assert(self != NULL);
392
393 if (position < cx_map_size(self->values)) {
394
395 cxsize i = 0;
396
397 cx_map_const_iterator pos = cx_map_begin(self->values);
398
399
400 while (i < position) {
401 pos = cx_map_next(self->values, pos);
402 ++i;
403 }
404
405 name = cx_map_get_key(self->values, pos);
406
407 }
408
409 return name;
410
411}
412
413
414cxint
415giraffe_psfdata_set_model(GiPsfData* self, const cxchar* name)
416{
417
418 cx_assert(self != NULL);
419
420 if (name == NULL) {
421 return 1;
422 }
423
424 if (self->model != NULL) {
425 cx_free((cxptr)self->model);
426 self->model = NULL;
427 }
428
429 self->model = cx_strdup(name);
430
431 return 0;
432
433}
434
435
436const cxchar*
437giraffe_psfdata_get_model(const GiPsfData* self)
438{
439
440 cx_assert(self != NULL);
441 return self->model;
442
443}
444
445
446cxint
447giraffe_psfdata_set_bin(GiPsfData* self, cxint fiber, cxint bin,
448 cxdouble position)
449{
450
451 cxdouble* data = NULL;
452
453
454 cx_assert(self != NULL);
455
456 if ((fiber < 0) || (fiber >= self->nfibers) ||
457 (bin < 0) || (bin >= self->nbins)) {
458 return 1;
459 }
460 else {
461
462 if (self->bins == NULL) {
463 self->bins = cpl_image_new(self->nfibers, self->nbins,
464 CPL_TYPE_DOUBLE);
465 }
466
467 data = cpl_image_get_data_double(self->bins);
468 data[self->nfibers * bin + fiber] = position;
469
470 }
471
472 return 0;
473
474}
475
476
477cxdouble
478giraffe_psfdata_get_bin(const GiPsfData* self, cxint fiber, cxint bin)
479{
480
481 const cxchar* const fctid = "giraffe_psfdata_get_bin";
482
483 cxdouble* data = NULL;
484
485
486 cx_assert(self != NULL);
487
488 if ((fiber < 0) || (fiber >= self->nfibers) ||
489 (bin < 0) || (bin >= self->nbins)) {
490 cpl_error_set(fctid, CPL_ERROR_ILLEGAL_INPUT);
491 return 0.;
492 }
493
494 if (self->bins == NULL) {
495
496 GiPsfData* _self = (GiPsfData*) self;
497
498 _self->bins = cpl_image_new(self->nfibers, self->nbins,
499 CPL_TYPE_DOUBLE);
500
501 }
502
503 data = cpl_image_get_data_double(self->bins);
504
505 return data[self->nfibers * bin + fiber];
506
507}
508
509
510const cpl_image*
511giraffe_psfdata_get_bins(const GiPsfData* self)
512{
513 cx_assert(self != NULL);
514 return self->bins;
515}
516
517
518cxint
519giraffe_psfdata_set(GiPsfData* self, const cxchar* name, cxint fiber,
520 cxint bin, cxdouble value)
521{
522
523 cxint status = 0;
524
525 cx_assert(self != NULL);
526
527 if (name == NULL) {
528 return 1;
529 }
530
531 if (fiber >= self->nfibers) {
532 return 1;
533 }
534
535 if (bin >= self->nbins) {
536 return 1;
537 }
538
539 status = _giraffe_psfdata_set(self, self->values, name, fiber, bin,
540 value);
541
542 if (status != 0) {
543 return 1;
544 }
545
546 return 0;
547
548}
549
550
551cxdouble
552giraffe_psfdata_get(const GiPsfData* self, const cxchar* name, cxint fiber,
553 cxint bin)
554{
555
556 const cxchar* const fctid = "giraffe_psfdata_get";
557
558 cxint status = 0;
559
560 cxdouble value = 0.;
561
562
563 cx_assert(self != NULL);
564
565 if (name == NULL) {
566 return 1;
567 }
568
569 if (fiber >= self->nfibers) {
570 return 1;
571 }
572
573 if (bin >= self->nbins) {
574 return 1;
575 }
576
577 status = _giraffe_psfdata_get(self, self->values, name, fiber, bin,
578 &value);
579
580 if (status != 0) {
581 cpl_error_set(fctid, CPL_ERROR_DATA_NOT_FOUND);
582 return 0.;
583 }
584
585 return value;
586
587}
588
589
590cxint
591giraffe_psfdata_set_data(GiPsfData* self, const cxchar* name,
592 const cpl_image* data)
593{
594
595 cxint status = 0;
596
597
598 cx_assert(self != NULL);
599
600 if (name == NULL) {
601 return 1;
602 }
603
604 if (data == NULL) {
605 return 1;
606 }
607
608 status = _giraffe_psfdata_assign(self, self->values, name, data);
609
610 if (status != 0) {
611 return 1;
612 }
613
614 return 0;
615
616}
617
618
619const cpl_image*
620giraffe_psfdata_get_data(const GiPsfData* self, const cxchar* name)
621{
622
623 cx_assert(self != NULL);
624
625 if (name == NULL) {
626 return NULL;
627 }
628
629 return cx_map_get(self->values, name);
630
631}
632
633
634cxint giraffe_psfdata_load(GiPsfData* self, const cxchar* filename)
635{
636
637 const cxchar* model = NULL;
638
639 cxint nfibers = 0;
640 cxint nbins = 0;
641 cxint nx = 0;
642 cxint ny = 0;
643 cxint nparameters = 0;
644
645 cxsize i = 0;
646 cxsize extension = 1;
647
648 cpl_propertylist* p = NULL;
649
650
651 if (self == NULL || filename == NULL) {
652 return -1;
653 }
654
655 giraffe_error_push();
656
657 p = cpl_propertylist_load(filename, 0);
658
659 if (p == NULL) {
660 return 1;
661 }
662
663 if (cpl_propertylist_has(p, GIALIAS_PSFMODEL) == 0) {
664 return 1;
665 }
666 else {
667 model = cpl_propertylist_get_string(p, GIALIAS_PSFMODEL);
668 }
669
670 if (cpl_propertylist_has(p, GIALIAS_PSFNS) == 0) {
671 return 1;
672 }
673 else {
674 nfibers = cpl_propertylist_get_int(p, GIALIAS_PSFNS);
675 }
676
677 if (cpl_propertylist_has(p, GIALIAS_PSFXBINS) == 0) {
678 return 1;
679 }
680 else {
681 nbins = cpl_propertylist_get_int(p, GIALIAS_PSFXBINS);
682 }
683
684 if (cpl_propertylist_has(p, GIALIAS_PSFPRMS) == 0) {
685 return 1;
686 }
687 else {
688 nparameters = cpl_propertylist_get_int(p, GIALIAS_PSFPRMS);
689 }
690
691 if (cpl_propertylist_has(p, GIALIAS_PSFNX) == 0) {
692 return 1;
693 }
694 else {
695 nx = cpl_propertylist_get_int(p, GIALIAS_PSFNX);
696 }
697
698 if (cpl_propertylist_has(p, GIALIAS_PSFNY) == 0) {
699 return 1;
700 }
701 else {
702 ny = cpl_propertylist_get_int(p, GIALIAS_PSFNY);
703 }
704
705 if (cpl_error_get_code() != CPL_ERROR_NONE) {
706
707 if (p != NULL) {
708 cpl_propertylist_delete(p);
709 p = NULL;
710 }
711
712 return 1;
713
714 }
715
716 giraffe_error_pop();
717
718
719 /*
720 * Prepare the psf data object. The model must be set before
721 * the property list is deallocated, since a reference is used!
722 *
723 * Note that the x-axis corresponds to the fibers, while the y-axis
724 * corresponds to the bins. Stick to OGL terminology.
725 */
726
727 giraffe_psfdata_set_model(self, model);
728 _giraffe_psfdata_resize(self, nfibers, nbins, ny, nx);
729
730 cpl_propertylist_delete(p);
731 p = NULL;
732
733
734 /*
735 * Load bin positions from the first extension.
736 */
737
738 self->bins = cpl_image_load(filename, CPL_TYPE_DOUBLE, 0, extension);
739
740 if (self->bins == NULL) {
741 _giraffe_psfdata_clear(self);
742 return 2;
743 }
744
745 if ((cpl_image_get_size_x(self->bins) != self->nfibers) ||
746 (cpl_image_get_size_y(self->bins) != self->nbins)) {
747 _giraffe_psfdata_clear(self);
748 return 2;
749 }
750
751 ++extension;
752
753 /*
754 * Load the data buffers from the nparameters following extensions.
755 * The extension labels are used as names to look up the individual
756 * parameters.
757 */
758
759 for (i = extension; i < extension + nparameters; i++) {
760
761 cpl_image* buffer = cpl_image_load(filename, CPL_TYPE_DOUBLE, 0, i);
762
763 if (buffer == NULL) {
764 _giraffe_psfdata_clear(self);
765 return 2;
766 }
767
768 if ((cpl_image_get_size_x(buffer) != self->nfibers) ||
769 (cpl_image_get_size_y(buffer) != self->nbins)) {
770
771 cpl_image_delete(buffer);
772 buffer = NULL;
773
774 _giraffe_psfdata_clear(self);
775
776 cpl_image_delete(buffer);
777 buffer = NULL;
778 return 2;
779 }
780 else {
781
782 const cxchar* name = NULL;
783
784 p = cpl_propertylist_load(filename, i);
785
786 if (p == NULL) {
787
788 cpl_image_delete(buffer);
789 buffer = NULL;
790
791 return 2;
792
793 }
794
795 if (cpl_propertylist_has(p, GIALIAS_EXTNAME) == 0) {
796
797 cpl_propertylist_delete(p);
798 p = NULL;
799
800 cpl_image_delete(buffer);
801 buffer = NULL;
802
803 return 2;
804
805 }
806
807 name = cpl_propertylist_get_string(p, GIALIAS_EXTNAME);
808 cx_map_insert(self->values, cx_strdup(name), buffer);
809
810 cpl_propertylist_delete(p);
811 p = NULL;
812
813 }
814
815 }
816
817 return 0;
818
819}
820
821
822cxint
823giraffe_psfdata_save(const GiPsfData* self, cpl_propertylist* properties,
824 const cxchar* filename, cxcptr data)
825{
826
827 const cxchar* const fctid = "giraffe_psfdata_save";
828
829 cx_map_const_iterator position;
830
831 cpl_propertylist* p = NULL;
832
833
834 /* Unused */
835 (void) data;
836
837 if (self == NULL || properties == NULL || filename == NULL) {
838 return -1;
839 }
840
841 cpl_propertylist_update_string(properties, GIALIAS_PSFMODEL,
842 self->model);
843 cpl_propertylist_update_int(properties, GIALIAS_PSFPRMS,
844 cx_map_size(self->values));
845 cpl_propertylist_update_int(properties, GIALIAS_PSFXBINS,
846 self->nbins);
847 cpl_propertylist_update_int(properties, GIALIAS_PSFNX,
848 self->height);
849 cpl_propertylist_update_int(properties, GIALIAS_PSFNY,
850 self->width);
851 cpl_propertylist_update_int(properties, GIALIAS_PSFNS,
852 self->nfibers);
853
854 cpl_propertylist_erase(properties, "BSCALE");
855 cpl_propertylist_erase(properties, "BZERO");
856 cpl_propertylist_erase(properties, "BUNIT");
857
858 cpl_propertylist_erase_regexp(properties, "^CRPIX[0-9]$", 0);
859 cpl_propertylist_erase_regexp(properties, "^CRVAL[0-9]$", 0);
860 cpl_propertylist_erase_regexp(properties, "^CDELT[0-9]$", 0);
861 cpl_propertylist_erase_regexp(properties, "^CTYPE[0-9]$", 0);
862
863 cpl_propertylist_erase_regexp(properties, "^DATA(MIN|MAX)", 0);
864
865 giraffe_error_push();
866
867
868 cpl_image_save(NULL, filename, CPL_BPP_IEEE_FLOAT,
869 properties, CPL_IO_DEFAULT);
870
871 if (cpl_error_get_code() != CPL_ERROR_NONE) {
872 return 1;
873 }
874
875 giraffe_error_pop();
876
877 p = cpl_propertylist_new();
878 cpl_propertylist_append_string(p, GIALIAS_EXTNAME, "Bin");
879 cpl_propertylist_set_comment(p, GIALIAS_EXTNAME, "FITS Extension name");
880
881 giraffe_error_push();
882
883 cpl_image_save(self->bins, filename, CPL_BPP_IEEE_FLOAT, p,
884 CPL_IO_EXTEND);
885
886 if (cpl_error_get_code() != CPL_ERROR_NONE) {
887
888 cpl_propertylist_delete(p);
889 p = NULL;
890
891 return 1;
892 }
893
894 giraffe_error_pop();
895
896 position = cx_map_begin(self->values);
897 while (position != cx_map_end(self->values)) {
898
899 cxint format = 0;
900
901 const cpl_image* psfdata = cx_map_get_value(self->values, position);
902
903
904 switch (cpl_image_get_type(psfdata)) {
905 case CPL_TYPE_INT:
906 format = CPL_BPP_32_SIGNED;
907 break;
908
909 case CPL_TYPE_FLOAT:
910 format = CPL_BPP_IEEE_FLOAT;
911 break;
912
913 case CPL_TYPE_DOUBLE:
914 format = CPL_BPP_IEEE_FLOAT;
915 break;
916
917 default:
918 cpl_propertylist_delete(p);
919 p = NULL;
920
921 cpl_error_set(fctid, CPL_ERROR_TYPE_MISMATCH);
922 return 2;
923
924 break;
925 }
926
927 giraffe_error_push();
928
929 cpl_propertylist_set_string(p, GIALIAS_EXTNAME,
930 cx_map_get_key(self->values, position));
931
932 cpl_image_save(psfdata, filename, format, p, CPL_IO_EXTEND);
933
934 if (cpl_error_get_code() != CPL_ERROR_NONE) {
935 cpl_propertylist_delete(p);
936 p = NULL;
937
938 return 2;
939 }
940
941 giraffe_error_pop();
942
943 position = cx_map_next(self->values, position);
944
945 }
946
947 cpl_propertylist_delete(p);
948 p = NULL;
949
950 return 0;
951
952}

This file is part of the GIRAFFE Pipeline Reference Manual 2.16.11.
Documentation copyright © 2002-2006 European Southern Observatory.
Generated on Wed Apr 17 2024 20:34:24 by doxygen 1.9.6 written by Dimitri van Heesch, © 1997-2004