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 <cxmap.h>
00033 #include <cxstring.h>
00034 #include <cxstrutils.h>
00035
00036 #include <cpl_error.h>
00037 #include <cpl_propertylist.h>
00038
00039 #include "gialias.h"
00040 #include "gitable.h"
00041 #include "gierror.h"
00042 #include "gichebyshev.h"
00043 #include "giwlresiduals.h"
00044
00045
00054 struct GiWlResidualData {
00055
00056 cxint ssn;
00057 GiChebyshev2D *fit;
00058
00059 };
00060
00061 typedef struct GiWlResidualData GiWlResidualData;
00062
00063
00064 struct GiWlResiduals {
00065
00066 cx_map *data;
00067
00068 };
00069
00070
00071 inline static cxint
00072 _giraffe_compare_int(cxcptr first, cxcptr second)
00073 {
00074
00075 cxint *_first = (cxint *)first;
00076 cxint *_second = (cxint *)second;
00077
00078 return *_first - *_second;
00079
00080 }
00081
00082
00083 inline static void
00084 _giraffe_wlresidualdata_delete(GiWlResidualData *self)
00085 {
00086
00087 if (self) {
00088
00089 if (self->fit) {
00090 giraffe_chebyshev2d_delete(self->fit);
00091 }
00092
00093 cx_free(self);
00094
00095 }
00096
00097 return;
00098
00099 }
00100
00101
00102 inline static GiWlResidualData *
00103 _giraffe_wlresiduals_get(const GiWlResiduals *self, cxsize idx)
00104 {
00105
00106 cx_map_const_iterator position;
00107
00108 GiWlResidualData *data = NULL;
00109
00110
00111 position = cx_map_begin(self->data);
00112
00113 if (position == cx_map_end(self->data)) {
00114 return NULL;
00115 }
00116
00117 if (idx > 0) {
00118
00119 cxsize i;
00120
00121 for (i = 1; i < idx; i++) {
00122 position = cx_map_next(self->data, position);
00123 }
00124
00125 }
00126
00127 data = cx_map_get_value(self->data, position);
00128
00129 return data;
00130
00131 }
00132
00133
00134 inline static void
00135 _giraffe_wlresiduals_insert(GiWlResiduals *self, cxint ssn,
00136 const GiChebyshev2D *fit)
00137 {
00138
00139 GiWlResidualData *data = cx_calloc(1, sizeof *data);
00140
00141
00142 data->ssn = ssn;
00143 data->fit = (GiChebyshev2D *)fit;
00144
00145 cx_map_insert(self->data, &data->ssn, data);
00146
00147 return;
00148
00149 }
00150
00151
00152 GiWlResiduals *
00153 giraffe_wlresiduals_new(void)
00154 {
00155
00156 GiWlResiduals *self = cx_calloc(1, sizeof *self);
00157
00158 if (self) {
00159
00160 self->data = cx_map_new(_giraffe_compare_int, NULL,
00161 (cx_free_func)_giraffe_wlresidualdata_delete);
00162 cx_assert(cx_map_empty(self->data));
00163
00164 }
00165
00166 return self;
00167
00168 }
00169
00170
00171 GiWlResiduals *
00172 giraffe_wlresiduals_clone(const GiWlResiduals *other)
00173 {
00174
00175 GiWlResiduals *self = NULL;
00176
00177
00178 if (other != NULL) {
00179
00180 self = giraffe_wlresiduals_new();
00181
00182 if (!cx_map_empty(other->data)) {
00183
00184 cx_map_const_iterator position = cx_map_begin(other->data);
00185
00186
00187 while (position != cx_map_end(other->data)) {
00188
00189 GiWlResidualData *data = cx_map_get_value(other->data,
00190 position);
00191
00192 GiChebyshev2D *fit = giraffe_chebyshev2d_clone(data->fit);
00193
00194
00195 _giraffe_wlresiduals_insert(self, data->ssn, fit);
00196
00197 position = cx_map_next(other->data, position);
00198
00199 }
00200
00201 }
00202
00203 cx_assert(cx_map_size(self->data) == cx_map_size(other->data));
00204
00205 }
00206
00207 return self;
00208
00209 }
00210
00211
00212 GiWlResiduals *
00213 giraffe_wlresiduals_create(GiTable *wlsolution)
00214 {
00215
00216 const cxchar *const fctid = "giraffe_wlresiduals_create";
00217
00218
00219 cpl_propertylist *properties = NULL;
00220
00221 cpl_table *residuals = NULL;
00222
00223 GiWlResiduals *self = giraffe_wlresiduals_new();
00224
00225
00226 if (wlsolution == NULL) {
00227
00228 cpl_error_set(fctid, CPL_ERROR_DATA_NOT_FOUND);
00229 giraffe_wlresiduals_delete(self);
00230
00231 return NULL;
00232
00233 }
00234
00235 properties = giraffe_table_get_properties(wlsolution);
00236
00237 if (properties == NULL) {
00238
00239 cpl_error_set(fctid, CPL_ERROR_DATA_NOT_FOUND);
00240 giraffe_wlresiduals_delete(self);
00241
00242 return NULL;
00243 }
00244
00245 residuals = giraffe_table_get(wlsolution);
00246
00247 if (residuals == NULL) {
00248
00249 cpl_error_set(fctid, CPL_ERROR_DATA_NOT_FOUND);
00250 giraffe_wlresiduals_delete(self);
00251
00252 return NULL;
00253 }
00254
00255 if (!cpl_table_has_column(residuals, "XMIN") ||
00256 !cpl_table_has_column(residuals, "XMAX") ||
00257 !cpl_table_has_column(residuals, "YMIN") ||
00258 !cpl_table_has_column(residuals, "YMAX")) {
00259
00260
00261
00262
00263
00264
00265 cpl_table_new_column(residuals, "XMIN", CPL_TYPE_DOUBLE);
00266 cpl_table_new_column(residuals, "XMAX", CPL_TYPE_DOUBLE);
00267 cpl_table_new_column(residuals, "YMIN", CPL_TYPE_DOUBLE);
00268 cpl_table_new_column(residuals, "YMAX", CPL_TYPE_DOUBLE);
00269
00270 cpl_table_set_double(residuals, "XMIN", 0, 0.);
00271 cpl_table_set_double(residuals, "XMAX", 0, 4096.);
00272 cpl_table_set_double(residuals, "YMIN", 0, 0.);
00273 cpl_table_set_double(residuals, "YMAX", 0, 2048.);
00274
00275 }
00276
00277
00278
00279 if (1) {
00280
00281 cxint i;
00282 cxint xorder = 0;
00283 cxint yorder = 0;
00284 cxint nc = 0;
00285
00286 cx_string *label = NULL;
00287
00288 cpl_matrix *coeffs = NULL;
00289
00290
00291 if (!cpl_propertylist_has(properties, GIALIAS_WSOL_XRORDER)) {
00292
00293 cpl_error_set(fctid, CPL_ERROR_ILLEGAL_INPUT);
00294 giraffe_wlresiduals_delete(self);
00295
00296 return NULL;
00297
00298 }
00299 else {
00300
00301
00302 const cxchar *s =
00303 cpl_propertylist_get_string(properties, GIALIAS_WSOL_XRORDER);
00304
00305 cxchar **orders = cx_strsplit(s, ":", 3);
00306
00307 if (orders[1] == NULL) {
00308
00309 cpl_error_set(fctid, CPL_ERROR_ILLEGAL_INPUT);
00310 giraffe_wlresiduals_delete(self);
00311 cx_strfreev(orders);
00312
00313 return NULL;
00314 }
00315
00316 xorder = strtol(orders[0], NULL, 10);
00317 yorder = strtol(orders[1], NULL, 10);
00318
00319 cx_strfreev(orders);
00320
00321 }
00322
00323
00324 nc = (xorder + 1) * (yorder + 1);
00325
00326 label = cx_string_new();
00327 coeffs = cpl_matrix_new(xorder + 1, yorder + 1);
00328
00329
00330 for (i = 0; i < cpl_table_get_nrow(residuals); i++) {
00331
00332 cxint j;
00333 cxint l = 0;
00334 cxint ssn = cpl_table_get_int(residuals, "SSN", i, NULL);
00335
00336 cxdouble ax = cpl_table_get(residuals, "XMIN", i, NULL);
00337 cxdouble bx = cpl_table_get(residuals, "XMAX", i, NULL);
00338 cxdouble ay = cpl_table_get(residuals, "YMIN", i, NULL);
00339 cxdouble by = cpl_table_get(residuals, "YMAX", i, NULL);
00340
00341 GiChebyshev2D *fit = NULL;
00342
00343
00344 for (j = 0; j <= xorder; j++) {
00345
00346 cxint k;
00347
00348 for (k = 0; k <= yorder; k++) {
00349
00350 cxdouble coeff = 0.;
00351
00352 cx_string_sprintf(label, "XC%-d", l);
00353 coeff = cpl_table_get(residuals, cx_string_get(label),
00354 i, NULL);
00355
00356 cpl_matrix_set(coeffs, j, k, coeff);
00357 ++l;
00358
00359 }
00360
00361 }
00362
00363 fit = giraffe_chebyshev2d_new(xorder, yorder);
00364 giraffe_chebyshev2d_set(fit, ax, bx, ay, by, coeffs);
00365
00366 _giraffe_wlresiduals_insert(self, ssn, fit);
00367
00368 }
00369
00370 cpl_matrix_delete(coeffs);
00371 cx_string_delete(label);
00372
00373 }
00374
00375 return self;
00376
00377 }
00378
00379
00380 void
00381 giraffe_wlresiduals_delete(GiWlResiduals *self)
00382 {
00383
00384 if (self) {
00385
00386 if (self->data != NULL) {
00387 cx_map_delete(self->data);
00388 }
00389
00390 cx_free(self);
00391
00392 }
00393
00394 return;
00395
00396 }
00397
00398
00399 cxsize
00400 giraffe_wlresiduals_get_size(const GiWlResiduals *self)
00401 {
00402
00403 cx_assert(self != NULL);
00404
00405 return cx_map_size(self->data);
00406
00407 }
00408
00409
00410 cxint
00411 giraffe_wlresiduals_get_subslit(const GiWlResiduals *self, cxsize idx)
00412 {
00413
00414 const GiWlResidualData *data = NULL;
00415
00416
00417 cx_assert(self != NULL);
00418
00419 data = _giraffe_wlresiduals_get(self, idx);
00420
00421 if (data == NULL) {
00422 return -1;
00423 }
00424
00425 return data->ssn;
00426
00427 }
00428
00429
00430 GiChebyshev2D *
00431 giraffe_wlresiduals_get_element(const GiWlResiduals *self, cxsize idx)
00432 {
00433
00434 const GiWlResidualData *data = NULL;
00435
00436
00437 cx_assert(self != NULL);
00438
00439 data = _giraffe_wlresiduals_get(self, idx);
00440
00441 if (data == NULL) {
00442 return NULL;
00443 }
00444
00445 return data->fit;
00446
00447 }
00448
00449
00450 cxint
00451 giraffe_wlresiduals_set(GiWlResiduals *self, cxint ssn,
00452 const GiChebyshev2D *residuals)
00453 {
00454
00455 cx_assert(self != NULL);
00456
00457 if (residuals == NULL) {
00458 return 1;
00459 }
00460
00461 cx_map_erase(self->data, &ssn);
00462 _giraffe_wlresiduals_insert(self, ssn , residuals);
00463
00464 return 0;
00465
00466 }
00467
00468 GiChebyshev2D *
00469 giraffe_wlresiduals_get(const GiWlResiduals *self, cxint ssn)
00470 {
00471
00472 const GiWlResidualData *data = NULL;
00473
00474
00475 cx_assert(self != NULL);
00476
00477 data = cx_map_get(self->data, &ssn);
00478 return data->fit;
00479
00480 }
00481
00482
00483 cpl_table *
00484 giraffe_wlresiduals_table(const GiWlResiduals *self)
00485 {
00486
00487 const cxchar *label = "SSN";
00488
00489 cxint i = 0;
00490 cxint xorder = 0;
00491 cxint yorder = 0;
00492 cxint ncoeff = 0;
00493
00494 cx_string *s = NULL;
00495
00496 cx_map_const_iterator position;
00497
00498 cpl_propertylist *sorting_order = NULL;
00499
00500 cpl_table *residuals = NULL;
00501
00502 const GiWlResidualData *data = NULL;
00503
00504
00505 cx_assert(self != NULL);
00506
00507 if (cx_map_empty(self->data)) {
00508 return NULL;
00509 }
00510
00511 position = cx_map_begin(self->data);
00512
00513 data = cx_map_get_value(self->data, position);
00514 cx_assert(data != NULL);
00515
00516 giraffe_chebyshev2d_get_order(data->fit, &xorder, &yorder);
00517 ncoeff = (xorder + 1) * (yorder + 1);
00518
00519
00520 residuals = cpl_table_new(cx_map_size(self->data));
00521
00522 s = cx_string_new();
00523
00524 giraffe_error_push();
00525
00526 cpl_table_new_column(residuals, label, CPL_TYPE_INT);
00527
00528 cpl_table_new_column(residuals, "XMIN", CPL_TYPE_DOUBLE);
00529 cpl_table_new_column(residuals, "XMAX", CPL_TYPE_DOUBLE);
00530 cpl_table_new_column(residuals, "YMIN", CPL_TYPE_DOUBLE);
00531 cpl_table_new_column(residuals, "YMAX", CPL_TYPE_DOUBLE);
00532
00533
00534 for (i = 0; i < ncoeff; i++) {
00535
00536 cx_string_sprintf(s, "XC%-d", i);
00537 cpl_table_new_column(residuals, cx_string_get(s), CPL_TYPE_DOUBLE);
00538
00539 }
00540
00541 if (cpl_error_get_code() != CPL_ERROR_NONE) {
00542
00543 cpl_table_delete(residuals);
00544 cx_string_delete(s);
00545
00546 return NULL;
00547 }
00548
00549 giraffe_error_pop();
00550
00551
00552 i = 0;
00553
00554 while (position != cx_map_end(self->data)) {
00555
00556 cxint ssn = 0;
00557
00558 cxsize j;
00559 cxsize l = 0;
00560 cxsize nx = 0;
00561 cxsize ny = 0;
00562
00563 cxdouble ax = 0.;
00564 cxdouble bx = 0.;
00565 cxdouble ay = 0.;
00566 cxdouble by = 0.;
00567
00568 cpl_matrix *_coeffs = NULL;
00569
00570 const GiChebyshev2D *fit = NULL;
00571
00572
00573 data = cx_map_get_value(self->data, position);
00574
00575 ssn = data->ssn;
00576
00577 fit = data->fit;
00578 cx_assert(fit != NULL);
00579
00580 _coeffs = (cpl_matrix *)giraffe_chebyshev2d_coeffs(fit);
00581 giraffe_chebyshev2d_get_range(fit, &ax, &bx, &ay, &by);
00582
00583 cpl_table_set_int(residuals, label, i , ssn);
00584
00585 cpl_table_set_double(residuals, "XMIN", i, ax);
00586 cpl_table_set_double(residuals, "XMAX", i, bx);
00587 cpl_table_set_double(residuals, "YMIN", i, ay);
00588 cpl_table_set_double(residuals, "YMAX", i, by);
00589
00590 nx = cpl_matrix_get_nrow(_coeffs);
00591 ny = cpl_matrix_get_ncol(_coeffs);
00592
00593 cx_assert(nx * ny == (cxsize)((xorder + 1) * (yorder + 1)));
00594
00595 for (j = 0; (cxsize)j < nx; j++) {
00596
00597 cxint k;
00598
00599 for (k = 0; (cxsize)k < ny; k++) {
00600
00601 cxdouble value = cpl_matrix_get(_coeffs, j, k);
00602
00603 cx_string_sprintf(s, "XC%-" CX_PRINTF_FORMAT_SIZE_TYPE, l);
00604 cpl_table_set_double(residuals, cx_string_get(s), i, value);
00605 ++l;
00606
00607 }
00608
00609 }
00610
00611 position = cx_map_next(self->data, position);
00612 ++i;
00613
00614 }
00615
00616 cx_string_delete(s);
00617 s = NULL;
00618
00619 sorting_order = cpl_propertylist_new();
00620 cpl_propertylist_append_bool(sorting_order, label, 0);
00621
00622 cpl_table_sort(residuals, sorting_order);
00623
00624 cpl_propertylist_delete(sorting_order);
00625 sorting_order = NULL;
00626
00627 return residuals;
00628
00629 }