00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
00027
00028 #ifdef HAVE_CONFIG_H
00029 # include <config.h>
00030 #endif
00031
00032 #include <string.h>
00033
00034 #include <cxtypes.h>
00035 #include <cxmemory.h>
00036 #include <cxmessages.h>
00037 #include <cxstrutils.h>
00038 #include <cxmap.h>
00039
00040 #include <cpl_type.h>
00041
00042 #include "gialias.h"
00043 #include "gierror.h"
00044 #include "gipsfdata.h"
00045
00046
00047
00048
00049
00050
00051
00052
00055 struct GiPsfData {
00056
00057 const cxchar* model;
00058
00059 cxint nfibers;
00060 cxint nbins;
00061 cxint width;
00062 cxint height;
00063
00064 cpl_image* bins;
00065 cx_map* values;
00066
00067 };
00068
00069
00070 inline static cxbool
00071 _giraffe_psfdata_compare(cxcptr s, cxcptr t)
00072 {
00073
00074 return strcmp(s, t) < 0 ? TRUE : FALSE;
00075
00076 }
00077
00078
00079 inline static void
00080 _giraffe_psfdata_clear(GiPsfData* self)
00081 {
00082
00083 if (self->model != NULL) {
00084 cx_free((cxptr)self->model);
00085 self->model = NULL;
00086 }
00087
00088 if (self->bins != NULL) {
00089 cpl_image_delete(self->bins);
00090 self->bins = NULL;
00091 }
00092
00093 if (self->values != NULL) {
00094 cx_map_clear(self->values);
00095 }
00096
00097 self->nfibers = 0;
00098 self->nbins = 0;
00099 self->width = 0;
00100 self->height = 0;
00101
00102 return;
00103
00104 }
00105
00106
00107 inline static void
00108 _giraffe_psfdata_resize(GiPsfData* self, cxint nfibers, cxint nbins,
00109 cxint width, cxint height)
00110 {
00111
00112 cx_assert(self->values != NULL);
00113
00114 self->nfibers = nfibers;
00115 self->nbins = nbins;
00116 self->width = width;
00117 self->height = height;
00118
00119 if (self->bins != NULL) {
00120 cpl_image_delete(self->bins);
00121 self->bins = NULL;
00122 }
00123
00124 if (cx_map_empty(self->values) == FALSE) {
00125 cx_map_clear(self->values);
00126 cx_assert(cx_map_empty(self->values));
00127 }
00128
00129 return;
00130
00131 }
00132
00133
00134 inline static cxint
00135 _giraffe_psfdata_assign(GiPsfData* self, cx_map* map, const cxchar* name,
00136 const cpl_image* values)
00137 {
00138
00139 cx_map_iterator position = cx_map_find(map, name);
00140
00141
00142 if (cpl_image_get_size_x(values) != self->nfibers) {
00143 return 1;
00144 }
00145
00146 if (cpl_image_get_size_y(values) != self->nbins) {
00147 return 2;
00148 }
00149
00150 if (position == cx_map_end(map)) {
00151 cx_map_insert(map, cx_strdup(name), values);
00152 }
00153 else {
00154
00155 cpl_image* previous = cx_map_assign(map, position, values);
00156
00157 if (previous != NULL) {
00158 cpl_image_delete(previous);
00159 previous = NULL;
00160 }
00161
00162 }
00163
00164 return 0;
00165
00166 }
00167
00168
00169 inline static cxint
00170 _giraffe_psfdata_set(GiPsfData* self, cx_map* map, const cxchar* name,
00171 cxint i, cxint j, cxdouble value)
00172 {
00173
00174 cxdouble* data = NULL;
00175
00176 cx_map_const_iterator position = cx_map_find(map, name);
00177
00178
00179 if (position == cx_map_end(map)) {
00180
00181 cpl_image* buffer = cpl_image_new(self->nfibers, self->nbins,
00182 CPL_TYPE_DOUBLE);
00183 cx_map_insert(map, cx_strdup(name), buffer);
00184
00185 data = cpl_image_get_data(buffer);
00186
00187 }
00188 else {
00189
00190 data = cpl_image_get_data(cx_map_get_value(map, position));
00191
00192 }
00193
00194 data[self->nfibers * j + i] = value;
00195
00196 return 0;
00197
00198 }
00199
00200
00201 inline static cxint
00202 _giraffe_psfdata_get(const GiPsfData* self, const cx_map* map,
00203 const cxchar* name, cxint i, cxint j, cxdouble* value)
00204 {
00205
00206 cxdouble* data = NULL;
00207
00208 cx_map_const_iterator position = cx_map_find(map, name);
00209
00210 if (position == cx_map_end(map)) {
00211 return 1;
00212 }
00213
00214 data = cpl_image_get_data(cx_map_get_value(map, position));
00215 *value = data[self->nfibers * j + i];
00216
00217 return 0;
00218
00219 }
00220
00221
00222 GiPsfData*
00223 giraffe_psfdata_new(void)
00224 {
00225
00226 GiPsfData* self = cx_calloc(1, sizeof *self);
00227
00228 self->nfibers = 0;
00229 self->nbins = 0;
00230 self->width = 0;
00231 self->height = 0;
00232
00233 self->model = NULL;
00234
00235 self->bins = NULL;
00236 self->values = cx_map_new(_giraffe_psfdata_compare, cx_free,
00237 (cx_free_func)cpl_image_delete);
00238 cx_assert(cx_map_empty(self->values));
00239
00240 return self;
00241
00242 }
00243
00244
00245 GiPsfData*
00246 giraffe_psfdata_create(cxint nfibers, cxint nbins, cxint width, cxint height)
00247 {
00248
00249 GiPsfData* self = giraffe_psfdata_new();
00250
00251 self->nfibers = nfibers;
00252 self->nbins = nbins;
00253 self->width = width;
00254 self->height = height;
00255
00256 self->model = NULL;
00257
00258 self->bins = cpl_image_new(self->nfibers, self->nbins, CPL_TYPE_DOUBLE);
00259 self->values = cx_map_new(_giraffe_psfdata_compare, cx_free,
00260 (cx_free_func)cpl_image_delete);
00261 cx_assert(cx_map_empty(self->values));
00262
00263 return self;
00264
00265 }
00266
00267
00268 void
00269 giraffe_psfdata_delete(GiPsfData* self)
00270 {
00271
00272 if (self != NULL) {
00273
00274 if (self->model != NULL) {
00275 cx_free((cxptr)self->model);
00276 self->model = NULL;
00277 }
00278
00279 if (self->bins != NULL) {
00280 cpl_image_delete(self->bins);
00281 self->bins = NULL;
00282 }
00283
00284 if (self->values != NULL) {
00285 cx_map_delete(self->values);
00286 self->values = NULL;
00287 }
00288
00289 cx_free(self);
00290
00291 }
00292
00293 return;
00294
00295 }
00296
00297
00298 void
00299 giraffe_psfdata_clear(GiPsfData* self)
00300 {
00301 _giraffe_psfdata_clear(self);
00302 return;
00303 }
00304
00305
00306 void
00307 giraffe_psfdata_resize(GiPsfData* self, cxint nfibers, cxint nbins,
00308 cxint width, cxint height)
00309 {
00310
00311 cx_assert(self != NULL);
00312
00313 _giraffe_psfdata_resize(self, nfibers, nbins, width, height);
00314 self->bins = cpl_image_new(self->nfibers, self->nbins, CPL_TYPE_DOUBLE);
00315
00316 return;
00317
00318 }
00319
00320
00321 cxsize
00322 giraffe_psfdata_fibers(const GiPsfData* self)
00323 {
00324
00325 cx_assert(self != NULL);
00326 return self->nfibers;
00327
00328 }
00329
00330
00331 cxsize
00332 giraffe_psfdata_bins(const GiPsfData* self)
00333 {
00334
00335 cx_assert(self != NULL);
00336 return self->nbins;
00337
00338 }
00339
00340
00341 cxsize
00342 giraffe_psfdata_xsize(const GiPsfData* self)
00343 {
00344
00345 cx_assert(self != NULL);
00346 return self->width;
00347
00348 }
00349
00350
00351 cxsize
00352 giraffe_psfdata_ysize(const GiPsfData* self)
00353 {
00354
00355 cx_assert(self != NULL);
00356 return self->height;
00357
00358 }
00359
00360
00361 cxsize
00362 giraffe_psfdata_parameters(const GiPsfData* self)
00363 {
00364
00365 cx_assert(self != NULL);
00366 return cx_map_size(self->values);
00367
00368 }
00369
00370
00371 cxbool
00372 giraffe_psfdata_contains(const GiPsfData* self, const cxchar* name)
00373 {
00374
00375 cx_map_const_iterator position;
00376
00377
00378 cx_assert(self != NULL);
00379
00380 if (name == NULL) {
00381 return FALSE;
00382 }
00383
00384 position = cx_map_find(self->values, name);
00385
00386 if (position == cx_map_end(self->values)) {
00387 return FALSE;
00388 }
00389
00390 return TRUE;
00391
00392 }
00393
00394
00395 const cxchar*
00396 giraffe_psfdata_get_name(const GiPsfData* self, cxsize position)
00397 {
00398
00399 const cxchar* name = NULL;
00400
00401
00402 cx_assert(self != NULL);
00403
00404 if (position < cx_map_size(self->values)) {
00405
00406 cxsize i = 0;
00407
00408 cx_map_const_iterator pos = cx_map_begin(self->values);
00409
00410
00411 while (i < position) {
00412 pos = cx_map_next(self->values, pos);
00413 ++i;
00414 }
00415
00416 name = cx_map_get_key(self->values, pos);
00417
00418 }
00419
00420 return name;
00421
00422 }
00423
00424
00425 cxint
00426 giraffe_psfdata_set_model(GiPsfData* self, const cxchar* name)
00427 {
00428
00429 cx_assert(self != NULL);
00430
00431 if (name == NULL) {
00432 return 1;
00433 }
00434
00435 if (self->model != NULL) {
00436 cx_free((cxptr)self->model);
00437 self->model = NULL;
00438 }
00439
00440 self->model = cx_strdup(name);
00441
00442 return 0;
00443
00444 }
00445
00446
00447 const cxchar*
00448 giraffe_psfdata_get_model(const GiPsfData* self)
00449 {
00450
00451 cx_assert(self != NULL);
00452 return self->model;
00453
00454 }
00455
00456
00457 cxint
00458 giraffe_psfdata_set_bin(GiPsfData* self, cxint fiber, cxint bin,
00459 cxdouble position)
00460 {
00461
00462 cxdouble* data = NULL;
00463
00464
00465 cx_assert(self != NULL);
00466
00467 if ((fiber < 0) || (fiber >= self->nfibers) ||
00468 (bin < 0) || (bin >= self->nbins)) {
00469 return 1;
00470 }
00471 else {
00472
00473 if (self->bins == NULL) {
00474 self->bins = cpl_image_new(self->nfibers, self->nbins,
00475 CPL_TYPE_DOUBLE);
00476 }
00477
00478 data = cpl_image_get_data_double(self->bins);
00479 data[self->nfibers * bin + fiber] = position;
00480
00481 }
00482
00483 return 0;
00484
00485 }
00486
00487
00488 cxdouble
00489 giraffe_psfdata_get_bin(const GiPsfData* self, cxint fiber, cxint bin)
00490 {
00491
00492 const cxchar* const fctid = "giraffe_psfdata_get_bin";
00493
00494 cxdouble* data = NULL;
00495
00496
00497 cx_assert(self != NULL);
00498
00499 if ((fiber < 0) || (fiber >= self->nfibers) ||
00500 (bin < 0) || (bin >= self->nbins)) {
00501 cpl_error_set(fctid, CPL_ERROR_ILLEGAL_INPUT);
00502 return 0.;
00503 }
00504
00505 if (self->bins == NULL) {
00506
00507 GiPsfData* _self = (GiPsfData*) self;
00508
00509 _self->bins = cpl_image_new(self->nfibers, self->nbins,
00510 CPL_TYPE_DOUBLE);
00511
00512 }
00513
00514 data = cpl_image_get_data_double(self->bins);
00515
00516 return data[self->nfibers * bin + fiber];
00517
00518 }
00519
00520
00521 const cpl_image*
00522 giraffe_psfdata_get_bins(const GiPsfData* self)
00523 {
00524 cx_assert(self != NULL);
00525 return self->bins;
00526 }
00527
00528
00529 cxint
00530 giraffe_psfdata_set(GiPsfData* self, const cxchar* name, cxint fiber,
00531 cxint bin, cxdouble value)
00532 {
00533
00534 cxint status = 0;
00535
00536 cx_assert(self != NULL);
00537
00538 if (name == NULL) {
00539 return 1;
00540 }
00541
00542 if (fiber >= self->nfibers) {
00543 return 1;
00544 }
00545
00546 if (bin >= self->nbins) {
00547 return 1;
00548 }
00549
00550 status = _giraffe_psfdata_set(self, self->values, name, fiber, bin,
00551 value);
00552
00553 if (status != 0) {
00554 return 1;
00555 }
00556
00557 return 0;
00558
00559 }
00560
00561
00562 cxdouble
00563 giraffe_psfdata_get(const GiPsfData* self, const cxchar* name, cxint fiber,
00564 cxint bin)
00565 {
00566
00567 const cxchar* const fctid = "giraffe_psfdata_get";
00568
00569 cxint status = 0;
00570
00571 cxdouble value = 0.;
00572
00573
00574 cx_assert(self != NULL);
00575
00576 if (name == NULL) {
00577 return 1;
00578 }
00579
00580 if (fiber >= self->nfibers) {
00581 return 1;
00582 }
00583
00584 if (bin >= self->nbins) {
00585 return 1;
00586 }
00587
00588 status = _giraffe_psfdata_get(self, self->values, name, fiber, bin,
00589 &value);
00590
00591 if (status != 0) {
00592 cpl_error_set(fctid, CPL_ERROR_DATA_NOT_FOUND);
00593 return 0.;
00594 }
00595
00596 return value;
00597
00598 }
00599
00600
00601 cxint
00602 giraffe_psfdata_set_data(GiPsfData* self, const cxchar* name,
00603 const cpl_image* data)
00604 {
00605
00606 cxint status = 0;
00607
00608
00609 cx_assert(self != NULL);
00610
00611 if (name == NULL) {
00612 return 1;
00613 }
00614
00615 if (data == NULL) {
00616 return 1;
00617 }
00618
00619 status = _giraffe_psfdata_assign(self, self->values, name, data);
00620
00621 if (status != 0) {
00622 return 1;
00623 }
00624
00625 return 0;
00626
00627 }
00628
00629
00630 const cpl_image*
00631 giraffe_psfdata_get_data(const GiPsfData* self, const cxchar* name)
00632 {
00633
00634 cx_assert(self != NULL);
00635
00636 if (name == NULL) {
00637 return NULL;
00638 }
00639
00640 return cx_map_get(self->values, name);
00641
00642 }
00643
00644
00645 cxint giraffe_psfdata_load(GiPsfData* self, const cxchar* filename)
00646 {
00647
00648 const cxchar* model = NULL;
00649
00650 cxint nfibers = 0;
00651 cxint nbins = 0;
00652 cxint nx = 0;
00653 cxint ny = 0;
00654 cxint nparameters = 0;
00655
00656 cxsize i = 0;
00657 cxsize extension = 1;
00658
00659 cpl_propertylist* p = NULL;
00660
00661
00662 if (self == NULL || filename == NULL) {
00663 return -1;
00664 }
00665
00666 giraffe_error_push();
00667
00668 p = cpl_propertylist_load(filename, 0);
00669
00670 if (p == NULL) {
00671 return 1;
00672 }
00673
00674 if (cpl_propertylist_has(p, GIALIAS_PSFMODEL) == 0) {
00675 return 1;
00676 }
00677 else {
00678 model = cpl_propertylist_get_string(p, GIALIAS_PSFMODEL);
00679 }
00680
00681 if (cpl_propertylist_has(p, GIALIAS_PSFNS) == 0) {
00682 return 1;
00683 }
00684 else {
00685 nfibers = cpl_propertylist_get_int(p, GIALIAS_PSFNS);
00686 }
00687
00688 if (cpl_propertylist_has(p, GIALIAS_PSFXBINS) == 0) {
00689 return 1;
00690 }
00691 else {
00692 nbins = cpl_propertylist_get_int(p, GIALIAS_PSFXBINS);
00693 }
00694
00695 if (cpl_propertylist_has(p, GIALIAS_PSFPRMS) == 0) {
00696 return 1;
00697 }
00698 else {
00699 nparameters = cpl_propertylist_get_int(p, GIALIAS_PSFPRMS);
00700 }
00701
00702 if (cpl_propertylist_has(p, GIALIAS_PSFNX) == 0) {
00703 return 1;
00704 }
00705 else {
00706 nx = cpl_propertylist_get_int(p, GIALIAS_PSFNX);
00707 }
00708
00709 if (cpl_propertylist_has(p, GIALIAS_PSFNY) == 0) {
00710 return 1;
00711 }
00712 else {
00713 ny = cpl_propertylist_get_int(p, GIALIAS_PSFNY);
00714 }
00715
00716 if (cpl_error_get_code() != CPL_ERROR_NONE) {
00717
00718 if (p != NULL) {
00719 cpl_propertylist_delete(p);
00720 p = NULL;
00721 }
00722
00723 return 1;
00724
00725 }
00726
00727 giraffe_error_pop();
00728
00729
00730
00731
00732
00733
00734
00735
00736
00737
00738 giraffe_psfdata_set_model(self, model);
00739 _giraffe_psfdata_resize(self, nfibers, nbins, ny, nx);
00740
00741 cpl_propertylist_delete(p);
00742 p = NULL;
00743
00744
00745
00746
00747
00748
00749 self->bins = cpl_image_load(filename, CPL_TYPE_DOUBLE, 0, extension);
00750
00751 if (self->bins == NULL) {
00752 _giraffe_psfdata_clear(self);
00753 return 2;
00754 }
00755
00756 if ((cpl_image_get_size_x(self->bins) != self->nfibers) ||
00757 (cpl_image_get_size_y(self->bins) != self->nbins)) {
00758 _giraffe_psfdata_clear(self);
00759 return 2;
00760 }
00761
00762 ++extension;
00763
00764
00765
00766
00767
00768
00769
00770 for (i = extension; i < extension + nparameters; i++) {
00771
00772 cpl_image* buffer = cpl_image_load(filename, CPL_TYPE_DOUBLE, 0, i);
00773
00774 if (buffer == NULL) {
00775 _giraffe_psfdata_clear(self);
00776 return 2;
00777 }
00778
00779 if ((cpl_image_get_size_x(buffer) != self->nfibers) ||
00780 (cpl_image_get_size_y(buffer) != self->nbins)) {
00781 _giraffe_psfdata_clear(self);
00782 return 2;
00783 }
00784 else {
00785
00786 const cxchar* name = NULL;
00787
00788 p = cpl_propertylist_load(filename, i);
00789
00790 if (p == NULL) {
00791
00792 cpl_image_delete(buffer);
00793 buffer = NULL;
00794
00795 return 2;
00796
00797 }
00798
00799 if (cpl_propertylist_has(p, GIALIAS_EXTNAME) == 0) {
00800
00801 cpl_propertylist_delete(p);
00802 p = NULL;
00803
00804 cpl_image_delete(buffer);
00805 buffer = NULL;
00806
00807 return 2;
00808
00809 }
00810
00811 name = cpl_propertylist_get_string(p, GIALIAS_EXTNAME);
00812 cx_map_insert(self->values, cx_strdup(name), buffer);
00813
00814 cpl_propertylist_delete(p);
00815 p = NULL;
00816
00817 }
00818
00819 }
00820
00821 return 0;
00822
00823 }
00824
00825
00826 cxint
00827 giraffe_psfdata_save(const GiPsfData* self, cpl_propertylist* properties,
00828 const cxchar* filename, cxcptr data)
00829 {
00830
00831 const cxchar* const fctid = "giraffe_psfdata_save";
00832
00833 cx_map_const_iterator position;
00834
00835 cpl_propertylist* p = NULL;
00836
00837
00838
00839 data = NULL;
00840
00841 if (self == NULL || properties == NULL || filename == NULL) {
00842 return -1;
00843 }
00844
00845 cpl_propertylist_update_string(properties, GIALIAS_PSFMODEL,
00846 self->model);
00847 cpl_propertylist_update_int(properties, GIALIAS_PSFPRMS,
00848 cx_map_size(self->values));
00849 cpl_propertylist_update_int(properties, GIALIAS_PSFXBINS,
00850 self->nbins);
00851 cpl_propertylist_update_int(properties, GIALIAS_PSFNX,
00852 self->height);
00853 cpl_propertylist_update_int(properties, GIALIAS_PSFNY,
00854 self->width);
00855 cpl_propertylist_update_int(properties, GIALIAS_PSFNS,
00856 self->nfibers);
00857
00858 giraffe_error_push();
00859
00860 cpl_image_save(NULL, filename, CPL_BPP_IEEE_FLOAT,
00861 properties, CPL_IO_DEFAULT);
00862
00863 if (cpl_error_get_code() != CPL_ERROR_NONE) {
00864 return 1;
00865 }
00866
00867 giraffe_error_pop();
00868
00869 p = cpl_propertylist_new();
00870 cpl_propertylist_append_string(p, GIALIAS_EXTNAME, "Bin");
00871 cpl_propertylist_set_comment(p, GIALIAS_EXTNAME, "FITS Extension name");
00872
00873 giraffe_error_push();
00874
00875 cpl_image_save(self->bins, filename, CPL_BPP_IEEE_FLOAT, p,
00876 CPL_IO_EXTEND);
00877
00878 if (cpl_error_get_code() != CPL_ERROR_NONE) {
00879
00880 cpl_propertylist_delete(p);
00881 p = NULL;
00882
00883 return 1;
00884 }
00885
00886 giraffe_error_pop();
00887
00888 position = cx_map_begin(self->values);
00889 while (position != cx_map_end(self->values)) {
00890
00891 cxint format = 0;
00892
00893 const cpl_image* psfdata = cx_map_get_value(self->values, position);
00894
00895
00896 switch (cpl_image_get_type(psfdata)) {
00897 case CPL_TYPE_INT:
00898 format = CPL_BPP_32_SIGNED;
00899 break;
00900
00901 case CPL_TYPE_FLOAT:
00902 format = CPL_BPP_IEEE_FLOAT;
00903 break;
00904
00905 case CPL_TYPE_DOUBLE:
00906 format = CPL_BPP_IEEE_FLOAT;
00907 break;
00908
00909 default:
00910 cpl_propertylist_delete(p);
00911 p = NULL;
00912
00913 cpl_error_set(fctid, CPL_ERROR_TYPE_MISMATCH);
00914 return 2;
00915
00916 break;
00917 }
00918
00919 giraffe_error_push();
00920
00921 cpl_propertylist_set_string(p, GIALIAS_EXTNAME,
00922 cx_map_get_key(self->values, position));
00923
00924 cpl_image_save(psfdata, filename, format, p, CPL_IO_EXTEND);
00925
00926 if (cpl_error_get_code() != CPL_ERROR_NONE) {
00927 cpl_propertylist_delete(p);
00928 p = NULL;
00929
00930 return 2;
00931 }
00932
00933 giraffe_error_pop();
00934
00935 position = cx_map_next(self->values, position);
00936
00937 }
00938
00939 cpl_propertylist_delete(p);
00940 p = NULL;
00941
00942 return 0;
00943
00944 }