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 <stdlib.h>
00033 #include <math.h>
00034
00035 #include <cxmap.h>
00036 #include <cxstring.h>
00037 #include <cxstrutils.h>
00038
00039 #include <cpl_error.h>
00040 #include <cpl_propertylist.h>
00041
00042 #include "gialias.h"
00043 #include "gierror.h"
00044 #include "giimage.h"
00045 #include "gitable.h"
00046 #include "gichebyshev.h"
00047 #include "giwlsolution.h"
00048
00049
00058 struct GiWlSolution {
00059
00060 GiModel *model;
00061
00062 cxbool subslits;
00063 GiWlResiduals *residuals;
00064
00065 };
00066
00067
00068 inline static GiWlSolution *
00069 _giraffe_wlsolution_new(const cxchar *name)
00070 {
00071
00072 GiWlSolution *self = cx_calloc(1, sizeof *self);
00073
00074
00075 if (self) {
00076
00077 self->model = giraffe_model_new(name);
00078
00079 if (self->model == NULL) {
00080 giraffe_wlsolution_delete(self);
00081 return NULL;
00082 }
00083
00084 if (giraffe_model_get_type(self->model) != GI_MODEL_XOPT) {
00085 giraffe_wlsolution_delete(self);
00086 return NULL;
00087 }
00088
00089 self->subslits = FALSE;
00090 self->residuals = NULL;
00091
00092 }
00093
00094 return self;
00095
00096 }
00097
00098
00099 GiWlSolution *
00100 giraffe_wlsolution_new(const cxchar *name, cxint orientation, cxint npixels,
00101 cxdouble pixelsize, GiGrating *grating)
00102 {
00103
00104 GiWlSolution *self = NULL;
00105
00106
00107 if (name == NULL) {
00108 return self;
00109 }
00110
00111 if (grating == NULL) {
00112 return self;
00113 }
00114
00115
00116 self = _giraffe_wlsolution_new(name);
00117
00118 if (self) {
00119
00120 orientation = orientation < 0 ? -npixels : npixels;
00121 pixelsize /= 1000.;
00122
00123 giraffe_error_push();
00124
00125 giraffe_model_set_parameter(self->model, "Orientation",
00126 orientation);
00127 giraffe_model_set_parameter(self->model, "Order",
00128 grating->order);
00129 giraffe_model_set_parameter(self->model, "PixelSize",
00130 pixelsize);
00131 giraffe_model_set_parameter(self->model, "FocalLength",
00132 grating->fcoll);
00133 giraffe_model_set_parameter(self->model, "Magnification",
00134 grating->gcam);
00135 giraffe_model_set_parameter(self->model, "Angle",
00136 grating->theta);
00137 giraffe_model_set_parameter(self->model, "Spacing",
00138 grating->space);
00139
00140 if (strcmp(name, "xoptmod2") == 0) {
00141
00142 giraffe_model_set_parameter(self->model, "Sdx", grating->sdx);
00143 giraffe_model_set_parameter(self->model, "Sdy", grating->sdy);
00144 giraffe_model_set_parameter(self->model, "Sphi", grating->sphi);
00145
00146 }
00147
00148 if (cpl_error_get_code() != CPL_ERROR_NONE) {
00149 giraffe_wlsolution_delete(self);
00150 return NULL;
00151 }
00152
00153 giraffe_error_pop();
00154
00155 }
00156
00157 return self;
00158
00159 }
00160
00161
00175 GiWlSolution *
00176 giraffe_wlsolution_clone(const GiWlSolution *other)
00177 {
00178
00179 GiWlSolution *self = NULL;
00180
00181
00182 if (other != NULL) {
00183
00184 self = cx_calloc(1, sizeof(GiWlSolution));
00185
00186 self->model = giraffe_model_clone(other->model);
00187
00188 self->subslits = other->subslits;
00189 self->residuals = giraffe_wlresiduals_clone(other->residuals);
00190
00191 }
00192
00193 return self;
00194
00195 }
00196
00197
00213 GiWlSolution *
00214 giraffe_wlsolution_create(GiTable *solution, GiImage *spectra,
00215 GiGrating *grating)
00216 {
00217
00218 const cxchar *name = NULL;
00219
00220 cxint npixels = 0;
00221 cxint orientation = 0;
00222
00223 cxdouble pixelsize = 0.;
00224 cxdouble fcoll = 0.;
00225 cxdouble gcam = 0.;
00226 cxdouble theta = 0.;
00227 cxdouble sdx = 0.;
00228 cxdouble sdy = 0.;
00229 cxdouble sphi = 0.;
00230
00231
00232 cpl_propertylist *properties = NULL;
00233
00234 GiWlSolution *self = NULL;
00235
00236
00237
00238 if (solution == NULL) {
00239 return NULL;
00240 }
00241
00242 if (giraffe_table_get_properties(solution) == NULL) {
00243 return NULL;
00244 }
00245
00246 if (giraffe_table_get(solution) == NULL) {
00247 return NULL;
00248 }
00249
00250
00251 if (spectra == NULL) {
00252 return NULL;
00253 }
00254
00255 if (giraffe_image_get_properties(spectra) == NULL) {
00256 return NULL;
00257 }
00258
00259 if (giraffe_image_get(spectra) == NULL) {
00260 return NULL;
00261 }
00262
00263
00264 if (grating == NULL) {
00265 return NULL;
00266 }
00267
00268
00269
00270
00271
00272
00273
00274
00275
00276
00277
00278 properties = giraffe_image_get_properties(spectra);
00279
00280 if (!cpl_propertylist_has(properties, GIALIAS_PIXSIZX)) {
00281 return NULL;
00282 }
00283 else {
00284
00285
00286
00287
00288
00289 pixelsize = cpl_propertylist_get_double(properties, GIALIAS_PIXSIZX);
00290 pixelsize /= 1000.;
00291
00292 }
00293
00294 npixels = cpl_image_get_size_y(giraffe_image_get(spectra));
00295
00296
00297
00298
00299
00300
00301
00302 properties = giraffe_table_get_properties(solution);
00303
00304
00305 if (!cpl_propertylist_has(properties, GIALIAS_WSOL_OMNAME)) {
00306 return NULL;
00307 }
00308 else {
00309 name = cpl_propertylist_get_string(properties, GIALIAS_WSOL_OMNAME);
00310 }
00311
00312
00313 self = _giraffe_wlsolution_new(name);
00314
00315 if (self) {
00316
00317 if (!cpl_propertylist_has(properties, GIALIAS_WSOL_SUBSLITS)) {
00318 giraffe_wlsolution_delete(self);
00319 return NULL;
00320 }
00321 else {
00322
00323 self->subslits = cpl_propertylist_get_bool(properties,
00324 GIALIAS_WSOL_SUBSLITS);
00325
00326 }
00327
00328 if (!cpl_propertylist_has(properties, GIALIAS_WSOL_OMDIR)) {
00329 giraffe_wlsolution_delete(self);
00330 return NULL;
00331 }
00332 else {
00333 orientation = cpl_propertylist_get_int(properties,
00334 GIALIAS_WSOL_OMDIR);
00335 orientation = orientation < 0 ? -fabs(npixels) : fabs(npixels);
00336 }
00337
00338
00339 if (!cpl_propertylist_has(properties, GIALIAS_WSOL_OMFCOLL)) {
00340 giraffe_wlsolution_delete(self);
00341 return NULL;
00342 }
00343 else {
00344 fcoll = cpl_propertylist_get_double(properties,
00345 GIALIAS_WSOL_OMFCOLL);
00346 }
00347
00348
00349 if (!cpl_propertylist_has(properties, GIALIAS_WSOL_OMGCAM)) {
00350 giraffe_wlsolution_delete(self);
00351 return NULL;
00352 }
00353 else {
00354 gcam = cpl_propertylist_get_double(properties,
00355 GIALIAS_WSOL_OMGCAM);
00356 }
00357
00358
00359 if (!cpl_propertylist_has(properties, GIALIAS_WSOL_OMGTHETA)) {
00360 giraffe_wlsolution_delete(self);
00361 return NULL;
00362 }
00363 else {
00364 theta = cpl_propertylist_get_double(properties,
00365 GIALIAS_WSOL_OMGTHETA);
00366 }
00367
00368
00369 if (strcmp(name, "xoptmod2") == 0) {
00370
00371 if (!cpl_propertylist_has(properties, GIALIAS_WSOL_OMSDX)) {
00372 giraffe_wlsolution_delete(self);
00373 return NULL;
00374 }
00375 else {
00376 sdx = cpl_propertylist_get_double(properties,
00377 GIALIAS_WSOL_OMSDX);
00378 }
00379
00380
00381 if (!cpl_propertylist_has(properties, GIALIAS_WSOL_OMSDY)) {
00382 giraffe_wlsolution_delete(self);
00383 return NULL;
00384 }
00385 else {
00386 sdy = cpl_propertylist_get_double(properties,
00387 GIALIAS_WSOL_OMSDY);
00388 }
00389
00390
00391 if (!cpl_propertylist_has(properties, GIALIAS_WSOL_OMSPHI)) {
00392 giraffe_wlsolution_delete(self);
00393 return NULL;
00394 }
00395 else {
00396 sphi = cpl_propertylist_get_double(properties,
00397 GIALIAS_WSOL_OMSPHI);
00398 }
00399
00400 }
00401
00402
00403
00404
00405
00406
00407 giraffe_error_push();
00408
00409 giraffe_model_set_parameter(self->model, "Orientation", orientation);
00410 giraffe_model_set_parameter(self->model, "Order", grating->order);
00411 giraffe_model_set_parameter(self->model, "PixelSize", pixelsize);
00412 giraffe_model_set_parameter(self->model, "FocalLength", fcoll);
00413 giraffe_model_set_parameter(self->model, "Magnification", gcam);
00414 giraffe_model_set_parameter(self->model, "Angle", theta);
00415 giraffe_model_set_parameter(self->model, "Spacing", grating->space);
00416
00417 if (strcmp(name, "xoptmod2") == 0) {
00418 giraffe_model_set_parameter(self->model, "Sdx", sdx);
00419 giraffe_model_set_parameter(self->model, "Sdy", sdy);
00420 giraffe_model_set_parameter(self->model, "Sphi", sphi);
00421 }
00422
00423 if (cpl_error_get_code() != CPL_ERROR_NONE) {
00424 giraffe_wlsolution_delete(self);
00425 return NULL;
00426 }
00427
00428 giraffe_error_pop();
00429
00430
00431
00432
00433
00434
00435
00436 self->residuals = giraffe_wlresiduals_create(solution);
00437
00438 if (self->residuals == NULL) {
00439 self->subslits = FALSE;
00440 }
00441
00442 }
00443
00444 return self;
00445
00446 }
00447
00448
00449 void
00450 giraffe_wlsolution_delete(GiWlSolution *self)
00451 {
00452
00453 if (self != NULL) {
00454
00455 if (self->model != NULL) {
00456 giraffe_model_delete(self->model);
00457 }
00458
00459 if (self->residuals != NULL) {
00460 giraffe_wlresiduals_delete(self->residuals);
00461 }
00462
00463 cx_free(self);
00464
00465 }
00466
00467 return;
00468
00469 }
00470
00471
00472 const cxchar *
00473 giraffe_wlsolution_name(const GiWlSolution *self)
00474 {
00475
00476 GiModel *model = NULL;
00477
00478
00479 cx_assert(self != NULL);
00480
00481 model = self->model;
00482 cx_assert(model != NULL);
00483
00484 return giraffe_model_get_name(model);
00485
00486 }
00487
00488
00489 GiModel *
00490 giraffe_wlsolution_model(const GiWlSolution *self)
00491 {
00492
00493 cx_assert(self != NULL);
00494
00495 return self->model;
00496
00497 }
00498
00499
00500 cxint
00501 giraffe_wlsolution_set_subslits(GiWlSolution *self, cxbool flag)
00502 {
00503
00504 cx_assert(self != NULL);
00505
00506 if (self->residuals != NULL) {
00507 return 1;
00508 }
00509
00510 self->subslits = flag;
00511
00512 return 0;
00513
00514 }
00515
00516
00517 cxbool
00518 giraffe_wlsolution_get_subslits(const GiWlSolution *self)
00519 {
00520
00521 cx_assert(self != NULL);
00522
00523 return self->subslits;
00524
00525 }
00526
00527
00528 cxint
00529 giraffe_wlsolution_set_residuals(GiWlSolution *self,
00530 const GiWlResiduals *residuals)
00531 {
00532
00533 cxbool subslits = FALSE;
00534
00535
00536 cx_assert(self != NULL);
00537
00538 if (residuals == NULL) {
00539 return 1;
00540 }
00541
00542
00543
00544
00545
00546
00547
00548
00549 subslits = giraffe_wlresiduals_get(residuals, 0) == NULL;
00550
00551 if (self->subslits != subslits) {
00552 return 2;
00553 }
00554
00555 giraffe_wlsolution_reset_residuals(self);
00556
00557 self->residuals = (GiWlResiduals *)residuals;
00558
00559 return 0;
00560
00561 }
00562
00563
00564 GiWlResiduals *
00565 giraffe_wlsolution_get_residuals(const GiWlSolution *self)
00566 {
00567
00568 cx_assert(self != NULL);
00569
00570 return self->residuals;
00571
00572 }
00573
00574
00575 void
00576 giraffe_wlsolution_reset_residuals(GiWlSolution *self)
00577 {
00578
00579 cx_assert(self != NULL);
00580
00581 if (self->residuals != NULL) {
00582 giraffe_wlresiduals_delete(self->residuals);
00583 self->residuals = NULL;
00584 }
00585
00586 return;
00587
00588 }
00589
00590
00591 cxdouble
00592 giraffe_wlsolution_compute_pixel(const GiWlSolution *self, cxdouble lambda,
00593 cxdouble x, cxdouble y, cxint *status)
00594 {
00595
00596 cxint code = 0;
00597 cxint _status = 0;
00598
00599 cxdouble result = 0.;
00600
00601
00602 cx_assert(self != NULL);
00603
00604 giraffe_error_push();
00605
00606 giraffe_model_set_argument(self->model, "xf", x);
00607 giraffe_model_set_argument(self->model, "yf", y);
00608 giraffe_model_set_argument(self->model, "lambda", lambda);
00609
00610 if (cpl_error_get_code() != CPL_ERROR_NONE) {
00611
00612 if (status != NULL) {
00613 *status = -128;
00614 }
00615
00616 return result;
00617 }
00618
00619 giraffe_error_pop();
00620
00621 code = giraffe_model_evaluate(self->model, &result, &_status);
00622
00623 if (code != 0) {
00624
00625 if (status != NULL) {
00626 *status = -128;
00627 }
00628
00629 return result;
00630
00631 }
00632
00633 if (status != NULL) {
00634 *status = _status;
00635 }
00636
00637 return result;
00638
00639 }
00640
00641
00642 cxdouble
00643 giraffe_wlsolution_compute_residual(const GiWlSolution *self, cxdouble x,
00644 cxdouble y)
00645 {
00646
00647 cxint i;
00648
00649 cxdouble r = 0.;
00650
00651 const GiWlResiduals *residuals = NULL;
00652
00653
00654 cx_assert(self != NULL);
00655
00656 residuals = giraffe_wlsolution_get_residuals(self);
00657
00658 if (residuals == NULL) {
00659 return r;
00660 }
00661
00662
00663
00664
00665
00666
00667
00668
00669 for (i = 0; (cxsize)i < giraffe_wlresiduals_get_size(residuals); i++) {
00670
00671 const GiChebyshev2D *fit = giraffe_wlresiduals_get(residuals, i);
00672
00673 if (fit != NULL) {
00674
00675 cxdouble ax;
00676 cxdouble bx;
00677 cxdouble ay;
00678 cxdouble by;
00679
00680 giraffe_chebyshev2d_get_range(fit, &ax, &bx, &ay, &by);
00681
00682 if (ax <= x && x <= bx && ay <= y && y <= by) {
00683 r = giraffe_chebyshev2d_eval(fit, x, y);
00684 break;
00685 }
00686
00687 }
00688
00689 }
00690
00691 return r;
00692
00693 }
00694
00695
00696 GiTable *
00697 giraffe_wlsolution_create_table(const GiWlSolution *solution)
00698 {
00699
00700
00701 cxint sign = 1;
00702
00703 cxdouble value = 0.;
00704
00705 cpl_propertylist *properties = NULL;
00706
00707 GiTable *result = NULL;
00708
00709 const GiModel *model = NULL;
00710
00711 const GiWlResiduals *residuals = NULL;
00712
00713
00714 if (solution == NULL) {
00715 return NULL;
00716 }
00717
00718
00719 result = giraffe_table_new();
00720 cx_assert(result != NULL);
00721
00722 properties = cpl_propertylist_new();
00723 cx_assert(properties != NULL);
00724
00725
00726
00727
00728
00729
00730 cpl_propertylist_update_string(properties, GIALIAS_GIRFTYPE,
00731 "WLSOLUTION");
00732 cpl_propertylist_set_comment(properties, GIALIAS_GIRFTYPE,
00733 "Giraffe frame type.");
00734
00735 cpl_propertylist_update_string(properties, GIALIAS_WSOL_OMNAME,
00736 giraffe_wlsolution_name(solution));
00737 cpl_propertylist_set_comment(properties, GIALIAS_WSOL_OMNAME,
00738 "Optical model name");
00739
00740 model = giraffe_wlsolution_model(solution);
00741
00742 sign = giraffe_model_get_parameter(model,"Orientation") < 0 ? -1 : 1;
00743 cpl_propertylist_update_int(properties, GIALIAS_WSOL_OMDIR, sign);
00744 cpl_propertylist_set_comment(properties, GIALIAS_WSOL_OMDIR,
00745 "Optical model orientation");
00746
00747 value = giraffe_model_get_parameter(model, "FocalLength");
00748 cpl_propertylist_update_double(properties, GIALIAS_WSOL_OMFCOLL, value);
00749 cpl_propertylist_set_comment(properties, GIALIAS_WSOL_OMFCOLL,
00750 "Optical model focal length");
00751
00752 value = giraffe_model_get_parameter(model, "Magnification");
00753 cpl_propertylist_update_double(properties, GIALIAS_WSOL_OMGCAM, value);
00754 cpl_propertylist_set_comment(properties, GIALIAS_WSOL_OMGCAM,
00755 "Optical model camera factor");
00756
00757 value = giraffe_model_get_parameter(model, "Angle");
00758 cpl_propertylist_update_double(properties, GIALIAS_WSOL_OMGTHETA,
00759 value);
00760 cpl_propertylist_set_comment(properties, GIALIAS_WSOL_OMGTHETA,
00761 "Optical model grating angle");
00762
00763 if (strcmp(giraffe_wlsolution_name(solution), "xoptmod2") == 0) {
00764
00765 value = giraffe_model_get_parameter(model, "Sdx");
00766 cpl_propertylist_update_double(properties, GIALIAS_WSOL_OMSDX,
00767 value);
00768 cpl_propertylist_set_comment(properties, GIALIAS_WSOL_OMSDX,
00769 "Optical model slit x-offset");
00770
00771 value = giraffe_model_get_parameter(model, "Sdy");
00772 cpl_propertylist_update_double(properties, GIALIAS_WSOL_OMSDY,
00773 value);
00774 cpl_propertylist_set_comment(properties, GIALIAS_WSOL_OMSDY,
00775 "Optical model slit y-offset");
00776
00777 value = giraffe_model_get_parameter(model, "Sphi");
00778 cpl_propertylist_update_double(properties, GIALIAS_WSOL_OMSPHI,
00779 value);
00780 cpl_propertylist_set_comment(properties, GIALIAS_WSOL_OMSPHI,
00781 "Optical model slit rotation");
00782
00783 }
00784
00785
00786
00787
00788
00789
00790
00791 residuals = giraffe_wlsolution_get_residuals(solution);
00792
00793 if (residuals != NULL) {
00794
00795 cpl_table *coeffs = giraffe_wlresiduals_table(residuals);
00796
00797 if (coeffs != NULL) {
00798 giraffe_table_set(result, coeffs);
00799 }
00800
00801 }
00802
00803 giraffe_table_set_properties(result, properties);
00804
00805 cpl_propertylist_delete(properties);
00806 properties = NULL;
00807
00808 return result;
00809
00810 }