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 <cxmemory.h>
00036 #include <cxstring.h>
00037 #include <cxstrutils.h>
00038
00039 #include <cpl_error.h>
00040 #include <cpl_msg.h>
00041
00042 #include "gimacros.h"
00043 #include "gialias.h"
00044 #include "gimatrix.h"
00045 #include "gigrating.h"
00046 #include "gimodel.h"
00047 #include "gilinedata.h"
00048 #include "giwlsolution.h"
00049 #include "gimath.h"
00050 #include "gimessages.h"
00051 #include "gifiberutils.h"
00052 #include "giclip.h"
00053 #include "giwlcalibration.h"
00054
00055
00064
00065
00066
00067
00068
00069
00070 enum GiLineType {
00071 GI_LINETYPE_UNDEFINED,
00072 GI_LINETYPE_THARNE,
00073 GI_LINETYPE_TELLURIC
00074 };
00075
00076 typedef enum GiLineType GiLineType;
00077
00078
00079
00080
00081
00082
00083 enum {
00084 LF_R_NONE = 0x0000,
00085 LF_R_AMPLI = 0x0001,
00086 LF_R_NITER = 0x0002,
00087 LF_R_CENTR = 0x0004,
00088 LF_R_WIDTH = 0x0008,
00089 LF_R_LEFT = 0x0010,
00090 LF_R_RIGHT = 0x0020,
00091 LF_R_OFFST = 0x0040,
00092 LF_R_BADLN = 0x0080,
00093 LF_R_ERROR = 0x0100,
00094 LF_R_PSFIT = 0x0200,
00095 LF_R_XRFIT = 0x0400,
00096 LF_R_RESOL = 0x0800,
00097 LF_R_XCCD = 0x1000
00098 };
00099
00100
00101
00102
00103
00104
00105 enum {
00106 SLIT_DX = 0x0001,
00107 SLIT_DY = 0x0002,
00108 SLIT_PHI = 0x0004,
00109 };
00110
00111
00112
00113
00114
00115
00116 enum {
00117 OPTM_FLENGTH = 1 << 0,
00118 OPTM_GCAMERA = 1 << 1,
00119 OPTM_THETA = 1 << 2,
00120 OPTM_SX = 1 << 3,
00121 OPTM_SY = 1 << 4,
00122 OPTM_SPHI = 1 << 5
00123 };
00124
00125
00126
00127
00128
00129
00130 enum GiOpticalModelInfo {
00131 GI_OPTM_PARAMETER_VALUES,
00132 GI_OPTM_PARAMETER_ERRORS,
00133 GI_OPTM_PARAMETER_STATUS
00134 };
00135
00136 typedef enum GiOpticalModelInfo GiOpticalModelInfo;
00137
00138
00139
00140
00141
00142
00143 struct GiLineParams {
00144
00145 const cxchar *model;
00146
00147 GiLineType type;
00148
00149 cxdouble grwid;
00150 cxdouble satlv;
00151 cxdouble thres;
00152 cxdouble offst;
00153 cxdouble wfact;
00154 cxdouble psfexp;
00155
00156 GiFitSetup fit;
00157
00158 };
00159
00160 typedef struct GiLineParams GiLineParams;
00161
00162
00163
00164
00165
00166
00167 struct GiOpticalModelParams {
00168
00169 GiFitSetup fit;
00170 cxint16 flags;
00171
00172 };
00173
00174 typedef struct GiOpticalModelParams GiOpticalModelParams;
00175
00176
00177
00178
00179
00180
00181 struct GiSCFitParams {
00182
00183 cxbool subslits;
00184
00185 struct {
00186 cxint xorder;
00187 cxint yorder;
00188 } fit;
00189
00190 GiClipParams clip;
00191
00192 };
00193
00194 typedef struct GiSCFitParams GiSCFitParams;
00195
00196
00197 struct GiWCalInfo {
00198
00199 cxint width;
00200
00201 cxbool residuals;
00202
00203 cxint nlines;
00204 cxint nfibers;
00205
00206 cxint ngood;
00207 cxint nreject;
00208
00209 cxdouble rms;
00210
00211 };
00212
00213 typedef struct GiWCalInfo GiWCalInfo;
00214
00215
00216 inline static cxint
00217 _giraffe_window_compare(cxcptr first, cxcptr second)
00218 {
00219
00220 cxint *_first = (cxint *)first;
00221 cxint *_second = (cxint *)second;
00222
00223 return *_second - *_first;
00224
00225 }
00226
00227
00228 inline static GiLineParams *
00229 _giraffe_lineparams_create(GiLineType type, const GiGrating *grating,
00230 const GiWCalConfig *config)
00231 {
00232
00233 GiLineParams *self = NULL;
00234
00235
00236 cx_assert(grating != NULL);
00237 cx_assert(config != NULL);
00238
00239 self = cx_calloc(1, sizeof(GiLineParams));
00240
00241 self->model = cx_strdup(config->line_model);
00242 self->type = type;
00243
00244
00245
00246
00247
00248
00249
00250 self->grwid = 1. / grating->band * (grating->wlen0 / grating->resol);
00251 self->satlv = config->line_saturation;
00252 self->thres = config->line_threshold;
00253 self->offst = config->line_offset;
00254 self->wfact = config->line_rwidthratio;
00255
00256 self->psfexp = config->line_widthexponent;
00257
00258 self->fit.iterations = config->line_niter;
00259 self->fit.tests = config->line_ntest;
00260 self->fit.delta = config->line_dchisq;
00261
00262 return self;
00263
00264 }
00265
00266
00267 inline static void
00268 _giraffe_lineparams_delete(GiLineParams *self)
00269 {
00270
00271 if (self) {
00272
00273 if (self->model) {
00274 cx_free((cxptr)self->model);
00275 }
00276
00277 cx_free(self);
00278
00279 }
00280
00281 return;
00282
00283 }
00284
00285
00286 inline static cxdouble
00287 _giraffe_get_fiber_position(const cpl_image *locy, cxint cs, cxdouble xccd)
00288 {
00289
00290 cxint xlower = (cxint)floor(xccd);
00291 cxint xupper = (cxint)ceil(xccd);
00292
00293 const cxdouble *ldata = cpl_image_get_data_const(locy);
00294
00295 cxdouble ylower = 0.;
00296 cxdouble yupper = 0.;
00297
00298
00299 cx_assert(ldata != NULL);
00300
00301 ylower = ldata[xlower * cpl_image_get_size_x(locy) + cs];
00302 yupper = ldata[xupper * cpl_image_get_size_x(locy) + cs];
00303
00304 return giraffe_interpolate_linear(xccd, xlower, ylower, xupper, yupper);
00305
00306 }
00307
00308
00309 inline static cxint
00310 _giraffe_subslit_get_max(const cpl_table *fibers)
00311 {
00312
00313 return cpl_table_get_column_max((cpl_table *)fibers, "SSN");
00314
00315 }
00316
00317
00318 inline static cpl_table *
00319 _giraffe_subslit_get(const cpl_table *fibers, cxint ssn)
00320 {
00321
00322 cxint ssn_max = 0;
00323
00324 cpl_table *_fibers;
00325
00326
00327 cx_assert(fibers != NULL);
00328 cx_assert(cpl_table_has_column((cpl_table *)fibers, "SSN"));
00329
00330 ssn_max = _giraffe_subslit_get_max(fibers);
00331
00332 if (ssn < 0 || ssn > ssn_max) {
00333 return NULL;
00334 }
00335
00336 cpl_table_unselect_all((cpl_table *)fibers);
00337 cpl_table_or_selected_int((cpl_table *)fibers, "SSN", CPL_EQUAL_TO, ssn);
00338
00339 _fibers = cpl_table_extract_selected((cpl_table *)fibers);
00340
00341 return _fibers;
00342
00343 }
00344
00345
00346 inline static cxint
00347 _giraffe_subslit_range(const cpl_table *subslit, const cpl_image *locy,
00348 const cpl_image *locw, cxdouble *ymin, cxdouble *ymax)
00349 {
00350
00351 const cxchar *idx = NULL;
00352
00353 cxint i;
00354 cxint ns = 0;
00355 cxint nx = 0;
00356
00357 const cxdouble *_locy = NULL;
00358 const cxdouble *_locw = NULL;
00359
00360 cxdouble _ymin = CX_MAXDOUBLE;
00361 cxdouble _ymax = 0.;
00362
00363 cx_assert(subslit != NULL);
00364 cx_assert(locy != NULL);
00365 cx_assert(locw != NULL);
00366
00367 idx = giraffe_fiberlist_query_index(subslit);
00368
00369 ns = cpl_image_get_size_x(locy);
00370 nx = cpl_image_get_size_y(locy);
00371
00372 _locy = cpl_image_get_data_const(locy);
00373 _locw = cpl_image_get_data_const(locw);
00374
00375 for (i = 0; i < cpl_table_get_nrow((cpl_table *)subslit); i++) {
00376
00377 cxint j;
00378 cxint cs = cpl_table_get_int((cpl_table *)subslit, idx, i, NULL) - 1;
00379
00380 for (j = 0; j < nx; j++) {
00381
00382 register cxint k = j * ns + cs;
00383
00384 cxdouble ylower = _locy[k] - _locw[k];
00385 cxdouble yupper = _locy[k] + _locw[k];
00386
00387 _ymin = CX_MIN(_ymin, ylower);
00388 _ymax = CX_MAX(_ymax, yupper);
00389
00390 }
00391
00392 }
00393
00394 if (_ymin > _ymax) {
00395 return 1;
00396 }
00397
00398 if (ymin != NULL) {
00399 *ymin = _ymin;
00400 }
00401
00402 if (ymax != NULL) {
00403 *ymax = _ymax;
00404 }
00405
00406 return 0;
00407
00408 }
00409
00410
00411 inline static cxint
00412 _giraffe_get_residuals(cpl_image *residuals, const cpl_image *positions,
00413 const cpl_image *fit)
00414 {
00415
00416 cxint i;
00417 cxint nfibers = 0;
00418 cxint nlines = 0;
00419 cxint nx = 0;
00420
00421 const cxdouble *_positions = NULL;
00422 const cxdouble *_fit = NULL;
00423
00424 cxdouble *_residuals = NULL;
00425
00426
00427 cx_assert(residuals != NULL);
00428 cx_assert(positions != NULL);
00429 cx_assert(fit != NULL);
00430
00431 nfibers = cpl_image_get_size_x(positions);
00432 nlines = cpl_image_get_size_y(positions);
00433 nx = cpl_image_get_size_y(fit);
00434
00435 cx_assert(nfibers == cpl_image_get_size_x(residuals));
00436 cx_assert(nlines == cpl_image_get_size_y(residuals));
00437
00438 _residuals = cpl_image_get_data(residuals);
00439 _positions = cpl_image_get_data_const(positions);
00440 _fit = cpl_image_get_data_const(fit);
00441
00442 for (i = 0; i < nlines; i++) {
00443
00444 register cxint j;
00445
00446 for (j = 0; j < nfibers; j++) {
00447
00448 register cxdouble line_pos = _positions[i * nfibers + j];
00449
00450 line_pos = CX_MIN(CX_MAX(line_pos, 0.), nx - 1);
00451 _residuals[i * nfibers + j] = _fit[(cxint)line_pos * nfibers + j];
00452
00453 }
00454
00455 }
00456
00457 return 0;
00458
00459 }
00460
00461
00462 inline static cxint
00463 _giraffe_apply_residuals(cpl_image *xccd, const cpl_image *residuals,
00464 const cpl_image *lflags, cxdouble value)
00465 {
00466
00467 cx_assert(xccd != NULL);
00468 cx_assert(residuals != NULL);
00469
00470 cpl_image_subtract(xccd, residuals);
00471
00472 if (lflags != NULL) {
00473
00474 const cxint *_lflags = cpl_image_get_data_const(lflags);
00475
00476 cxint i;
00477 cxint nfibers = cpl_image_get_size_x(xccd);
00478 cxint nlines = cpl_image_get_size_y(xccd);
00479
00480 cxdouble *_xccd = cpl_image_get_data(xccd);
00481
00482
00483 cx_assert(nfibers == cpl_image_get_size_x(lflags));
00484 cx_assert(nlines == cpl_image_get_size_y(lflags));
00485
00486 for (i = 0; i < nlines; i++) {
00487
00488 cxint j;
00489
00490 for (j = 0; j < nfibers; j++) {
00491
00492 if (_lflags[i * nfibers + j] > 0) {
00493 _xccd[i * nfibers + j] = value;
00494 }
00495
00496 }
00497
00498 }
00499
00500 }
00501
00502 return 0;
00503
00504 }
00505
00506
00507 inline static cxint
00508 _giraffe_linelist_setup(GiTable *lines, GiGrating *grating,
00509 const GiWCalConfig *config)
00510 {
00511
00512 const cxchar *const fctid = "_giraffe_linelist_setup";
00513
00514
00515 const cxdouble fraction = 500.;
00516
00517 cxint nlines = 0;
00518 cxint nreject = 0;
00519 cxint status = 0;
00520
00521 cxdouble wlmin = 0.;
00522 cxdouble wlmax = 0.;
00523 cxdouble margin = 0.;
00524
00525 cpl_table *_lines = NULL;
00526
00527
00528
00529 cx_assert(lines != NULL);
00530 cx_assert(grating != NULL);
00531 cx_assert(config != NULL);
00532
00533
00534 _lines = giraffe_table_get(lines);
00535
00536 if (_lines == NULL) {
00537 return 1;
00538 }
00539
00540 if (!cpl_table_has_column(_lines, "WLEN") ||
00541 !cpl_table_has_column(_lines, "FLUX")) {
00542 return 2;
00543 }
00544
00545
00546
00547
00548
00549
00550
00551 nlines = cpl_table_get_nrow(_lines);
00552 cpl_table_unselect_all(_lines);
00553
00554 wlmin = grating->wlenmin;
00555 wlmax = grating->wlenmax;
00556
00557 if (giraffe_range_get_min(config->line_wlrange) > 0.) {
00558 wlmin = giraffe_range_get_min(config->line_wlrange);
00559 grating->wlenmin = wlmin;
00560 }
00561
00562 if (giraffe_range_get_max(config->line_wlrange) > 0.) {
00563 wlmax = giraffe_range_get_max(config->line_wlrange);
00564 grating->wlenmax = wlmax;
00565 }
00566
00567 margin = (wlmax - wlmin) / fraction;
00568
00569 cpl_msg_debug(fctid, "Selecting wavelength range [%.4f, %.4f[ [nm] with "
00570 "margin %.4f nm.", wlmin, wlmax, margin);
00571
00572 cpl_table_or_selected_double(_lines, "WLEN", CPL_LESS_THAN,
00573 wlmin + margin);
00574 cpl_table_or_selected_double(_lines, "WLEN", CPL_NOT_LESS_THAN,
00575 wlmax - margin);
00576
00577 cpl_table_erase_selected(_lines);
00578
00579 if (cpl_table_get_nrow(_lines) <= 0) {
00580 cpl_msg_debug(fctid, "Invalid line list! All lines have been "
00581 "rejected!");
00582 return -1;
00583 }
00584
00585 nreject = nlines - cpl_table_get_nrow(_lines);
00586 cpl_msg_debug(fctid, "%d of %d lines rejected because of wavelength "
00587 "range.", nreject, nlines);
00588
00589
00590
00591
00592
00593
00594 nlines = cpl_table_get_nrow(_lines);
00595
00596 if (config->line_count != 0) {
00597
00598 cxint i;
00599 cxint line_count = abs(config->line_count);
00600
00601 cpl_propertylist *sorting_order = NULL;
00602
00603
00604 if (line_count > nlines) {
00605 cpl_msg_debug(fctid, "Too few lines in line list for brightness "
00606 "selection!");
00607
00608 if (config->line_count > 0) {
00609 return 3;
00610 }
00611 else {
00612 cpl_msg_debug(fctid, "Skipping brightness selection!");
00613 line_count = nlines;
00614 }
00615 }
00616
00617 sorting_order = cpl_propertylist_new();
00618 cpl_propertylist_append_bool(sorting_order, "FLUX", 1);
00619
00620 cpl_table_sort(_lines, sorting_order);
00621
00622 cpl_propertylist_delete(sorting_order);
00623 sorting_order = NULL;
00624
00625 cpl_table_select_all(_lines);
00626
00627 for (i = 0; i < line_count; i++) {
00628 cpl_table_unselect_row(_lines, i);
00629 }
00630
00631 status = cpl_table_erase_selected(_lines);
00632
00633 if (cpl_table_get_nrow(_lines) <= 0) {
00634 return -1;
00635 }
00636
00637 sorting_order = cpl_propertylist_new();
00638 cpl_propertylist_append_bool(sorting_order, "WLEN", 0);
00639
00640 cpl_table_sort(_lines, sorting_order);
00641
00642 cpl_propertylist_delete(sorting_order);
00643 sorting_order = NULL;
00644
00645 }
00646
00647 if (config->line_brightness > 0.) {
00648
00649 cpl_table_select_all(_lines);
00650 cpl_table_and_selected_double(_lines, "FLUX", CPL_NOT_GREATER_THAN,
00651 config->line_brightness);
00652
00653 cpl_table_erase_selected(_lines);
00654
00655 if (cpl_table_get_nrow(_lines) <= 0) {
00656 cpl_msg_debug(fctid, "Invalid line brightness! All lines have "
00657 "been rejected!");
00658 return -2;
00659 }
00660
00661 }
00662
00663 nreject = nlines - cpl_table_get_nrow(_lines);
00664 cpl_msg_debug(fctid, "%d of %d lines rejected because brightness "
00665 "criteria.", nreject, nlines);
00666
00667
00668 return 0;
00669
00670 }
00671
00672
00673 inline static cpl_table *
00674 _giraffe_linelist_select(const GiTable *lines, const GiImage *spectra,
00675 const GiGrating *grating, cxdouble width,
00676 const GiWCalConfig *config)
00677 {
00678
00679 const cxchar *const fctid = "_giraffe_linelist_select";
00680
00681
00682 cxint i;
00683 cxint nlines = 0;
00684 cxint nreject = 0;
00685
00686 cxdouble scale = 0.;
00687 cxdouble separation = 0.;
00688
00689 cpl_image *_spectra = NULL;
00690
00691 cpl_table *_lines = NULL;
00692
00693
00694 cx_assert(lines != NULL);
00695 cx_assert(spectra != NULL);
00696 cx_assert(grating != NULL);
00697 cx_assert(config != NULL);
00698
00699 _spectra = giraffe_image_get(spectra);
00700 cx_assert(_spectra != NULL);
00701
00702 _lines = cpl_table_duplicate(giraffe_table_get(lines));
00703
00704 if (_lines == NULL) {
00705 return NULL;
00706 }
00707
00708 nlines = cpl_table_get_nrow(_lines);
00709
00710
00711
00712
00713
00714
00715
00716 scale = fabs(cpl_image_get_size_y(_spectra)) / grating->band;
00717 separation = width / scale * config->line_separation;
00718
00719 cpl_msg_debug(fctid, "Estimated wavelength scale: %.4e nm/pxl",
00720 1. / scale);
00721 cpl_msg_debug(fctid, "Minimum required line separation: %.4f nm (%.4f "
00722 "pxl)", separation, separation * scale);
00723
00724
00725
00726
00727
00728
00729
00730
00731
00732
00733
00734
00735
00736
00737
00738 cpl_table_unselect_all(_lines);
00739
00740 for (i = 0; i < cpl_table_get_nrow(_lines); i++) {
00741
00742 register cxint j;
00743
00744 register cxdouble w = cpl_table_get(_lines, "WLEN", i, NULL);
00745 register cxdouble f = cpl_table_get(_lines, "FLUX", i, NULL);
00746
00747
00748 for (j = 0; j < cpl_table_get_nrow(_lines); j++) {
00749
00750 if (i != j) {
00751
00752 register cxdouble _w = cpl_table_get(_lines, "WLEN", j, NULL);
00753 register cxdouble _f = cpl_table_get(_lines, "FLUX", j, NULL);
00754
00755
00756 if (fabs(w - _w) < separation &&
00757 f / _f < config->line_fluxratio) {
00758
00759 cpl_table_select_row(_lines, i);
00760 break;
00761
00762 }
00763
00764 }
00765
00766 }
00767
00768 }
00769
00770 cpl_table_erase_selected(_lines);
00771
00772 if (cpl_table_get_nrow(_lines) <= 0) {
00773 cpl_table_delete(_lines);
00774 return NULL;
00775 }
00776
00777 nreject = nlines - cpl_table_get_nrow(_lines);
00778 cpl_msg_debug(fctid, "%d of %d lines rejected due to crowding.",
00779 nreject, nlines);
00780
00781
00782
00783
00784
00785
00786
00787
00788
00789
00790
00791 cpl_msg_debug(fctid, "Removing lines with non-zero line quality.");
00792
00793 nlines = cpl_table_get_nrow(_lines);
00794 cpl_table_unselect_all(_lines);
00795
00796 if (cpl_table_has_column(_lines, "FLAGS")) {
00797
00798 cpl_table_or_selected_int(_lines, "FLAGS", CPL_NOT_EQUAL_TO, 0);
00799
00800 }
00801 else {
00802
00803 if (cpl_table_has_column(_lines, "COMMENT")) {
00804
00805 for (i = 0; i < nlines; i++) {
00806
00807 cxchar *s = cx_strdup(cpl_table_get_string(_lines,
00808 "COMMENT", i));
00809
00810 if (strlen(cx_strstrip(s)) > 3) {
00811 cpl_table_select_row(_lines, i);
00812 }
00813
00814 cx_free(s);
00815
00816 }
00817
00818 }
00819 else {
00820
00821 cpl_msg_debug(fctid, "No comments found in line list! No line "
00822 "quality checks will be done!");
00823
00824 }
00825
00826 }
00827
00828 cpl_table_erase_selected(_lines);
00829
00830 if (cpl_table_get_nrow(_lines) <= 0) {
00831 cpl_msg_debug(fctid, "Invalid line list! All lines have been "
00832 "rejected!");
00833 cpl_table_delete(_lines);
00834 return NULL;
00835 }
00836
00837 nreject = nlines - cpl_table_get_nrow(_lines);
00838 cpl_msg_debug(fctid, "%d of %d lines rejected because of line quality.",
00839 nreject, nlines);
00840
00841
00842 return _lines;
00843
00844 }
00845
00846
00847 inline static cpl_image *
00848 _giraffe_line_abscissa(const cpl_table *lines, const GiTable *slitgeometry,
00849 const GiTable *fibers, const GiWlSolution *solution,
00850 const GiLocalization *localization, cxbool residuals)
00851 {
00852
00853 const cxchar *const fctid = "_giraffe_line_abscissa";
00854
00855
00856 const cxchar *idx = NULL;
00857
00858 cxint i;
00859 cxint nlines = 0;
00860 cxint nfibers = 0;
00861
00862 cpl_table *_lines = NULL;
00863 cpl_table *_fibers = NULL;
00864 cpl_table *_slitgeometry = NULL;
00865
00866 cpl_image *abscissa = NULL;
00867
00868
00869 cx_assert(lines != NULL);
00870 cx_assert(slitgeometry != NULL);
00871 cx_assert(fibers != NULL);
00872 cx_assert(solution != NULL);
00873
00874 _lines = (cpl_table *)lines;
00875
00876 _fibers = giraffe_table_get(fibers);
00877 cx_assert(_fibers != NULL);
00878
00879 _slitgeometry = giraffe_table_get(slitgeometry);
00880 cx_assert(_slitgeometry != NULL);
00881
00882
00883 nlines = cpl_table_get_nrow(_lines);
00884 nfibers = cpl_table_get_nrow(_fibers);
00885
00886 if (nfibers != cpl_table_get_nrow(_slitgeometry)) {
00887 cpl_error_set(fctid, CPL_ERROR_ILLEGAL_INPUT);
00888 return NULL;
00889 }
00890
00891
00892 idx = giraffe_fiberlist_query_index(_fibers);
00893
00894 if (idx == NULL) {
00895 cpl_error_set(fctid, CPL_ERROR_ILLEGAL_INPUT);
00896 return NULL;
00897 }
00898
00899
00900 if (residuals == TRUE) {
00901
00902 if (localization == NULL) {
00903 cpl_error_set(fctid, CPL_ERROR_ILLEGAL_INPUT);
00904 return NULL;
00905 }
00906 else {
00907 if (localization->locy == NULL || localization->locw == NULL) {
00908 cpl_error_set(fctid, CPL_ERROR_DATA_NOT_FOUND);
00909 return NULL;
00910 }
00911 }
00912
00913 if (giraffe_wlsolution_get_residuals(solution) == NULL) {
00914 cpl_error_set(fctid, CPL_ERROR_DATA_NOT_FOUND);
00915 return NULL;
00916 }
00917
00918 }
00919
00920
00921 abscissa = cpl_image_new(nfibers, nlines, CPL_TYPE_DOUBLE);
00922
00923 for (i = 0; i < nfibers; i++) {
00924
00925 cxint j;
00926
00927 cxdouble xf = cpl_table_get(_slitgeometry, "XF", i, NULL);
00928 cxdouble yf = cpl_table_get(_slitgeometry, "YF", i, NULL);
00929 cxdouble *data = cpl_image_get_data(abscissa);
00930
00931
00932 for (j = 0; j < nlines; j++) {
00933
00934 cxint status = 0;
00935
00936 cxdouble lambda = cpl_table_get(_lines, "WLEN", j, NULL);
00937
00938 cxdouble xccd = 0.;
00939
00940
00941 xccd = giraffe_wlsolution_compute_pixel(solution, lambda, xf, yf,
00942 &status);
00943
00944 if (status != 0) {
00945 cpl_image_delete(abscissa);
00946 return NULL;
00947 }
00948
00949 if (residuals == TRUE) {
00950
00951 cxint cs = cpl_table_get_int(_fibers, idx, i, NULL) - 1;
00952
00953 cxdouble yccd = 0.;
00954
00955 cpl_image *_locy = giraffe_image_get(localization->locy);
00956
00957
00958 cx_assert(_locy != NULL);
00959
00960 if (xccd > 0. && xccd < cpl_image_get_size_y(_locy)) {
00961
00962 cxdouble xres = 0.;
00963
00964 yccd = _giraffe_get_fiber_position(_locy, cs, xccd);
00965 xres = giraffe_wlsolution_compute_residual(solution,
00966 xccd, yccd);
00967
00968 xccd -= xres;
00969 }
00970
00971 }
00972
00973 data[j * nfibers + i] = xccd;
00974
00975 }
00976
00977 }
00978
00979 return abscissa;
00980
00981 }
00982
00983
00984 inline static cpl_image *
00985 _giraffe_line_ordinate(GiTable *lines, const GiTable *slitgeometry,
00986 const GiWlSolution *solution)
00987 {
00988
00989 return NULL;
00990
00991 }
00992
00993
00994
00995
00996
00997
00998
00999 inline static void
01000 _giraffe_line_fit_setup(GiModel *model, cxdouble width, cxint xmin,
01001 const cpl_matrix *y, const cpl_matrix *sigma,
01002 const GiLineParams *setup, cxint *lflags)
01003 {
01004
01005 cxint k;
01006 cxint center = 0;
01007 cxint xline = 0;
01008
01009 cxdouble amplitude = 0.;
01010 cxdouble background = 0.;
01011 cxdouble _sigma = 0.;
01012
01013 cpl_matrix *_y = NULL;
01014
01015
01016 cx_assert(model != NULL);
01017 cx_assert(y != NULL);
01018 cx_assert(setup != NULL);
01019 cx_assert(lflags != NULL);
01020
01021
01022 if (*lflags != LF_R_NONE) {
01023 return;
01024 }
01025
01026
01027
01028
01029
01030
01031
01032
01033
01034
01035
01036 center = xmin;
01037 for (k = 0; k < cpl_matrix_get_nrow((cpl_matrix*)y); k++) {
01038 if (cpl_matrix_get((cpl_matrix *)y, k, 0) >= amplitude) {
01039 center = xmin + k;
01040 xline = k;
01041 amplitude = cpl_matrix_get((cpl_matrix *)y, k, 0);
01042 }
01043 }
01044
01045
01046
01047
01048 _y = cpl_matrix_duplicate((cpl_matrix *)y);
01049
01050 giraffe_matrix_sort(_y);
01051
01052 background = 0.5 * (cpl_matrix_get(_y, 0, 0) + cpl_matrix_get(_y, 1, 0));
01053 cpl_matrix_delete(_y);
01054
01055
01056
01057
01058
01059
01060
01061
01062
01063 _sigma = cpl_matrix_get((cpl_matrix *)sigma, xline, 0) * setup->thres;
01064
01065 if (amplitude <= _sigma || amplitude > setup->satlv) {
01066 *lflags |= LF_R_AMPLI;
01067 return;
01068 }
01069
01070 giraffe_model_set_parameter(model, "Amplitude", amplitude - background);
01071 giraffe_model_set_parameter(model, "Center", center);
01072 giraffe_model_set_parameter(model, "Background", background);
01073 giraffe_model_set_parameter(model, "Width1", width);
01074
01075 if (strncmp(giraffe_model_get_name(model), "psfexp", 6) == 0) {
01076
01077 cxdouble width2 = setup->psfexp < 0. ? -setup->psfexp : setup->psfexp;
01078
01079 giraffe_model_set_parameter(model, "Width2", width2);
01080
01081
01082
01083
01084
01085
01086
01087 if (setup->psfexp >= 0.) {
01088 giraffe_model_freeze_parameter(model, "Width2");
01089 }
01090 else {
01091 giraffe_model_thaw_parameter(model, "Width2");
01092 }
01093
01094 }
01095
01096 return;
01097
01098 }
01099
01100
01101 inline static cxint
01102 _giraffe_line_fit(GiLineData *lines, const cpl_image *positions, cxint width,
01103 const GiExtraction *extraction, const GiTable *fibers,
01104 const GiImage *locy, const GiLineParams *setup)
01105 {
01106
01107 const cxchar *const fctid = "_giraffe_line_fit";
01108
01109
01110 const cxchar *idx = NULL;
01111
01112 cxint i;
01113 cxint nfibers = 0;
01114 cxint nlines = 0;
01115
01116 const cxdouble LOG2 = log(2.);
01117 const cxdouble fwhm_ratio = 2. * sqrt(2. * LOG2);
01118
01119 cpl_image *_spectra = NULL;
01120 cpl_image *_errors = NULL;
01121 cpl_image *_locy = NULL;
01122
01123 cpl_matrix *x = NULL;
01124 cpl_matrix *y = NULL;
01125 cpl_matrix *sigma = NULL;
01126
01127 cpl_table *_fibers = NULL;
01128
01129 GiModel *model = NULL;
01130
01131
01132 cx_assert(positions != NULL);
01133 cx_assert(width > 0);
01134
01135 cx_assert(extraction != NULL);
01136 cx_assert(extraction->spectra != NULL && extraction->error != NULL);
01137
01138 cx_assert(fibers != NULL);
01139 cx_assert(locy != NULL);
01140 cx_assert(setup != NULL);
01141
01142
01143 _fibers = giraffe_table_get(fibers);
01144 cx_assert(_fibers != NULL);
01145
01146 _spectra = giraffe_image_get(extraction->spectra);
01147 cx_assert(_spectra != NULL);
01148
01149 _errors = giraffe_image_get(extraction->error);
01150 cx_assert(_errors != NULL);
01151
01152 _locy = giraffe_image_get(locy);
01153 cx_assert(_locy != NULL);
01154
01155 nfibers = cpl_table_get_nrow(_fibers);
01156
01157 cx_assert(nfibers == cpl_image_get_size_x(_spectra));
01158 cx_assert(nfibers == cpl_image_get_size_x(_errors));
01159
01160
01161
01162
01163
01164 idx = giraffe_fiberlist_query_index(_fibers);
01165 cx_assert(idx != NULL);
01166
01167 nlines = cpl_image_get_size_y(positions);
01168
01169
01170
01171
01172
01173
01174 if (strcmp(setup->model, "gaussian") != 0 &&
01175 strcmp(setup->model, "psfexp") != 0 &&
01176 strcmp(setup->model, "psfexp2") != 0) {
01177 cpl_error_set(fctid, CPL_ERROR_ILLEGAL_INPUT);
01178 return 1;
01179 }
01180
01181 model = giraffe_model_new(setup->model);
01182
01183 if (giraffe_model_get_type(model) != GI_MODEL_LINE) {
01184 giraffe_model_delete(model);
01185 return 2;
01186 }
01187
01188 giraffe_model_thaw(model);
01189
01190 giraffe_model_set_iterations(model, setup->fit.iterations);
01191 giraffe_model_set_tests(model, setup->fit.tests);
01192 giraffe_model_set_delta(model, setup->fit.delta);
01193
01194
01195
01196
01197
01198
01199 x = cpl_matrix_new(width, 1);
01200 y = cpl_matrix_new(width, 1);
01201 sigma = cpl_matrix_new(width, 1);
01202
01203 for (i = 0; i < nfibers; i++) {
01204
01205 cxint j;
01206
01207 for (j = 0; j < nlines; j++) {
01208
01209 cxint k;
01210 cxint lflags = LF_R_NONE;
01211 cxint iterations = 0;
01212 cxint ndata = 0;
01213 cxint xmin = 0;
01214 cxint xmax = 0;
01215 cxint nx = cpl_image_get_size_y(_spectra);
01216
01217 cxdouble xccd = 0.;
01218 cxdouble yccd = 0.;
01219 cxdouble lwidth = 0.;
01220 cxdouble amplitude = 0.;
01221 cxdouble background = 0.;
01222 cxdouble center = 0.;
01223 cxdouble width1 = 0.;
01224 cxdouble exponent = 0.;
01225 cxdouble error = 0.;
01226 cxdouble gwidth = 0.;
01227
01228 const cxdouble *_positions = cpl_image_get_data_const(positions);
01229
01230
01231
01232
01233
01234
01235 xccd = _positions[j * nfibers + i];
01236
01237 xmin = xccd;
01238 xmax = xccd;
01239
01240 if (0 < xccd && xccd < nx) {
01241
01242 cxint cs = cpl_table_get_int(_fibers, idx, i, NULL) - 1;
01243
01244
01245
01246
01247
01248
01249
01250 xmin = (cxint)(xccd - 0.5 * width + 0.5);
01251 xmax = (cxint)(xccd + 0.5 * width + 0.5);
01252
01253 xmin = CX_MAX(CX_MIN(xmin, nx - 1), 0);
01254 xmax = CX_MAX(CX_MIN(xmax, nx - 1), 0);
01255
01256 ndata = xmax - xmin;
01257
01258
01259
01260
01261
01262
01263 yccd = _giraffe_get_fiber_position(_locy, cs, xccd);
01264
01265 }
01266
01267
01268
01269
01270
01271
01272
01273 if (ndata < 3) {
01274 lflags |= LF_R_XCCD;
01275 }
01276 else {
01277
01278
01279
01280
01281
01282 if (ndata != cpl_matrix_get_nrow(x)) {
01283 cpl_matrix_set_size(x, ndata, 1);
01284 cpl_matrix_set_size(y, ndata, 1);
01285 cpl_matrix_set_size(sigma, ndata, 1);
01286 }
01287
01288 for (k = 0; k < ndata; k++) {
01289
01290 cxint l = xmin + k;
01291
01292 cxdouble *sdata = cpl_image_get_data(_spectra);
01293 cxdouble *edata = cpl_image_get_data(_errors);
01294
01295 cpl_matrix_set(x, k, 0, xmin + k);
01296 cpl_matrix_set(y, k, 0, sdata[l * nfibers + i]);
01297 cpl_matrix_set(sigma, k, 0, edata[l * nfibers + i]);
01298
01299 }
01300
01301 }
01302
01303
01304
01305
01306
01307
01308
01309
01310
01311
01312
01313
01314 if (strcmp(setup->model, "psfexp") == 0) {
01315
01316 exponent = fabs(setup->psfexp);
01317
01318 lwidth = pow(0.5 * setup->grwid * nx, exponent) / LOG2;
01319
01320 }
01321 else if (strcmp(setup->model, "psfexp2") == 0) {
01322
01323 exponent = fabs(setup->psfexp);
01324
01325 lwidth = setup->grwid * nx / (2. * pow(LOG2, 1. / exponent));
01326
01327 }
01328 else if (strcmp(setup->model, "gaussian") == 0) {
01329
01330 lwidth = setup->grwid * nx / fwhm_ratio;
01331
01332 }
01333 else {
01334
01335
01336
01337
01338
01339 gi_error("Unsupported line model encountered!");
01340
01341 }
01342
01343
01344
01345
01346
01347
01348
01349
01350 _giraffe_line_fit_setup(model, lwidth, xmin, y, sigma, setup,
01351 &lflags);
01352
01353
01354 if (lflags == LF_R_NONE) {
01355
01356 cxint xline = giraffe_model_get_parameter(model, "Center");
01357
01358 cxdouble hwidth = 0.;
01359
01360 cxint status = 0;
01361
01362
01363
01364
01365
01366
01367 status = giraffe_model_fit(model, x, y, sigma);
01368
01369
01370 amplitude = giraffe_model_get_parameter(model, "Amplitude");
01371 background = giraffe_model_get_parameter(model, "Background");
01372 center = giraffe_model_get_parameter(model, "Center");
01373
01374
01375
01376
01377
01378
01379
01380 if (strcmp(setup->model, "psfexp") == 0) {
01381
01382 width1 = giraffe_model_get_parameter(model, "Width1");
01383 exponent = giraffe_model_get_parameter(model, "Width2");
01384
01385
01386 gwidth = 2. * pow(width1 * LOG2, 1. / exponent);
01387
01388 }
01389 else if (strcmp(setup->model, "psfexp2") == 0) {
01390
01391 width1 = giraffe_model_get_parameter(model, "Width1");
01392 exponent = giraffe_model_get_parameter(model, "Width2");
01393
01394
01395 gwidth = 2. * pow(LOG2, 1. / exponent) * width1;
01396
01397 }
01398 else if (strcmp(setup->model, "gaussian") == 0) {
01399
01400 width1 = giraffe_model_get_parameter(model, "Width1");
01401
01402
01403 gwidth = width1 * fwhm_ratio;
01404
01405 }
01406 else {
01407
01408
01409
01410
01411
01412 gi_error("Unsupported line model encountered!");
01413
01414 }
01415
01416 hwidth = gwidth / 2.;
01417 iterations = giraffe_model_get_position(model);
01418
01419
01420
01421
01422
01423
01424
01425 if (status < 0) {
01426
01427
01428 lflags |= LF_R_ERROR;
01429
01430 }
01431
01432 if (iterations >= giraffe_model_get_iterations(model)) {
01433
01434
01435 lflags |= LF_R_NITER;
01436
01437 }
01438
01439 if (xmin > center || center > xmax) {
01440
01441
01442 lflags |= LF_R_CENTR;
01443
01444 }
01445
01446 if ((center - hwidth) < xmin) {
01447
01448
01449 lflags |= LF_R_LEFT;
01450
01451 }
01452
01453 if ((center + hwidth) > xmax) {
01454
01455
01456 lflags |= LF_R_RIGHT;
01457
01458 }
01459
01460 if ((center - xline) >= setup->offst) {
01461
01462
01463 lflags |= LF_R_OFFST;
01464
01465 }
01466
01467 if (width1 < 0. || exponent < 0.) {
01468
01469
01470 lflags |= LF_R_BADLN;
01471
01472 }
01473
01474 if (gwidth > (xmax - xmin)) {
01475
01476
01477 lflags |= LF_R_WIDTH;
01478
01479 }
01480
01481 if (gwidth < (setup->grwid * nx * setup->wfact)) {
01482
01483
01484 lflags |= LF_R_RESOL;
01485
01486 }
01487
01488 if (gwidth > (setup->grwid * nx / setup->wfact)) {
01489
01490
01491 lflags |= LF_R_RESOL;
01492
01493 }
01494
01495 }
01496
01497
01498
01499
01500
01501
01502
01503
01504 giraffe_linedata_set_status(lines, i, j, lflags);
01505
01506 giraffe_linedata_set(lines, "Iterations", i, j,iterations);
01507 giraffe_linedata_set(lines, "Chi-square", i, j,
01508 giraffe_model_get_chisq(model));
01509 giraffe_linedata_set(lines, "DoF", i, j,
01510 giraffe_model_get_df(model));
01511 giraffe_linedata_set(lines, "R-square", i, j,
01512 giraffe_model_get_rsquare(model));
01513 giraffe_linedata_set(lines, "Xccd", i, j, xccd);
01514 giraffe_linedata_set(lines, "Yccd", i, j, yccd);
01515
01516
01517
01518
01519
01520
01521
01522
01523
01524 giraffe_linedata_set(lines, "Amplitude", i, j, amplitude);
01525 giraffe_linedata_set(lines, "Background", i, j, background);
01526 giraffe_linedata_set(lines, "Center", i, j, center);
01527 giraffe_linedata_set(lines, "Width1", i, j, width1);
01528
01529 if (strncmp(setup->model, "psfexp", 6) == 0) {
01530 giraffe_linedata_set(lines, "Width2", i, j, exponent);
01531 }
01532
01533 giraffe_linedata_set(lines, "FWHM", i, j, gwidth);
01534
01535
01536
01537 error = giraffe_model_get_sigma(model, "Amplitude");
01538 giraffe_linedata_set(lines, "dAmplitude", i, j, error);
01539
01540 error = giraffe_model_get_sigma(model, "Center");
01541 giraffe_linedata_set(lines, "dCenter", i, j, error);
01542
01543 error = giraffe_model_get_sigma(model, "Background");
01544 giraffe_linedata_set(lines, "dBackground", i, j, error);
01545
01546 error = giraffe_model_get_sigma(model, "Width1");
01547 giraffe_linedata_set(lines, "dWidth1", i, j, error);
01548
01549 if (strncmp(setup->model, "psfexp", 6) == 0) {
01550 error = giraffe_model_get_sigma(model, "Width2");
01551 giraffe_linedata_set(lines, "dWidth2", i, j, error);
01552 }
01553
01554 }
01555
01556 }
01557
01558 cpl_matrix_delete(x);
01559 cpl_matrix_delete(y);
01560 cpl_matrix_delete(sigma);
01561
01562 giraffe_model_delete(model);
01563
01564 return 0;
01565
01566 }
01567
01568
01569 inline static cpl_image *
01570 _giraffe_psf_fit(GiLineData *lines, const GiLocalization *localization,
01571 GiTable *fibers, GiTable *slitgeometry, GiSCFitParams *setup)
01572 {
01573
01574 const cxchar *const fctid = "_giraffe_psf_fit";
01575
01576
01577 cxint i;
01578 cxint status = 0;
01579 cxint ngood = 0;
01580 cxint nlines = 0;
01581 cxint nsubslits = 1;
01582 cxint nx = 0;
01583
01584 cpl_table *_fibers = NULL;
01585
01586 cpl_image *locy = NULL;
01587 cpl_image *locw = NULL;
01588 cpl_image *psfwidth = NULL;
01589
01590
01591 cx_assert(lines != NULL);
01592 cx_assert(localization != NULL);
01593 cx_assert(fibers != NULL);
01594 cx_assert(slitgeometry != NULL);
01595 cx_assert(setup != NULL);
01596
01597 _fibers = giraffe_table_get(fibers);
01598 cx_assert(_fibers != NULL);
01599
01600 locy = giraffe_image_get(localization->locy);
01601 cx_assert(locy != NULL);
01602
01603 locw = giraffe_image_get(localization->locw);
01604 cx_assert(locw != NULL);
01605
01606 nx = cpl_image_get_size_y(locy);
01607 nlines = giraffe_linedata_lines(lines);
01608
01609 psfwidth = cpl_image_new(cpl_table_get_nrow(_fibers), nx,
01610 CPL_TYPE_DOUBLE);
01611
01612 if (setup->subslits == TRUE) {
01613 nsubslits = _giraffe_subslit_get_max(_fibers);
01614 }
01615
01616 for (i = 0; i < nsubslits; i++) {
01617
01618 cxint j;
01619 cxint k;
01620 cxint ssn = 0;
01621 cxint nfibers = 0;
01622 cxint ndata = 0;
01623 cxint iterations = 0;
01624 cxint accepted = 0;
01625 cxint total = 0;
01626
01627 cxdouble ymin = 0.;
01628 cxdouble ymax = 0.;
01629 cxdouble ratio = 1.;
01630
01631 cpl_matrix *xss = NULL;
01632 cpl_matrix *yss = NULL;
01633 cpl_matrix *wss = NULL;
01634 cpl_matrix *sss = NULL;
01635 cpl_matrix *nss = NULL;
01636 cpl_matrix *lss = NULL;
01637 cpl_matrix *base = NULL;
01638 cpl_matrix *fit = NULL;
01639 cpl_matrix *coeff = NULL;
01640 cpl_matrix *chebyshev = NULL;
01641
01642 cpl_table *subslit = NULL;
01643
01644 GiChebyshev2D *psffit = NULL;
01645
01646
01647 if (setup->subslits == TRUE) {
01648 subslit = _giraffe_subslit_get(_fibers, i + 1);
01649 ssn = cpl_table_get_int(subslit, "SSN", 0, NULL);
01650
01651 cx_assert(ssn == i + 1);
01652 }
01653 else {
01654 subslit = cpl_table_duplicate(_fibers);
01655 ssn = 0;
01656 }
01657
01658 if (subslit == NULL) {
01659 continue;
01660 }
01661
01662 _giraffe_subslit_range(subslit, locy, locw, &ymin, &ymax);
01663
01664 nfibers = cpl_table_get_nrow(subslit);
01665 ndata = nfibers * nlines;
01666
01667
01668 xss = cpl_matrix_new(ndata, 1);
01669 yss = cpl_matrix_new(ndata, 1);
01670 wss = cpl_matrix_new(1, ndata);
01671 sss = cpl_matrix_new(ndata, 1);
01672 nss = cpl_matrix_new(ndata, 1);
01673 lss = cpl_matrix_new(ndata, 1);
01674
01675
01676
01677
01678
01679
01680
01681 k = 0;
01682
01683 for (j = 0; j < nfibers; j++) {
01684
01685 cxint l;
01686 cxint n = cpl_table_get_int(subslit, "INDEX", j, NULL) - 1;
01687
01688 for (l = 0; l < nlines; l++) {
01689
01690 cxdouble value = 0.;
01691 cxdouble yccd = giraffe_linedata_get(lines, "Yccd", n, l);
01692
01693 if (giraffe_linedata_get_status(lines, n, l) != 0) {
01694 continue;
01695 }
01696
01697 if (yccd < ymin || yccd > ymax) {
01698 continue;
01699 }
01700
01701 value = giraffe_linedata_get(lines, "Xccd", n, l);
01702 cpl_matrix_set(xss, k, 0, value);
01703
01704 cpl_matrix_set(yss, k, 0, yccd);
01705
01706
01707
01708
01709
01710
01711
01712
01713 value = giraffe_linedata_get(lines, "FWHM", n, l);
01714 cpl_matrix_set(wss, 0, k, value);
01715
01716 value = giraffe_linedata_get(lines, "dWidth1", n, l);
01717 cpl_matrix_set(sss, k, 0, value);
01718
01719 cpl_matrix_set(nss, k, 0, n);
01720 cpl_matrix_set(lss, k, 0, l);
01721
01722 ++k;
01723
01724 }
01725
01726 }
01727
01728 if (k == 0) {
01729 cpl_msg_debug(fctid, "Skipping subslit %d: No input lines left! "
01730 "All lines have non-zero status or are beyond the "
01731 "subslit boundaries (%.4f, %.4f).", ssn, ymin, ymax);
01732 continue;
01733 }
01734
01735
01736
01737
01738
01739 cpl_matrix_set_size(xss, k, 1);
01740 cpl_matrix_set_size(yss, k, 1);
01741 cpl_matrix_set_size(wss, 1, k);
01742 cpl_matrix_set_size(sss, k, 1);
01743 cpl_matrix_set_size(nss, k, 1);
01744 cpl_matrix_set_size(lss, k, 1);
01745
01746
01747
01748
01749
01750
01751 iterations = 0;
01752 ratio = 1.0;
01753 accepted = cpl_matrix_get_ncol(wss);
01754 total = accepted;
01755
01756 while (accepted > 0 && iterations < setup->clip.iterations &&
01757 ratio > setup->clip.fraction) {
01758
01759 base = giraffe_chebyshev_base2d(0., ymin, nx, ymax - ymin + 1.,
01760 setup->fit.xorder + 1,
01761 setup->fit.yorder + 1, xss, yss);
01762
01763 if (coeff != NULL) {
01764 cpl_matrix_delete(coeff);
01765 coeff = NULL;
01766 }
01767
01768 coeff = giraffe_matrix_leastsq(base, wss);
01769
01770 if (coeff == NULL) {
01771 cpl_msg_debug(fctid, "Error solving linear system for "
01772 "subslit %d, skipping subslit.", ssn);
01773 break;
01774 }
01775
01776 fit = cpl_matrix_product_create(coeff, base);
01777
01778 k = 0;
01779
01780 for (j = 0; j < cpl_matrix_get_ncol(fit); j++) {
01781
01782 cxdouble _fit = cpl_matrix_get(fit, 0, j);
01783 cxdouble _wss = cpl_matrix_get(wss, 0, j);
01784 cxdouble _sss = cpl_matrix_get(sss, j, 0);
01785
01786 if (fabs(_fit - _wss) >= setup->clip.level * _sss) {
01787
01788 cxint n = (cxint)cpl_matrix_get(nss, j, 0);
01789 cxint l = (cxint)cpl_matrix_get(lss, j, 0);
01790
01791
01792
01793
01794
01795 giraffe_linedata_set_status(lines, n, l, LF_R_PSFIT);
01796 continue;
01797
01798 }
01799
01800 cpl_matrix_set(xss, k, 0, cpl_matrix_get(xss, j, 0));
01801 cpl_matrix_set(yss, k, 0, cpl_matrix_get(yss, j, 0));
01802 cpl_matrix_set(wss, 0, k, cpl_matrix_get(wss, 0, j));
01803 cpl_matrix_set(sss, k, 0, cpl_matrix_get(sss, j, 0));
01804 cpl_matrix_set(nss, k, 0, cpl_matrix_get(nss, j, 0));
01805 cpl_matrix_set(lss, k, 0, cpl_matrix_get(lss, j, 0));
01806 ++k;
01807
01808 }
01809
01810 cpl_matrix_delete(base);
01811 cpl_matrix_delete(fit);
01812
01813 if (k == accepted) {
01814
01815
01816
01817
01818
01819 break;
01820 }
01821 else {
01822 accepted = k;
01823 ratio = (cxdouble)accepted / (cxdouble)total;
01824
01825 cpl_matrix_set_size(xss, k, 1);
01826 cpl_matrix_set_size(yss, k, 1);
01827 cpl_matrix_set_size(wss, 1, k);
01828 cpl_matrix_set_size(sss, k, 1);
01829 cpl_matrix_set_size(nss, k, 1);
01830 cpl_matrix_set_size(lss, k, 1);
01831
01832 ++iterations;
01833
01834 }
01835
01836 }
01837
01838 if (accepted == 0) {
01839 cpl_msg_debug(fctid, "Subslit %d: All lines rejected.", ssn);
01840 continue;
01841 }
01842
01843 if (coeff == NULL) {
01844 continue;
01845 }
01846
01847 ngood += accepted;
01848
01849 cpl_matrix_delete(xss);
01850 cpl_matrix_delete(yss);
01851 cpl_matrix_delete(wss);
01852 cpl_matrix_delete(sss);
01853 cpl_matrix_delete(nss);
01854 cpl_matrix_delete(lss);
01855
01856
01857
01858
01859
01860
01861 xss = cpl_matrix_new(nx * nfibers, 1);
01862 yss = cpl_matrix_new(nx * nfibers, 1);
01863
01864 giraffe_compute_image_coordinates(nx, nfibers, xss, NULL);
01865
01866 for (j = 0; j < cpl_table_get_nrow(subslit); j++) {
01867
01868 const cxchar *idx = giraffe_fiberlist_query_index(subslit);
01869
01870 cxint l;
01871 cxint ns = cpl_image_get_size_x(locy);
01872 cxint cs = cpl_table_get_int(subslit, idx, j, NULL) - 1;
01873
01874 cxdouble *data = cpl_image_get_data(locy);
01875
01876
01877 for (l = 0; l < nx; l++) {
01878 cpl_matrix_set(yss, l * nfibers + j, 0, data[l * ns + cs]);
01879 }
01880
01881 }
01882
01883
01884
01885
01886
01887
01888 base = giraffe_chebyshev_base2d(0., ymin, nx, ymax - ymin + 1.,
01889 setup->fit.xorder + 1,
01890 setup->fit.yorder + 1, xss, yss);
01891
01892 fit = cpl_matrix_product_create(coeff, base);
01893
01894 cpl_matrix_delete(xss);
01895 xss = NULL;
01896
01897 cpl_matrix_delete(yss);
01898 yss = NULL;
01899
01900
01901
01902
01903
01904
01905
01906
01907
01908
01909
01910 chebyshev = cpl_matrix_wrap(setup->fit.xorder + 1,
01911 setup->fit.yorder + 1,
01912 cpl_matrix_get_data(coeff));
01913
01914 psffit = giraffe_chebyshev2d_new(setup->fit.xorder, setup->fit.yorder);
01915 status = giraffe_chebyshev2d_set(psffit, 0., nx, ymin, ymax,
01916 chebyshev);
01917
01918 if (status != 0) {
01919
01920 giraffe_chebyshev2d_delete(psffit);
01921
01922 cpl_matrix_unwrap(chebyshev);
01923
01924 cpl_matrix_delete(base);
01925 cpl_matrix_delete(coeff);
01926 cpl_matrix_delete(fit);
01927
01928 cpl_table_delete(subslit);
01929
01930 cpl_image_delete(psfwidth);
01931
01932 return NULL;
01933
01934 }
01935
01936 cpl_matrix_unwrap(chebyshev);
01937 chebyshev = NULL;
01938
01939 giraffe_chebyshev2d_delete(psffit);
01940 psffit = NULL;
01941
01942
01943
01944
01945
01946
01947 for (j = 0; j < cpl_table_get_nrow(subslit); j++) {
01948
01949 cxint l;
01950 cxint n = cpl_table_get_int(subslit, "INDEX", j, NULL) - 1;
01951 cxint ns = cpl_table_get_nrow(_fibers);
01952
01953 cxdouble *data = cpl_image_get_data(psfwidth);
01954
01955 for (l = 0; l < nx; l++) {
01956 data[l * ns + n] = cpl_matrix_get(fit, 0, l * nfibers + j);
01957 }
01958
01959 }
01960
01961 cpl_matrix_delete(base);
01962 cpl_matrix_delete(coeff);
01963 cpl_matrix_delete(fit);
01964
01965 cpl_table_delete(subslit);
01966
01967 }
01968
01969 return psfwidth;
01970
01971 }
01972
01973
01974 inline static cxint
01975 _giraffe_opticalmodel_fit(GiWlSolution *solution, GiLineData *lines,
01976 GiTable *fibers, GiTable *slitgeometry,
01977 GiOpticalModelParams *setup)
01978 {
01979
01980 const cxchar *const fctid = "_giraffe_opticalmodel_fit";
01981
01982
01983 cxint status = 0;
01984 cxint ndata = 0;
01985 cxint ngood = 0;
01986
01987 cxsize i;
01988
01989 cpl_matrix *x = NULL;
01990 cpl_matrix *y = NULL;
01991 cpl_matrix *sigma = NULL;
01992
01993 cpl_table *_fibers = NULL;
01994 cpl_table *_slitgeometry = NULL;
01995
01996 GiModel *model = NULL;
01997
01998
01999 cx_assert(solution != NULL);
02000 cx_assert(lines != NULL);
02001 cx_assert(fibers != NULL);
02002 cx_assert(slitgeometry != NULL);
02003 cx_assert(setup != NULL);
02004
02005 _fibers = giraffe_table_get(fibers);
02006 cx_assert(_fibers != NULL);
02007
02008 _slitgeometry = giraffe_table_get(slitgeometry);
02009 cx_assert(_slitgeometry != NULL);
02010
02011 model = giraffe_wlsolution_model(solution);
02012
02013
02014
02015
02016
02017
02018 ndata = giraffe_linedata_lines(lines) * giraffe_linedata_fibers(lines);
02019
02020 x = cpl_matrix_new(ndata, giraffe_model_count_arguments(model));
02021 y = cpl_matrix_new(ndata, 1);
02022 sigma = cpl_matrix_new(ndata, 1);
02023
02024 for (i = 0; i < giraffe_linedata_fibers(lines); i++) {
02025
02026 cxsize j;
02027
02028 cxdouble xf = cpl_table_get(_slitgeometry, "XF", i, NULL);
02029 cxdouble yf = cpl_table_get(_slitgeometry, "YF", i, NULL);
02030
02031
02032 for (j = 0; j < giraffe_linedata_lines(lines); j++) {
02033
02034 if (giraffe_linedata_get_status(lines, i, j) != 0) {
02035 continue;
02036 }
02037
02038
02039
02040
02041 if (giraffe_linedata_get(lines, "dCenter", i, j) <= 0.) {
02042 continue;
02043 }
02044
02045 cpl_matrix_set(x, ngood, 0,
02046 giraffe_linedata_get_wavelength(lines, j));
02047 cpl_matrix_set(x, ngood, 1, xf);
02048 cpl_matrix_set(x, ngood, 2, yf);
02049
02050 cpl_matrix_set(y, ngood, 0,
02051 giraffe_linedata_get(lines, "Center", i, j));
02052 cpl_matrix_set(sigma, ngood, 0,
02053 giraffe_linedata_get(lines, "dCenter", i, j));
02054
02055 ++ngood;
02056
02057 }
02058
02059 }
02060
02061 cpl_msg_debug(fctid, "Using %d of %d line positions for optical "
02062 "model fit.", ngood, ndata);
02063
02064 if (ngood == 0) {
02065
02066 cpl_matrix_delete(x);
02067 cpl_matrix_delete(y);
02068 cpl_matrix_delete(sigma);
02069
02070 return 1;
02071 }
02072
02073
02074
02075
02076
02077
02078 cpl_matrix_set_size(x, ngood, giraffe_model_count_arguments(model));
02079 cpl_matrix_set_size(y, ngood, 1);
02080 cpl_matrix_set_size(sigma, ngood, 1);
02081
02082
02083
02084
02085
02086
02087 giraffe_model_freeze(model);
02088
02089 if (setup->flags & OPTM_FLENGTH) {
02090 giraffe_model_thaw_parameter(model, "FocalLength");
02091 }
02092
02093 if (setup->flags & OPTM_GCAMERA) {
02094 giraffe_model_thaw_parameter(model, "Magnification");
02095 }
02096
02097 if (setup->flags & OPTM_THETA) {
02098 giraffe_model_thaw_parameter(model, "Angle");
02099 }
02100
02101 if (strcmp(giraffe_model_get_name(model), "xoptmod2") == 0) {
02102 if (setup->flags & OPTM_SX) {
02103 giraffe_model_thaw_parameter(model, "Sdx");
02104 }
02105
02106 if (setup->flags & OPTM_SY) {
02107 giraffe_model_thaw_parameter(model, "Sdy");
02108 }
02109
02110 if (setup->flags & OPTM_SPHI) {
02111 giraffe_model_thaw_parameter(model, "Sphi");
02112 }
02113 }
02114
02115 giraffe_model_set_iterations(model, setup->fit.iterations);
02116 giraffe_model_set_tests(model, setup->fit.tests);
02117 giraffe_model_set_delta(model, setup->fit.delta);
02118
02119
02120
02121
02122
02123
02124 status = giraffe_model_fit(model, x, y, sigma);
02125
02126 if (status < 0) {
02127
02128 cpl_matrix_delete(x);
02129 cpl_matrix_delete(y);
02130 cpl_matrix_delete(sigma);
02131
02132 return 2;
02133
02134 }
02135
02136 cpl_matrix_delete(x);
02137 cpl_matrix_delete(y);
02138 cpl_matrix_delete(sigma);
02139
02140 return 0;
02141
02142 }
02143
02144
02145 inline static cxint
02146 _giraffe_opticalmodel_format(cx_string *s, const GiModel *model,
02147 GiOpticalModelInfo info)
02148 {
02149
02150 const cxchar *name = NULL;
02151
02152 cxbool offsets = FALSE;
02153
02154 cxint status = 0;
02155
02156
02157 cx_assert(s != NULL);
02158
02159 if (model == NULL) {
02160 return -1;
02161 }
02162
02163 name = giraffe_model_get_name(model);
02164
02165 if (name == NULL || strncmp(name, "xoptmod", 7) != 0) {
02166 return -2;
02167 }
02168 else {
02169 if (strncmp(name, "xoptmod2", 8) == 0) {
02170 offsets = TRUE;
02171 }
02172 }
02173
02174 switch (info) {
02175
02176 case GI_OPTM_PARAMETER_VALUES:
02177 {
02178
02179 cxdouble fcoll = 0.;
02180 cxdouble gcam = 0.;
02181 cxdouble theta = 0.;
02182
02183 fcoll = giraffe_model_get_parameter(model, "FocalLength");
02184 gcam = giraffe_model_get_parameter(model, "Magnification");
02185 theta = giraffe_model_get_parameter(model, "Angle");
02186
02187 cx_string_sprintf(s, "focal length = %.6f, camera "
02188 "magnification = %.6f, grating angle = %.9f",
02189 fcoll, gcam, theta);
02190
02191 if (offsets == TRUE) {
02192
02193 cxdouble sdx = 0.;
02194 cxdouble sdy = 0.;
02195 cxdouble sphi = 0.;
02196
02197 cx_string *_s = cx_string_new();
02198
02199 sdx = giraffe_model_get_parameter(model, "Sdx");
02200 sdy = giraffe_model_get_parameter(model, "Sdy");
02201 sphi = giraffe_model_get_parameter(model, "Sphi");
02202
02203 cx_string_sprintf(_s, ", slit x-shift = %.9f, slit "
02204 "y-shift = %.9f, slit rotation = %.9f",
02205 sdx, sdy, sphi);
02206 cx_string_append(s, cx_string_get(_s));
02207
02208 cx_string_delete(_s);
02209 _s = NULL;
02210
02211 }
02212
02213 break;
02214 }
02215
02216 case GI_OPTM_PARAMETER_ERRORS:
02217 {
02218
02219 cxdouble fcoll = 0.;
02220 cxdouble gcam = 0.;
02221 cxdouble theta = 0.;
02222
02223 fcoll = giraffe_model_get_sigma(model, "FocalLength");
02224 gcam = giraffe_model_get_sigma(model, "Magnification");
02225 theta = giraffe_model_get_sigma(model, "Angle");
02226
02227 cx_string_sprintf(s, "focal length = %.6f, camera "
02228 "magnification = %.6f, grating angle = %.9f",
02229 fcoll, gcam, theta);
02230
02231 if (offsets == TRUE) {
02232
02233 cxdouble sdx = 0.;
02234 cxdouble sdy = 0.;
02235 cxdouble sphi = 0.;
02236
02237 cx_string *_s = cx_string_new();
02238
02239 sdx = giraffe_model_get_sigma(model, "Sdx");
02240 sdy = giraffe_model_get_sigma(model, "Sdy");
02241 sphi = giraffe_model_get_sigma(model, "Sphi");
02242
02243 cx_string_sprintf(_s, ", slit x-shift = %.9f, slit "
02244 "y-shift = %.9f, slit rotation = %.9f",
02245 sdx, sdy, sphi);
02246 cx_string_append(s, cx_string_get(_s));
02247
02248 cx_string_delete(_s);
02249 _s = NULL;
02250
02251 }
02252
02253 break;
02254 }
02255
02256 case GI_OPTM_PARAMETER_STATUS:
02257 {
02258
02259 const cxchar *const s_free = "free";
02260 const cxchar *const s_frozen = "frozen";
02261 const cxchar *t = NULL;
02262
02263 cx_string *buffer = cx_string_new();
02264
02265
02266 t = giraffe_model_frozen_parameter(model, "FocalLength") ?
02267 s_frozen : s_free;
02268 cx_string_sprintf(buffer, "focal length = %s", t);
02269 cx_string_set(s, cx_string_get(buffer));
02270
02271 t = giraffe_model_frozen_parameter(model, "Magnification") ?
02272 s_frozen : s_free;
02273 cx_string_sprintf(buffer, ", camera magnification = %s", t);
02274 cx_string_append(s, cx_string_get(buffer));
02275
02276 t = giraffe_model_frozen_parameter(model, "Angle") ?
02277 s_frozen : s_free;
02278 cx_string_sprintf(buffer, ", grating angle = %s", t);
02279 cx_string_append(s, cx_string_get(buffer));
02280
02281
02282 if (offsets == TRUE) {
02283
02284 t = giraffe_model_frozen_parameter(model, "Sdx") ?
02285 s_frozen : s_free;
02286 cx_string_sprintf(buffer, ", slit x-shift = %s", t);
02287 cx_string_append(s, cx_string_get(buffer));
02288
02289 t = giraffe_model_frozen_parameter(model, "Sdy") ?
02290 s_frozen : s_free;
02291 cx_string_sprintf(buffer, ", slit y-shift = %s", t);
02292 cx_string_append(s, cx_string_get(buffer));
02293
02294 t = giraffe_model_frozen_parameter(model, "Sphi") ?
02295 s_frozen : s_free;
02296 cx_string_sprintf(buffer, ", slit rotation = %s", t);
02297 cx_string_append(s, cx_string_get(buffer));
02298
02299 }
02300
02301 cx_string_delete(buffer);
02302 buffer = NULL;
02303
02304 break;
02305 }
02306
02307 default:
02308 status = -2;
02309 break;
02310
02311 }
02312
02313 return status;
02314
02315 }
02316
02317
02318 inline static cpl_image *
02319 _giraffe_residuals_fit(GiWlResiduals *residuals, GiLineData *lines,
02320 const GiLocalization *localization, GiTable *fibers,
02321 GiTable *slitgeometry, GiSCFitParams *setup)
02322 {
02323
02324 const cxchar *const fctid = "_giraffe_residuals_fit";
02325
02326
02327 cxint i;
02328 cxint status = 0;
02329 cxint ngood = 0;
02330 cxint nlines = 0;
02331 cxint nsubslits = 1;
02332 cxint nx = 0;
02333
02334 cpl_table *_fibers = NULL;
02335
02336 cpl_image *locy = NULL;
02337 cpl_image *locw = NULL;
02338 cpl_image *xresiduals = NULL;
02339
02340
02341 cx_assert(lines != NULL);
02342 cx_assert(localization != NULL);
02343 cx_assert(fibers != NULL);
02344 cx_assert(slitgeometry != NULL);
02345 cx_assert(setup != NULL);
02346
02347 _fibers = giraffe_table_get(fibers);
02348 cx_assert(_fibers != NULL);
02349
02350 locy = giraffe_image_get(localization->locy);
02351 cx_assert(locy != NULL);
02352
02353 locw = giraffe_image_get(localization->locw);
02354 cx_assert(locw != NULL);
02355
02356 nx = cpl_image_get_size_y(locy);
02357 nlines = giraffe_linedata_lines(lines);
02358
02359 xresiduals = cpl_image_new(cpl_table_get_nrow(_fibers), nx,
02360 CPL_TYPE_DOUBLE);
02361
02362 if (setup->subslits == TRUE) {
02363 nsubslits = _giraffe_subslit_get_max(_fibers);
02364 }
02365
02366 for (i = 0; i < nsubslits; i++) {
02367
02368 cxint j;
02369 cxint k;
02370 cxint ssn = 0;
02371 cxint nfibers = 0;
02372 cxint ndata = 0;
02373 cxint iterations = 0;
02374 cxint accepted = 0;
02375 cxint total = 0;
02376
02377 cxdouble ymin = 0.;
02378 cxdouble ymax = 0.;
02379 cxdouble ratio = 1.;
02380 cxdouble sigma = 0.;
02381
02382 cpl_matrix *xss = NULL;
02383 cpl_matrix *yss = NULL;
02384 cpl_matrix *rss = NULL;
02385 cpl_matrix *sss = NULL;
02386 cpl_matrix *nss = NULL;
02387 cpl_matrix *lss = NULL;
02388 cpl_matrix *base = NULL;
02389 cpl_matrix *fit = NULL;
02390 cpl_matrix *coeff = NULL;
02391 cpl_matrix *chebyshev = NULL;
02392
02393 cpl_table *subslit = NULL;
02394
02395 GiChebyshev2D *xwsfit = NULL;
02396
02397
02398 if (setup->subslits == TRUE) {
02399 subslit = _giraffe_subslit_get(_fibers, i + 1);
02400 ssn = cpl_table_get_int(subslit, "SSN", 0, NULL);
02401
02402 cx_assert(ssn == i + 1);
02403 }
02404 else {
02405 subslit = cpl_table_duplicate(_fibers);
02406 ssn = 0;
02407 }
02408
02409 if (subslit == NULL) {
02410 continue;
02411 }
02412
02413 _giraffe_subslit_range(subslit, locy, locw, &ymin, &ymax);
02414
02415 nfibers = cpl_table_get_nrow(subslit);
02416 ndata = nfibers * nlines;
02417
02418
02419 xss = cpl_matrix_new(ndata, 1);
02420 yss = cpl_matrix_new(ndata, 1);
02421 rss = cpl_matrix_new(1, ndata);
02422 sss = cpl_matrix_new(ndata, 1);
02423 nss = cpl_matrix_new(ndata, 1);
02424 lss = cpl_matrix_new(ndata, 1);
02425
02426
02427
02428
02429
02430
02431
02432 k = 0;
02433
02434 for (j = 0; j < nfibers; j++) {
02435
02436 cxint l;
02437 cxint n = cpl_table_get_int(subslit, "INDEX", j, NULL) - 1;
02438
02439 for (l = 0; l < nlines; l++) {
02440
02441 cxdouble value = 0.;
02442 cxdouble xccd = giraffe_linedata_get(lines, "Xccd", n, l);
02443 cxdouble yccd = giraffe_linedata_get(lines, "Yccd", n, l);
02444
02445 if (giraffe_linedata_get_status(lines, n, l) != 0) {
02446 continue;
02447 }
02448
02449 if (yccd < ymin || yccd > ymax) {
02450 continue;
02451 }
02452
02453 cpl_matrix_set(xss, k, 0, xccd);
02454 cpl_matrix_set(yss, k, 0, yccd);
02455
02456 value = xccd - giraffe_linedata_get(lines, "Center", n, l);
02457
02458 cpl_matrix_set(rss, 0, k, value);
02459 giraffe_linedata_set(lines, "Xoff", n, l, value);
02460
02461 value = giraffe_linedata_get(lines, "dCenter", n, l);
02462 cpl_matrix_set(sss, k, 0, value);
02463
02464 cpl_matrix_set(nss, k, 0, n);
02465 cpl_matrix_set(lss, k, 0, l);
02466
02467 ++k;
02468
02469 }
02470
02471 }
02472
02473 if (k == 0) {
02474 cpl_msg_debug(fctid, "Skipping subslit %d: No input lines left! "
02475 "All lines have non-zero status or are beyond the "
02476 "subslit boundaries (%.4f, %.4f).", ssn, ymin, ymax);
02477 continue;
02478 }
02479
02480
02481
02482
02483
02484 cpl_matrix_set_size(xss, k, 1);
02485 cpl_matrix_set_size(yss, k, 1);
02486 cpl_matrix_set_size(rss, 1, k);
02487 cpl_matrix_set_size(sss, k, 1);
02488 cpl_matrix_set_size(nss, k, 1);
02489 cpl_matrix_set_size(lss, k, 1);
02490
02491
02492
02493
02494
02495
02496
02497 sigma = cpl_matrix_get_median(sss);
02498
02499
02500
02501
02502
02503
02504 iterations = 0;
02505 ratio = 1.0;
02506 accepted = cpl_matrix_get_ncol(rss);
02507 total = accepted;
02508
02509 while (accepted > 0 && iterations < setup->clip.iterations &&
02510 ratio > setup->clip.fraction) {
02511
02512 base = giraffe_chebyshev_base2d(0., ymin, nx, ymax - ymin + 1.,
02513 setup->fit.xorder + 1,
02514 setup->fit.yorder + 1, xss, yss);
02515
02516 if (coeff != NULL) {
02517 cpl_matrix_delete(coeff);
02518 coeff = NULL;
02519 }
02520
02521 coeff = giraffe_matrix_leastsq(base, rss);
02522
02523 if (coeff == NULL) {
02524 cpl_msg_debug(fctid, "Error solving linear system for "
02525 "subslit %d, skipping subslit.", ssn);
02526 break;
02527 }
02528
02529 fit = cpl_matrix_product_create(coeff, base);
02530
02531 k = 0;
02532
02533 for (j = 0; j < cpl_matrix_get_ncol(fit); j++) {
02534
02535 cxdouble _fit = cpl_matrix_get(fit, 0, j);
02536 cxdouble _rss = cpl_matrix_get(rss, 0, j);
02537
02538 if (fabs(_fit - _rss) >= setup->clip.level * sigma) {
02539
02540 cxint n = (cxint)cpl_matrix_get(nss, j, 0);
02541 cxint l = (cxint)cpl_matrix_get(lss, j, 0);
02542
02543
02544
02545
02546
02547 giraffe_linedata_set_status(lines, n, l, LF_R_XRFIT);
02548 continue;
02549
02550 }
02551
02552 cpl_matrix_set(xss, k, 0, cpl_matrix_get(xss, j, 0));
02553 cpl_matrix_set(yss, k, 0, cpl_matrix_get(yss, j, 0));
02554 cpl_matrix_set(rss, 0, k, cpl_matrix_get(rss, 0, j));
02555 cpl_matrix_set(sss, k, 0, cpl_matrix_get(sss, j, 0));
02556 cpl_matrix_set(nss, k, 0, cpl_matrix_get(nss, j, 0));
02557 cpl_matrix_set(lss, k, 0, cpl_matrix_get(lss, j, 0));
02558 ++k;
02559
02560 }
02561
02562 cpl_matrix_delete(base);
02563 cpl_matrix_delete(fit);
02564
02565 if (k == accepted) {
02566
02567
02568
02569
02570
02571 break;
02572 }
02573 else {
02574 accepted = k;
02575 ratio = (cxdouble)accepted / (cxdouble)total;
02576
02577 cpl_matrix_set_size(xss, k, 1);
02578 cpl_matrix_set_size(yss, k, 1);
02579 cpl_matrix_set_size(rss, 1, k);
02580 cpl_matrix_set_size(sss, k, 1);
02581 cpl_matrix_set_size(nss, k, 1);
02582 cpl_matrix_set_size(lss, k, 1);
02583
02584 ++iterations;
02585
02586 }
02587
02588 }
02589
02590 if (accepted == 0) {
02591 cpl_msg_debug(fctid, "Subslit %d: All lines rejected.", ssn);
02592 continue;
02593 }
02594
02595 if (coeff == NULL) {
02596 continue;
02597 }
02598
02599 ngood += accepted;
02600
02601 cpl_matrix_delete(xss);
02602 cpl_matrix_delete(yss);
02603 cpl_matrix_delete(rss);
02604 cpl_matrix_delete(sss);
02605 cpl_matrix_delete(nss);
02606 cpl_matrix_delete(lss);
02607
02608
02609
02610
02611
02612
02613 xss = cpl_matrix_new(nx * nfibers, 1);
02614 yss = cpl_matrix_new(nx * nfibers, 1);
02615
02616 giraffe_compute_image_coordinates(nx, nfibers, xss, NULL);
02617
02618 for (j = 0; j < cpl_table_get_nrow(subslit); j++) {
02619
02620 const cxchar *idx = giraffe_fiberlist_query_index(subslit);
02621
02622 cxint l;
02623 cxint ns = cpl_image_get_size_x(locy);
02624 cxint cs = cpl_table_get_int(subslit, idx, j, NULL) - 1;
02625
02626 cxdouble *data = cpl_image_get_data(locy);
02627
02628
02629 for (l = 0; l < nx; l++) {
02630 cpl_matrix_set(yss, l * nfibers + j, 0, data[l * ns + cs]);
02631 }
02632
02633 }
02634
02635
02636
02637
02638
02639
02640 base = giraffe_chebyshev_base2d(0., ymin, nx, ymax - ymin + 1.,
02641 setup->fit.xorder + 1,
02642 setup->fit.yorder + 1, xss, yss);
02643
02644 fit = cpl_matrix_product_create(coeff, base);
02645
02646 cpl_matrix_delete(xss);
02647 xss = NULL;
02648
02649 cpl_matrix_delete(yss);
02650 yss = NULL;
02651
02652
02653
02654
02655
02656
02657
02658
02659
02660
02661
02662
02663
02664 chebyshev = cpl_matrix_wrap(setup->fit.xorder + 1,
02665 setup->fit.yorder + 1,
02666 cpl_matrix_get_data(coeff));
02667
02668 xwsfit = giraffe_chebyshev2d_new(setup->fit.xorder, setup->fit.yorder);
02669 status = giraffe_chebyshev2d_set(xwsfit, 0., nx, ymin, ymax,
02670 chebyshev);
02671
02672 if (status != 0) {
02673
02674 giraffe_chebyshev2d_delete(xwsfit);
02675
02676 cpl_matrix_unwrap(chebyshev);
02677
02678 cpl_matrix_delete(base);
02679 cpl_matrix_delete(coeff);
02680 cpl_matrix_delete(fit);
02681
02682 cpl_table_delete(subslit);
02683
02684 cpl_image_delete(xresiduals);
02685
02686 return NULL;
02687
02688 }
02689
02690 cpl_matrix_unwrap(chebyshev);
02691 chebyshev = NULL;
02692
02693 giraffe_wlresiduals_set(residuals, ssn, xwsfit);
02694 xwsfit = NULL;
02695
02696
02697
02698
02699
02700
02701 for (j = 0; j < cpl_table_get_nrow(subslit); j++) {
02702
02703 cxint l;
02704 cxint n = cpl_table_get_int(subslit, "INDEX", j, NULL) - 1;
02705 cxint ns = cpl_table_get_nrow(_fibers);
02706
02707 cxdouble *data = cpl_image_get_data(xresiduals);
02708
02709 for (l = 0; l < nx; l++) {
02710 data[l * ns + n] = cpl_matrix_get(fit, 0, l * nfibers + j);
02711 }
02712
02713 }
02714
02715 cpl_matrix_delete(base);
02716 cpl_matrix_delete(coeff);
02717 cpl_matrix_delete(fit);
02718
02719 cpl_table_delete(subslit);
02720
02721 }
02722
02723 return xresiduals;
02724
02725 }
02726
02727
02728 inline static cxdouble
02729 _giraffe_compute_statistics(const GiLineData *lines, const cpl_image *xwsfit,
02730 const cpl_image *lflags)
02731 {
02732
02733 cxint i;
02734 cxint nlines = 0;
02735 cxint nfibers = 0;
02736
02737 cxdouble sum = 0.;
02738 cxdouble rms = 0.;
02739 cxdouble *_xccd;
02740
02741 cpl_image *xccd = NULL;
02742
02743
02744 cx_assert(lines != NULL);
02745
02746
02747 nlines = giraffe_linedata_lines(lines);
02748 nfibers = giraffe_linedata_fibers(lines);
02749
02750 xccd = cpl_image_duplicate(giraffe_linedata_get_data(lines, "Xccd"));
02751
02752 if (xwsfit != NULL) {
02753
02754 cpl_image *residuals = NULL;
02755
02756
02757 cx_assert(lflags != NULL);
02758
02759 residuals = cpl_image_new(giraffe_linedata_fibers(lines),
02760 giraffe_linedata_lines(lines),
02761 CPL_TYPE_DOUBLE);
02762
02763 _giraffe_get_residuals(residuals, xccd, xwsfit);
02764 _giraffe_apply_residuals(xccd, residuals, lflags, 0.);
02765
02766 cpl_image_delete(residuals);
02767 residuals = NULL;
02768
02769 }
02770
02771 _xccd = cpl_image_get_data(xccd);
02772
02773 for (i = 0; i < nfibers; i++) {
02774
02775 cxint j;
02776
02777 for (j = 0; j < nlines; j++) {
02778
02779 if (giraffe_linedata_get_status(lines, i, j) == LF_R_NONE) {
02780
02781 cxdouble center = giraffe_linedata_get(lines, "Center", i, j);
02782
02783 sum += pow(center - _xccd[j * nfibers + i], 2.);
02784
02785 }
02786
02787 }
02788
02789 }
02790
02791 cpl_image_delete(xccd);
02792
02793 rms = sqrt(sum / CX_MAX(giraffe_linedata_accepted(lines), 1.));
02794
02795 return rms;
02796
02797 }
02798
02799
02800 inline static cxint
02801 _giraffe_convert_wlsolution(GiTable *result, const GiWlSolution *solution,
02802 const GiImage *spectra, const GiGrating *setup,
02803 const GiWCalInfo *info, const GiWCalConfig *config)
02804 {
02805
02806 cxint i;
02807 cxint status = 0;
02808 cxint sign = 1;
02809
02810 cxdouble value = 0.;
02811 cxdouble scale = 0.;
02812 cxdouble xccd[2] = {0., 0.};
02813
02814 cx_string *s = NULL;
02815
02816 cpl_propertylist *properties = NULL;
02817
02818 cpl_table *coeffs = NULL;
02819
02820 const GiModel *model = NULL;
02821
02822 const GiWlResiduals *residuals = NULL;
02823
02824
02825 cx_assert(result != NULL);
02826 cx_assert(solution != NULL);
02827
02828 s = cx_string_new();
02829
02830 properties =
02831 cpl_propertylist_duplicate(giraffe_image_get_properties(spectra));
02832
02833
02834
02835
02836
02837 cpl_propertylist_erase(properties, "NAXIS1");
02838 cpl_propertylist_erase(properties, "NAXIS2");
02839 cpl_propertylist_erase(properties, GIALIAS_DATAMIN);
02840 cpl_propertylist_erase(properties, GIALIAS_DATAMAX);
02841 cpl_propertylist_erase(properties, GIALIAS_EXTNAME);
02842
02843 cpl_propertylist_erase(properties, GIALIAS_PROCATG);
02844 cpl_propertylist_erase(properties, GIALIAS_PROTYPE);
02845 cpl_propertylist_erase(properties, GIALIAS_DATAMEAN);
02846 cpl_propertylist_erase(properties, GIALIAS_DATAMEDI);
02847 cpl_propertylist_erase(properties, GIALIAS_DATASIG);
02848
02849 cpl_propertylist_update_string(properties, GIALIAS_GIRFTYPE,
02850 "WAVCOEFFTAB");
02851 cpl_propertylist_set_comment(properties, GIALIAS_GIRFTYPE,
02852 "Giraffe frame type.");
02853
02854
02855
02856
02857
02858
02859
02860
02861
02862
02863
02864
02865
02866
02867
02868
02869
02870
02871
02872
02873
02874
02875
02876 cpl_propertylist_update_string(properties, GIALIAS_WSOL_LMNAME,
02877 config->line_model);
02878 cpl_propertylist_set_comment(properties, GIALIAS_WSOL_LMNAME,
02879 "Line profile model");
02880
02881 cpl_propertylist_update_bool(properties, GIALIAS_WSOL_LMRES, info->residuals);
02882 cpl_propertylist_set_comment(properties, GIALIAS_WSOL_LMRES,
02883 "Line detection optical model residuals flag");
02884
02885 cpl_propertylist_update_int(properties, GIALIAS_WSOL_LMWIDTH, info->width);
02886 cpl_propertylist_set_comment(properties, GIALIAS_WSOL_LMWIDTH,
02887 "Line detection window size [pxl]");
02888
02889 cpl_propertylist_update_double(properties, GIALIAS_WSOL_LMTHRESH,
02890 config->line_threshold);
02891 cpl_propertylist_set_comment(properties, GIALIAS_WSOL_LMTHRESH,
02892 "Calibration line threshold");
02893
02894 cpl_propertylist_update_int(properties, GIALIAS_WSOL_LMITER,
02895 config->line_niter);
02896 cpl_propertylist_set_comment(properties, GIALIAS_WSOL_LMITER,
02897 "Line profile fit maximum number "
02898 "of iterations");
02899
02900 cpl_propertylist_update_int(properties, GIALIAS_WSOL_LMTEST,
02901 config->line_ntest);
02902 cpl_propertylist_set_comment(properties, GIALIAS_WSOL_LMTEST,
02903 "Line profile fit maximum number "
02904 "of chi-square tests");
02905
02906 cpl_propertylist_update_double(properties, GIALIAS_WSOL_LMDCHISQ,
02907 config->line_dchisq);
02908 cpl_propertylist_set_comment(properties, GIALIAS_WSOL_LMDCHISQ,
02909 "Line profile fit minimum delta "
02910 "chi-square");
02911
02912
02913
02914
02915
02916
02917 cx_string_sprintf(s, "%d:%d", config->pxw_xorder, config->pxw_yorder);
02918
02919 cpl_propertylist_update_string(properties, GIALIAS_WSOL_PWORDER,
02920 cx_string_get(s));
02921 cpl_propertylist_set_comment(properties, GIALIAS_WSOL_PWORDER,
02922 "PSF width fit polynomial order");
02923
02924 cpl_propertylist_update_double(properties, GIALIAS_WSOL_PWSIGMA,
02925 config->pxw_cliplevel);
02926 cpl_propertylist_set_comment(properties, GIALIAS_WSOL_PWSIGMA,
02927 "PSF width fit sigma clipping level");
02928
02929 cpl_propertylist_update_int(properties, GIALIAS_WSOL_PWITER,
02930 config->pxw_clipniter);
02931 cpl_propertylist_set_comment(properties, GIALIAS_WSOL_PWITER,
02932 "PSF width fit maximum number of "
02933 "iterations");
02934
02935 cpl_propertylist_update_double(properties, GIALIAS_WSOL_PWFRAC,
02936 config->pxw_clipmfrac);
02937 cpl_propertylist_set_comment(properties, GIALIAS_WSOL_PWFRAC,
02938 "PSF width fit minimum fraction of "
02939 "accepted points");
02940
02941
02942
02943
02944
02945
02946 cpl_propertylist_update_bool(properties, GIALIAS_WSOL_OMFIT,
02947 config->opt_solution);
02948 cpl_propertylist_set_comment(properties, GIALIAS_WSOL_OMFIT,
02949 "Optical model fit flag");
02950
02951 cpl_propertylist_update_string(properties, GIALIAS_WSOL_OMNAME,
02952 giraffe_wlsolution_name(solution));
02953 cpl_propertylist_set_comment(properties, GIALIAS_WSOL_OMNAME,
02954 "Optical model name");
02955
02956 model = giraffe_wlsolution_model(solution);
02957
02958 sign = giraffe_model_get_parameter(model,"Orientation") < 0 ? -1 : 1;
02959 cpl_propertylist_update_int(properties, GIALIAS_WSOL_OMDIR, sign);
02960 cpl_propertylist_set_comment(properties, GIALIAS_WSOL_OMDIR,
02961 "Optical model orientation");
02962
02963 value = giraffe_model_get_parameter(model, "FocalLength");
02964 cpl_propertylist_update_double(properties, GIALIAS_WSOL_OMFCOLL, value);
02965 cpl_propertylist_set_comment(properties, GIALIAS_WSOL_OMFCOLL,
02966 "Optical model focal length");
02967
02968 value = giraffe_model_get_parameter(model, "Magnification");
02969 cpl_propertylist_update_double(properties, GIALIAS_WSOL_OMGCAM, value);
02970 cpl_propertylist_set_comment(properties, GIALIAS_WSOL_OMGCAM,
02971 "Optical model camera factor");
02972
02973 value = giraffe_model_get_parameter(model, "Angle");
02974 cpl_propertylist_update_double(properties, GIALIAS_WSOL_OMGTHETA, value);
02975 cpl_propertylist_set_comment(properties, GIALIAS_WSOL_OMGTHETA,
02976 "Optical model grating angle");
02977
02978 if (strcmp(giraffe_wlsolution_name(solution), "xoptmod2") == 0) {
02979
02980 value = giraffe_model_get_parameter(model, "Sdx");
02981 cpl_propertylist_update_double(properties, GIALIAS_WSOL_OMSDX, value);
02982 cpl_propertylist_set_comment(properties, GIALIAS_WSOL_OMSDX,
02983 "Optical model slit x-offset");
02984
02985 value = giraffe_model_get_parameter(model, "Sdy");
02986 cpl_propertylist_update_double(properties, GIALIAS_WSOL_OMSDY, value);
02987 cpl_propertylist_set_comment(properties, GIALIAS_WSOL_OMSDY,
02988 "Optical model slit y-offset");
02989
02990 value = giraffe_model_get_parameter(model, "Sphi");
02991 cpl_propertylist_update_double(properties, GIALIAS_WSOL_OMSPHI, value);
02992 cpl_propertylist_set_comment(properties, GIALIAS_WSOL_OMSPHI,
02993 "Optical model slit rotation");
02994
02995 }
02996
02997
02998
02999
03000
03001
03002
03003 residuals = giraffe_wlsolution_get_residuals(solution);
03004
03005 cpl_propertylist_update_bool(properties, GIALIAS_WSOL_SUBSLITS,
03006 giraffe_wlsolution_get_subslits(solution));
03007 cpl_propertylist_set_comment(properties, GIALIAS_WSOL_SUBSLITS,
03008 "Subslit fit flag");
03009
03010
03011 cpl_propertylist_update_int(properties, GIALIAS_WSOL_XRSSN,
03012 giraffe_wlresiduals_get_size(residuals));
03013 cpl_propertylist_set_comment(properties, GIALIAS_WSOL_XRSSN,
03014 "Number of subslits");
03015
03016
03017 cx_string_sprintf(s, "%d:%d", config->xws_xorder, config->xws_yorder);
03018
03019 cpl_propertylist_update_string(properties, GIALIAS_WSOL_XRORDER,
03020 cx_string_get(s));
03021 cpl_propertylist_set_comment(properties, GIALIAS_WSOL_XRORDER,
03022 "Residual fit polynomial order");
03023
03024
03025 cpl_propertylist_update_double(properties, GIALIAS_WSOL_XRSIGMA,
03026 config->xws_cliplevel);
03027 cpl_propertylist_set_comment(properties, GIALIAS_WSOL_XRSIGMA,
03028 "Residual fit sigma clipping level");
03029
03030 cpl_propertylist_update_int(properties, GIALIAS_WSOL_XRITER,
03031 config->xws_clipniter);
03032 cpl_propertylist_set_comment(properties, GIALIAS_WSOL_XRITER,
03033 "Residual fit maximum number of "
03034 "iterations");
03035
03036 cpl_propertylist_update_double(properties, GIALIAS_WSOL_XRFRAC,
03037 config->xws_clipmfrac);
03038 cpl_propertylist_set_comment(properties, GIALIAS_WSOL_XRFRAC,
03039 "Residual fit minimum fraction of "
03040 "accepted points");
03041
03042 cpl_propertylist_update_int(properties, GIALIAS_WSOL_NLINES,
03043 info->nlines);
03044 cpl_propertylist_set_comment(properties, GIALIAS_WSOL_NLINES,
03045 "Number of calibration lines used.");
03046
03047 cpl_propertylist_update_int(properties, GIALIAS_WSOL_NACCEPT,
03048 info->ngood);
03049 cpl_propertylist_set_comment(properties, GIALIAS_WSOL_NACCEPT,
03050 "Number of accepted lines");
03051
03052 cpl_propertylist_update_int(properties, GIALIAS_WSOL_NREJECT,
03053 info->nreject);
03054 cpl_propertylist_set_comment(properties, GIALIAS_WSOL_NREJECT,
03055 "Number of rejected lines");
03056
03057 cpl_propertylist_update_double(properties, GIALIAS_WSOL_RMS,
03058 info->rms);
03059 cpl_propertylist_set_comment(properties, GIALIAS_WSOL_RMS,
03060 "Average RMS [pxl] of fitted line "
03061 "positions");
03062
03063
03064
03065
03066
03067
03068
03069 xccd[0] = giraffe_wlsolution_compute_pixel(solution, setup->wlenmin,
03070 0., 0., &status);
03071 xccd[1] = giraffe_wlsolution_compute_pixel(solution, setup->wlenmax,
03072 0., 0., &status);
03073
03074 scale = (setup->wlenmax - setup->wlenmin) / (xccd[1] - xccd[0]);
03075
03076
03077 cpl_propertylist_update_double(properties, GIALIAS_WSOL_WLMIN,
03078 setup->wlenmin);
03079 cpl_propertylist_set_comment(properties, GIALIAS_WSOL_WLMIN,
03080 "Wavelength solution minimum wavelength");
03081
03082 cpl_propertylist_update_double(properties, GIALIAS_WSOL_WLMAX,
03083 setup->wlenmax);
03084 cpl_propertylist_set_comment(properties, GIALIAS_WSOL_WLMAX,
03085 "Wavelength solution maximum wavelength");
03086
03087 cpl_propertylist_update_double(properties, GIALIAS_WSOL_SCALE, scale);
03088 cpl_propertylist_set_comment(properties, GIALIAS_WSOL_SCALE,
03089 "Approximate wavelength scale [nm/pxl]");
03090
03091
03092 cx_string_delete(s);
03093 s = NULL;
03094
03095
03096
03097
03098
03099
03100 for (i = 0; (cxsize)i < giraffe_wlresiduals_get_size(residuals); i++) {
03101
03102 const GiChebyshev2D *fit = giraffe_wlresiduals_get(residuals, i);
03103
03104
03105 if (fit != NULL) {
03106
03107 cxint xorder = 0;
03108 cxint yorder = 0;
03109
03110
03111 giraffe_chebyshev2d_get_order(fit, &xorder, &yorder);
03112
03113 if (xorder != config->xws_xorder || yorder != config->xws_yorder) {
03114
03115 gi_error("Invalid wavelength solution. Inconsistent residual "
03116 "fit polynomial order!");
03117
03118 }
03119
03120 }
03121
03122 }
03123
03124
03125
03126
03127
03128
03129 coeffs = giraffe_wlresiduals_table(residuals);
03130
03131 if (coeffs == NULL) {
03132 cpl_propertylist_delete(properties);
03133 return 1;
03134 }
03135
03136 giraffe_table_set_properties(result, properties);
03137 cpl_propertylist_delete(properties);
03138 properties = NULL;
03139
03140 giraffe_table_set(result, coeffs);
03141
03142 cpl_table_delete(coeffs);
03143 coeffs = NULL;
03144
03145 return 0;
03146
03147 }
03148
03149
03150 GiWCalData *
03151 giraffe_wcaldata_new(void)
03152 {
03153
03154 GiWCalData *self = cx_calloc(1, sizeof *self);
03155
03156 self->coeffs = NULL;
03157 self->lines = NULL;
03158 self->linedata = NULL;
03159
03160 return self;
03161
03162 }
03163
03164
03165 void
03166 giraffe_wcaldata_delete(GiWCalData *self)
03167 {
03168
03169 if (self) {
03170
03171 if (self->coeffs) {
03172 giraffe_table_delete(self->coeffs);
03173 self->coeffs = NULL;
03174 }
03175
03176 if (self->lines) {
03177 giraffe_table_delete(self->lines);
03178 self->lines = NULL;
03179 }
03180
03181 if (self->linedata) {
03182 giraffe_linedata_delete(self->linedata);
03183 self->linedata = NULL;
03184 }
03185
03186 cx_free(self);
03187
03188 }
03189
03190 return;
03191
03192 }
03193
03194
03216 cxint
03217 giraffe_calibrate_wavelength(GiWCalData *result, GiExtraction *extraction,
03218 GiLocalization *localization, GiTable *fibers,
03219 GiTable *slitgeometry, GiTable *grating,
03220 GiTable *lines, GiTable *initial,
03221 GiWCalConfig *config)
03222 {
03223
03224 const cxchar *fctid = "giraffe_calibrate_wavelength";
03225
03226
03227 cxbool residuals = FALSE;
03228
03229 cxint i;
03230 cxint status = 0;
03231 cxint nlines = 0;
03232 cxint width = 0;
03233
03234 cxdouble rms = 0.;
03235
03236 cpl_image *psf_fit = NULL;
03237 cpl_image *xws_fit = NULL;
03238
03239 GiTable *tsolution = NULL;
03240
03241 GiGrating *setup = NULL;
03242
03243 GiSCFitParams psf_setup;
03244 GiSCFitParams xws_setup;
03245
03246 GiLineParams *line_setup = NULL;
03247
03248 GiLineData *line_data = NULL;
03249
03250 GiWlSolution *solution = NULL;
03251
03252 GiWCalInfo info;
03253
03254
03255 if (extraction == NULL) {
03256 return 1;
03257 }
03258
03259 if (extraction->spectra == NULL || extraction->error == NULL) {
03260 return 1;
03261 }
03262
03263
03264 if (fibers == NULL) {
03265 return 1;
03266 }
03267
03268 if (slitgeometry == NULL) {
03269 return 1;
03270 }
03271
03272 if (grating == NULL) {
03273 return 1;
03274 }
03275
03276 if (lines == NULL) {
03277 return 1;
03278 }
03279
03280
03281
03282
03283
03284
03285 setup = giraffe_grating_create(extraction->spectra, grating);
03286
03287 if (setup == NULL) {
03288 cpl_msg_error(fctid, "Cannot initialize grating setup parameters!");
03289 return 2;
03290 }
03291
03292 if (config->slit_position != 0) {
03293
03294 if (config->slit_position & SLIT_DX) {
03295 setup->sdx = config->slit_dx;
03296 }
03297
03298 if (config->slit_position & SLIT_DY) {
03299 setup->sdy = config->slit_dy;
03300 }
03301
03302 if (config->slit_position & SLIT_PHI) {
03303 setup->sphi = config->slit_phi;
03304 }
03305
03306 cpl_msg_info(fctid, "Setting initial slit offsets: x-shift = %.9f, "
03307 "y-shift = %.9f, rotation = %.9f", setup->sdx,
03308 setup->sdy, setup->sphi);
03309
03310 }
03311
03312
03313
03314
03315
03316
03317
03318
03319
03320
03321
03322 line_setup = _giraffe_lineparams_create(GI_LINETYPE_THARNE, setup,
03323 config);
03324
03325 if (line_setup == NULL) {
03326 cpl_msg_error(fctid, "Cannot initialize line fit setup parameters!");
03327
03328 giraffe_grating_delete(setup);
03329
03330 return 3;
03331 }
03332
03333
03334
03335
03336
03337
03338 if (initial == NULL) {
03339
03340 cxint npixel = 0;
03341 cxdouble pixelsize = 0.;
03342
03343 cpl_propertylist *properties = NULL;
03344
03345 cpl_image *spectra = NULL;
03346
03347
03348 properties = giraffe_image_get_properties(extraction->spectra);
03349 cx_assert(properties != NULL);
03350
03351 spectra = giraffe_image_get(extraction->spectra);
03352 cx_assert(spectra != NULL);
03353
03354 pixelsize = cpl_propertylist_get_double(properties, GIALIAS_PIXSIZY);
03355 npixel = cpl_image_get_size_y(spectra);
03356
03357 solution = giraffe_wlsolution_new(config->opt_model,
03358 config->opt_direction, npixel,
03359 pixelsize, setup);
03360
03361 if (solution == NULL) {
03362 cpl_msg_error(fctid, "Cannot initialize initial wavelength "
03363 "solution!");
03364
03365 giraffe_grating_delete(setup);
03366
03367 _giraffe_lineparams_delete(line_setup);
03368
03369 return 4;
03370 }
03371
03372 }
03373 else {
03374
03375 const cpl_propertylist* _properties =
03376 giraffe_table_get_properties(initial);
03377
03378
03379
03380
03381
03382
03383 solution = giraffe_wlsolution_create(initial, extraction->spectra,
03384 setup);
03385
03386
03387
03388
03389
03390
03391
03392
03393
03394 if (cpl_propertylist_has(_properties, GIALIAS_WSOL_WLMIN) == TRUE) {
03395
03396 setup->wlenmin = cpl_propertylist_get_double(_properties,
03397 GIALIAS_WSOL_WLMIN);
03398
03399 cpl_msg_debug(fctid, "Using minimum wavelength %.2f from "
03400 "initial solution", setup->wlenmin);
03401
03402 }
03403
03404 if (cpl_propertylist_has(_properties, GIALIAS_WSOL_WLMAX) == TRUE) {
03405
03406 setup->wlenmax = cpl_propertylist_get_double(_properties,
03407 GIALIAS_WSOL_WLMAX);
03408
03409 cpl_msg_debug(fctid, "Using maximum wavelength %.2f from "
03410 "initial solution", setup->wlenmax);
03411
03412 }
03413
03414 }
03415
03416 giraffe_wlsolution_set_subslits(solution, config->opt_subslits);
03417
03418
03419 cpl_msg_info(fctid, "Computing line positions on the CCD using "
03420 "model `%s'", giraffe_wlsolution_name(solution));
03421
03422
03423
03424
03425
03426
03427 if (strcmp(config->line_residuals, "enable") == 0) {
03428
03429 if (giraffe_wlsolution_get_residuals(solution) == NULL) {
03430
03431 cpl_msg_error(fctid, "Initial wavelength solution does not "
03432 "provide optical model residuals!");
03433
03434 giraffe_grating_delete(setup);
03435
03436 _giraffe_lineparams_delete(line_setup);
03437
03438 giraffe_wlsolution_delete(solution);
03439
03440 return 5;
03441 }
03442 else {
03443
03444 residuals = TRUE;
03445
03446 }
03447 }
03448 else if (strcmp(config->line_residuals, "auto") == 0) {
03449
03450 residuals = giraffe_wlsolution_get_residuals(solution) != NULL;
03451
03452 if (residuals == TRUE) {
03453 cpl_msg_info(fctid, "Using wavelength solution residuals when "
03454 "computing line positions.");
03455 }
03456
03457 }
03458 else {
03459
03460 residuals = FALSE;
03461
03462 }
03463
03464
03465
03466
03467
03468
03469 status = _giraffe_linelist_setup(lines, setup, config);
03470
03471 if (status) {
03472 cpl_msg_error(fctid, "Line list creation failed!");
03473
03474 giraffe_grating_delete(setup);
03475
03476 _giraffe_lineparams_delete(line_setup);
03477
03478 giraffe_wlsolution_delete(solution);
03479
03480 return 6;
03481 }
03482
03483 nlines = cpl_table_get_nrow(giraffe_table_get(lines));
03484 cpl_msg_info(fctid, "%d lines have been selected from the line list.",
03485 nlines);
03486
03487
03488
03489
03490
03491
03492 line_data = giraffe_linedata_new();
03493
03494 for (i = 0; i < config->line_nwidths; i++) {
03495
03496 cxint _nlines = 0;
03497 cxint _nfibers = 0;
03498 cxint _nreject = 0;
03499 cxint _ngood = 0;
03500
03501 cpl_table *_lines = NULL;
03502 cpl_table *_fibers = giraffe_table_get(fibers);
03503
03504 cpl_image *xccd = NULL;
03505 cpl_image *xres = NULL;
03506 cpl_image *line_status = NULL;
03507
03508 GiWlResiduals *xws_coeffs = NULL;
03509
03510
03511
03512 width = config->line_widths[i];
03513
03514 cpl_msg_info(fctid, "Current search window width: %d pxl", width);
03515 cpl_msg_info(fctid, "Applying crowding criterium to line list.");
03516
03517 _lines = _giraffe_linelist_select(lines, extraction->spectra, setup,
03518 width, config);
03519 if (_lines == NULL) {
03520 cpl_msg_error(fctid, "Removing crowded lines from line list "
03521 "for search window width %d pxl failed!", width);
03522
03523 giraffe_grating_delete(setup);
03524
03525 _giraffe_lineparams_delete(line_setup);
03526
03527 giraffe_wlsolution_delete(solution);
03528
03529 return 7;
03530 }
03531
03532 _nlines = cpl_table_get_nrow(_lines);
03533
03534 #if 0
03535 cpl_msg_info(fctid, "%d lines used for fit. %d of %d lines rejected "
03536 "due to crowding.", _nlines, nlines - _nlines, nlines);
03537 #else
03538 cpl_msg_info(fctid, "%d lines used for fit. %d of %d lines "
03539 "rejected due to crowding and line quality.",
03540 _nlines, nlines - _nlines, nlines);
03541 #endif
03542
03543
03544
03545
03546
03547
03548 xccd = _giraffe_line_abscissa(_lines, slitgeometry, fibers,
03549 solution, localization, residuals);
03550
03551 _nfibers = cpl_image_get_size_x(xccd);
03552 _nlines = cpl_image_get_size_y(xccd);
03553
03554
03555
03556
03557
03558
03559 cpl_msg_info(fctid, "Fitting %d line profiles for %d spectra using "
03560 "line model `%s'", _nlines, _nfibers , line_setup->model);
03561
03562 cpl_msg_info(fctid, "Total number of lines to fit: %d (%d x %d)",
03563 _nlines * _nfibers, _nfibers, _nlines);
03564
03565
03566 status = giraffe_linedata_reset(line_data, _lines, _fibers,
03567 line_setup->model);
03568
03569 if (status != 0) {
03570
03571 cpl_msg_error(fctid, "Line profile fit failed!");
03572
03573 cpl_image_delete(xccd);
03574
03575 cpl_table_delete(_lines);
03576 giraffe_linedata_delete(line_data);
03577
03578 giraffe_grating_delete(setup);
03579
03580 _giraffe_lineparams_delete(line_setup);
03581
03582 giraffe_wlsolution_delete(solution);
03583
03584 return 8;
03585
03586 }
03587
03588 status = _giraffe_line_fit(line_data, xccd, width, extraction, fibers,
03589 localization->locy, line_setup);
03590
03591 if (status != 0) {
03592
03593 cpl_msg_error(fctid, "Line profile fit failed!");
03594
03595 cpl_image_delete(xccd);
03596
03597 cpl_table_delete(_lines);
03598 giraffe_linedata_delete(line_data);
03599
03600 giraffe_grating_delete(setup);
03601
03602 _giraffe_lineparams_delete(line_setup);
03603
03604 giraffe_wlsolution_delete(solution);
03605
03606 return 8;
03607
03608 }
03609
03610 cpl_image_delete(xccd);
03611 xccd = NULL;
03612
03613 if (giraffe_linedata_accepted(line_data) == 0) {
03614 cpl_msg_error(fctid, "No lines left after line profile fit!");
03615
03616 cpl_table_delete(_lines);
03617 giraffe_linedata_delete(line_data);
03618
03619 giraffe_grating_delete(setup);
03620
03621 _giraffe_lineparams_delete(line_setup);
03622
03623 giraffe_wlsolution_delete(solution);
03624
03625 return 9;
03626
03627 }
03628
03629 _nreject = giraffe_linedata_rejected(line_data);
03630 _ngood = giraffe_linedata_accepted(line_data);
03631
03632 cpl_msg_info(fctid, "Number of good lines: %d. %d of %d lines "
03633 "rejected due to line profile fit.", _ngood, _nreject,
03634 _nlines *_nfibers);
03635
03636
03637
03638
03639
03640 line_status = giraffe_linedata_status(line_data);
03641
03642
03643
03644
03645
03646
03647 cpl_msg_info(fctid, "Fit of the line profile PSF width variation.");
03648
03649 psf_setup.subslits = giraffe_wlsolution_get_subslits(solution);
03650 psf_setup.fit.xorder = config->pxw_xorder;
03651 psf_setup.fit.yorder = config->pxw_yorder;
03652
03653 cpl_msg_info(fctid, "Chebyshev polynomial order is (%d, %d).",
03654 psf_setup.fit.xorder, psf_setup.fit.yorder);
03655
03656 psf_setup.clip.iterations = config->pxw_clipniter;
03657 psf_setup.clip.level = config->pxw_cliplevel;
03658 psf_setup.clip.fraction = config->pxw_clipmfrac;
03659
03660 cpl_msg_info(fctid, "Sigma clipping: iterations = %d, level = %.4f, "
03661 "fraction = %.4f", psf_setup.clip.iterations,
03662 psf_setup.clip.level, psf_setup.clip.fraction);
03663
03664
03665 psf_fit = _giraffe_psf_fit(line_data, localization, fibers,
03666 slitgeometry, &psf_setup);
03667
03668
03669 if (psf_fit == NULL) {
03670
03671 cpl_msg_error(fctid, "Fit of the line profile PSF width "
03672 "variation failed!");
03673
03674 cpl_table_delete(_lines);
03675 cpl_image_delete(line_status);
03676 giraffe_linedata_delete(line_data);
03677
03678 giraffe_grating_delete(setup);
03679
03680 _giraffe_lineparams_delete(line_setup);
03681
03682 giraffe_wlsolution_delete(solution);
03683
03684 return 10;
03685
03686 }
03687 else {
03688
03689
03690
03691
03692
03693 cpl_image_delete(psf_fit);
03694
03695 }
03696
03697 if (giraffe_linedata_accepted(line_data) == 0) {
03698 cpl_msg_error(fctid, "No lines left after line profile PSF "
03699 "width fit!");
03700
03701 cpl_table_delete(_lines);
03702 cpl_image_delete(line_status);
03703 giraffe_linedata_delete(line_data);
03704
03705 giraffe_grating_delete(setup);
03706
03707 _giraffe_lineparams_delete(line_setup);
03708
03709 giraffe_wlsolution_delete(solution);
03710
03711 return 10;
03712
03713 }
03714
03715 cpl_msg_info(fctid, "Number of good lines: %d. %d of %d lines "
03716 "rejected due to line profile PSF width fit.",
03717 giraffe_linedata_accepted(line_data),
03718 giraffe_linedata_rejected(line_data) - _nreject, _ngood);
03719
03720 _ngood = giraffe_linedata_accepted(line_data);
03721 _nreject = giraffe_linedata_rejected(line_data);
03722
03723
03724
03725
03726
03727
03728
03729 if (config->opt_solution == TRUE) {
03730
03731 cxint iterations = 0;
03732 cxint df = 0;
03733
03734 cxdouble chisq = 0.;
03735 cxdouble rsquare = 0.;
03736
03737 cx_string *s = NULL;
03738
03739 GiOpticalModelParams om_setup;
03740
03741 GiModel *guess = NULL;
03742 GiModel *model = giraffe_wlsolution_model(solution);
03743
03744
03745
03746
03747
03748
03749 guess = giraffe_model_clone(model);
03750
03751 om_setup.fit.iterations = config->opt_niter;
03752 om_setup.fit.tests = config->opt_ntest;
03753 om_setup.fit.delta = config->opt_dchisq;
03754 om_setup.flags = config->opt_flags;
03755
03756 cpl_msg_info(fctid, "Optical model fit setup: iterations = %d, "
03757 "tests = %d, delta = %.4f", om_setup.fit.iterations,
03758 om_setup.fit.tests, om_setup.fit.delta);
03759
03760 status = _giraffe_opticalmodel_fit(solution, line_data, fibers,
03761 slitgeometry, &om_setup);
03762
03763 if (status != 0) {
03764 cpl_msg_error(fctid, "Optical model fit failed!");
03765
03766 giraffe_model_delete(guess);
03767
03768 cpl_table_delete(_lines);
03769 cpl_image_delete(line_status);
03770 giraffe_linedata_delete(line_data);
03771
03772 giraffe_grating_delete(setup);
03773
03774 _giraffe_lineparams_delete(line_setup);
03775
03776 giraffe_wlsolution_delete(solution);
03777
03778 return 11;
03779
03780 }
03781
03782
03783
03784
03785
03786
03787 cpl_msg_info(fctid, "Optical model parameters:");
03788
03789 s = cx_string_new();
03790
03791 _giraffe_opticalmodel_format(s, guess, GI_OPTM_PARAMETER_VALUES);
03792 cpl_msg_info(fctid, "Initial: %s", cx_string_get(s));
03793
03794 _giraffe_opticalmodel_format(s, model, GI_OPTM_PARAMETER_VALUES);
03795 cpl_msg_info(fctid, " Fitted: %s", cx_string_get(s));
03796
03797 _giraffe_opticalmodel_format(s, model, GI_OPTM_PARAMETER_ERRORS);
03798 cpl_msg_info(fctid, " Sigma: %s", cx_string_get(s));
03799
03800 _giraffe_opticalmodel_format(s, model, GI_OPTM_PARAMETER_STATUS);
03801 cpl_msg_info(fctid, " Status: %s", cx_string_get(s));
03802
03803 cx_string_delete(s);
03804 s = NULL;
03805
03806 #if 0
03807 if (strcmp(giraffe_model_get_name(model), "xoptmod2") == 0) {
03808
03809 cxdouble flength = 0.;
03810 cxdouble sdx = 0.;
03811 cxdouble sdy = 0.;
03812 cxdouble sphi = 0.;
03813
03814 cx_string *s = cx_string_new();
03815
03816
03817 flength = giraffe_model_get_parameter(guess, "FocalLength");
03818 sdx = giraffe_model_get_parameter(guess, "Sdx");
03819 sdy = giraffe_model_get_parameter(guess, "Sdy");
03820 sphi = giraffe_model_get_parameter(guess, "Sphi");
03821
03822 cx_string_sprintf(s, "Initial: focal length = %.6f, slit "
03823 "x-shift = %.9f, slit y-shift = %.9f, "
03824 "slit rotation = %.9f", flength, sdx, sdy,
03825 sphi);
03826 cpl_msg_info(fctid, "%s", cx_string_get(s));
03827
03828
03829 flength = giraffe_model_get_parameter(model, "FocalLength");
03830 sdx = giraffe_model_get_parameter(model, "Sdx");
03831 sdy = giraffe_model_get_parameter(model, "Sdy");
03832 sphi = giraffe_model_get_parameter(model, "Sphi");
03833
03834 cx_string_sprintf(s, " Fitted: focal length = %.6f, slit "
03835 "x-shift = %.9f, slit y-shift = %.9f, "
03836 "slit rotation = %.9f", flength, sdx, sdy,
03837 sphi);
03838 cpl_msg_info(fctid, "%s", cx_string_get(s));
03839
03840
03841 flength = giraffe_model_get_sigma(model, "FocalLength");
03842 sdx = giraffe_model_get_sigma(model, "Sdx");
03843 sdy = giraffe_model_get_sigma(model, "Sdy");
03844 sphi = giraffe_model_get_sigma(model, "Sphi");
03845
03846 cx_string_sprintf(s, " Sigma: focal length = %.6f, slit "
03847 "x-shift = %.9f, slit y-shift = %.9f, "
03848 "slit rotation = %.9f", flength, sdx, sdy,
03849 sphi);
03850 cpl_msg_info(fctid, "%s", cx_string_get(s));
03851
03852 cx_string_delete(s);
03853
03854 }
03855 else {
03856
03857 cxdouble flength = 0.;
03858
03859 cx_string *s = cx_string_new();
03860
03861
03862 flength = giraffe_model_get_parameter(guess, "FocalLength");
03863
03864 cx_string_sprintf(s, "Initial: focal length = %.6f", flength);
03865 cpl_msg_info(fctid, "%s", cx_string_get(s));
03866
03867
03868 flength = giraffe_model_get_parameter(model, "FocalLength");
03869
03870 cx_string_sprintf(s, " Fitted: focal length = %.6f", flength);
03871 cpl_msg_info(fctid, "%s", cx_string_get(s));
03872
03873
03874 flength = giraffe_model_get_sigma(model, "FocalLength");
03875
03876 cx_string_sprintf(s, " Sigma: focal length = %.6f", flength);
03877 cpl_msg_info(fctid, "%s", cx_string_get(s));
03878
03879 cx_string_delete(s);
03880
03881 }
03882 #endif
03883
03884 giraffe_model_delete(guess);
03885
03886
03887 iterations = giraffe_model_get_position(model);
03888 df = giraffe_model_get_df(model);
03889
03890 chisq = giraffe_model_get_chisq(model);
03891 rsquare = giraffe_model_get_rsquare(model);
03892
03893 cpl_msg_info(fctid, "Optical model fit statistics: iterations = "
03894 "%d, DoF = %d, Chi-square = %.6g, Chi-square/DoF = "
03895 "%.6g, R-square = %.6g", iterations, df, chisq,
03896 chisq / df, rsquare);
03897
03898
03899
03900
03901
03902
03903
03904 setup->fcoll = giraffe_model_get_parameter(model, "FocalLength");
03905 setup->gcam = giraffe_model_get_parameter(model, "Magnification");
03906 setup->theta = giraffe_model_get_parameter(model, "Angle");
03907 setup->order = giraffe_model_get_parameter(model, "Order");
03908 setup->space = giraffe_model_get_parameter(model, "Spacing");
03909
03910 if (strcmp(giraffe_model_get_name(model), "xoptmod2") == 0) {
03911 setup->sdx = giraffe_model_get_parameter(model, "Sdx");
03912 setup->sdy = giraffe_model_get_parameter(model, "Sdy");
03913 setup->sphi = giraffe_model_get_parameter(model, "Sphi");
03914 }
03915
03916
03917
03918
03919
03920
03921
03922
03923
03924
03925
03926
03927
03928 cpl_msg_info(fctid, "Re-computing line positions with updated "
03929 "optical model");
03930
03931 xccd = _giraffe_line_abscissa(_lines, slitgeometry, fibers,
03932 solution, localization, FALSE);
03933
03934 giraffe_linedata_set_data(line_data, "Xccd", xccd);
03935 xccd = NULL;
03936
03937 }
03938 else {
03939
03940 cx_string *s = cx_string_new();
03941
03942 GiModel *model = giraffe_wlsolution_model(solution);
03943
03944
03945 _giraffe_opticalmodel_format(s, model, GI_OPTM_PARAMETER_VALUES);
03946 cpl_msg_info(fctid, "Optical model: %s", cx_string_get(s));
03947
03948 cx_string_delete(s);
03949 s = NULL;
03950
03951 }
03952
03953 rms = _giraffe_compute_statistics(line_data, NULL, NULL);
03954
03955 cpl_msg_info(fctid, "Average RMS [pxl] of line positions using "
03956 "%d of %d lines: %.4f", _ngood, _nlines * _nfibers,
03957 rms);
03958
03959
03960
03961
03962
03963
03964
03965 cpl_msg_info(fctid, "Fit of the wavelength solution coefficients "
03966 "using %d lines", giraffe_linedata_accepted(line_data));
03967
03968 xws_setup.subslits = giraffe_wlsolution_get_subslits(solution);
03969 xws_setup.fit.xorder = config->xws_xorder;
03970 xws_setup.fit.yorder = config->xws_yorder;
03971
03972 cpl_msg_info(fctid, "Chebyshev polynomial order is (%d, %d).",
03973 xws_setup.fit.xorder, xws_setup.fit.yorder);
03974
03975 xws_setup.clip.iterations = config->xws_clipniter;
03976 xws_setup.clip.level = config->xws_cliplevel;
03977 xws_setup.clip.fraction = config->xws_clipmfrac;
03978
03979 cpl_msg_info(fctid, "Sigma clipping: iterations = %d, level = %.4f, "
03980 "fraction = %.4f", xws_setup.clip.iterations,
03981 xws_setup.clip.level, xws_setup.clip.fraction);
03982
03983 xws_coeffs = giraffe_wlresiduals_new();
03984
03985 xws_fit = _giraffe_residuals_fit(xws_coeffs, line_data, localization,
03986 fibers, slitgeometry, &xws_setup);
03987
03988
03989 if (xws_fit == NULL) {
03990
03991 cpl_msg_error(fctid, "Fit of the wavelength solution "
03992 "coefficients failed!");
03993
03994 giraffe_wlresiduals_delete(xws_coeffs);
03995
03996 cpl_table_delete(_lines);
03997 cpl_image_delete(line_status);
03998 giraffe_linedata_delete(line_data);
03999
04000 giraffe_grating_delete(setup);
04001
04002 _giraffe_lineparams_delete(line_setup);
04003
04004 giraffe_wlsolution_delete(solution);
04005
04006 return 12;
04007
04008 }
04009
04010
04011
04012
04013
04014
04015
04016 xres = cpl_image_new(giraffe_linedata_fibers(line_data),
04017 giraffe_linedata_lines(line_data),
04018 CPL_TYPE_DOUBLE);
04019
04020 _giraffe_get_residuals(xres,
04021 giraffe_linedata_get_data(line_data, "Xccd"),
04022 xws_fit);
04023 giraffe_linedata_set_data(line_data, "Xres", xres);
04024
04025
04026 if (giraffe_linedata_accepted(line_data) == 0) {
04027 cpl_msg_error(fctid, "No lines left after wavelength solution "
04028 "coefficients fit!");
04029
04030 giraffe_wlresiduals_delete(xws_coeffs);
04031
04032 cpl_table_delete(_lines);
04033 cpl_image_delete(line_status);
04034 cpl_image_delete(xws_fit);
04035 giraffe_linedata_delete(line_data);
04036
04037 giraffe_grating_delete(setup);
04038
04039 _giraffe_lineparams_delete(line_setup);
04040
04041 giraffe_wlsolution_delete(solution);
04042
04043 return 12;
04044
04045 }
04046
04047 cpl_msg_info(fctid, "Number of good lines: %d. %d of %d lines "
04048 "rejected due to wavelength solution coefficients fit.",
04049 giraffe_linedata_accepted(line_data),
04050 giraffe_linedata_rejected(line_data) - _nreject, _ngood);
04051
04052 _ngood = giraffe_linedata_accepted(line_data);
04053 _nreject = giraffe_linedata_rejected(line_data);
04054
04055
04056
04057
04058
04059
04060 giraffe_wlsolution_set_residuals(solution, xws_coeffs);
04061 xws_coeffs = NULL;
04062
04063
04064
04065
04066
04067
04068
04069
04070 rms = _giraffe_compute_statistics(line_data, xws_fit, line_status);
04071
04072 cpl_msg_info(fctid, "Average RMS [pxl] of line positions using "
04073 "%d of %d lines: %.4f", _ngood, _nlines * _nfibers,
04074 rms);
04075
04076
04077
04078
04079
04080
04081 info.width = width;
04082
04083 info.residuals = residuals;
04084
04085 info.nlines = _nlines;
04086 info.nfibers = _nfibers;
04087
04088 info.ngood = _ngood;
04089 info.nreject = _nreject;
04090
04091 info.rms = rms;
04092
04093
04094
04095
04096
04097
04098 cpl_image_delete(xws_fit);
04099
04100 cpl_table_delete(_lines);
04101 cpl_image_delete(line_status);
04102
04103 }
04104
04105
04106
04107
04108
04109
04110
04111 tsolution = giraffe_table_new();
04112
04113 status = _giraffe_convert_wlsolution(tsolution, solution,
04114 extraction->spectra, setup,
04115 &info, config);
04116
04117 if (status != 0) {
04118
04119 giraffe_table_delete(tsolution);
04120
04121 giraffe_grating_delete(setup);
04122
04123 _giraffe_lineparams_delete(line_setup);
04124
04125 giraffe_wlsolution_delete(solution);
04126
04127 return 13;
04128
04129 }
04130
04131
04132
04133
04134
04135
04136 result->coeffs = tsolution;
04137 tsolution = NULL;
04138
04139 result->linedata = line_data;
04140
04141
04142
04143
04144
04145
04146 giraffe_grating_delete(setup);
04147 giraffe_wlsolution_delete(solution);
04148
04149 _giraffe_lineparams_delete(line_setup);
04150
04151 return 0;
04152
04153 }
04154
04155
04166 GiWCalConfig *
04167 giraffe_wlcalibration_config_create(cpl_parameterlist *list)
04168 {
04169
04170 const cxchar *s = NULL;
04171 const cpl_parameter *p = NULL;
04172
04173 GiWCalConfig *config = NULL;
04174
04175
04176 if (!list) {
04177 return NULL;
04178 }
04179
04180 config = cx_calloc(1, sizeof *config);
04181
04182
04183
04184
04185
04186
04187
04188 config->line_saturation = 1.e7;
04189
04190
04191
04192
04193
04194
04195 p = cpl_parameterlist_find(list, "giraffe.wlcalibration.line.widths");
04196 s = cpl_parameter_get_string(p);
04197
04198 if (s) {
04199
04200 cxchar **values = cx_strsplit(s, ",", -1);
04201
04202
04203 if (values == NULL) {
04204
04205 giraffe_wlcalibration_config_destroy(config);
04206 return NULL;
04207
04208 }
04209 else {
04210
04211 cxchar *last;
04212
04213 cxint n = 0;
04214
04215
04216 while (values[n] != NULL) {
04217 ++n;
04218 }
04219
04220 config->line_nwidths = n;
04221 config->line_widths = cx_malloc(n * sizeof(cxint));
04222 cx_assert(config->line_widths != NULL);
04223
04224 n = 0;
04225 while (values[n] != NULL) {
04226
04227 cxint w = strtol(values[n], &last, 10);
04228
04229 if (*last != '\0') {
04230 cx_strfreev(values);
04231 giraffe_wlcalibration_config_destroy(config);
04232
04233 return NULL;
04234 }
04235
04236 config->line_widths[n] = w;
04237 ++n;
04238
04239 }
04240
04241 if (n > 1) {
04242 qsort(config->line_widths, config->line_nwidths,
04243 sizeof(cxint), _giraffe_window_compare);
04244 }
04245
04246 cx_strfreev(values);
04247 values = NULL;
04248
04249 }
04250
04251 }
04252
04253
04254 p = cpl_parameterlist_find(list, "giraffe.wlcalibration.line.separation");
04255 config->line_separation = fabs(cpl_parameter_get_double(p));
04256
04257 p = cpl_parameterlist_find(list, "giraffe.wlcalibration.line.fluxratio");
04258 config->line_fluxratio = cpl_parameter_get_double(p);
04259
04260 p = cpl_parameterlist_find(list, "giraffe.wlcalibration.line.brightness");
04261 config->line_brightness = cpl_parameter_get_double(p);
04262
04263 p = cpl_parameterlist_find(list, "giraffe.wlcalibration.line.count");
04264 config->line_count = cpl_parameter_get_int(p);
04265
04266 p = cpl_parameterlist_find(list, "giraffe.wlcalibration.line.wrange");
04267 s = cpl_parameter_get_string(p);
04268
04269 if (s) {
04270
04271 cxchar **values = cx_strsplit(s, ",", 3);
04272
04273 if (values == NULL) {
04274
04275 giraffe_wlcalibration_config_destroy(config);
04276 return NULL;
04277
04278 }
04279 else {
04280
04281 cxchar *last;
04282
04283 cxdouble lower = 0.;
04284 cxdouble upper = 0.;
04285
04286
04287 lower = strtod(values[0], &last);
04288
04289 if (*last != '\0') {
04290
04291 cx_strfreev(values);
04292 giraffe_wlcalibration_config_destroy(config);
04293
04294 return NULL;
04295
04296 }
04297
04298 lower = lower >= 0. ? lower : 0.;
04299
04300
04301 if (values[1] != NULL) {
04302
04303 upper = strtod(values[1], &last);
04304
04305 if (*last != '\0') {
04306
04307 cx_strfreev(values);
04308 giraffe_wlcalibration_config_destroy(config);
04309
04310 return NULL;
04311
04312 }
04313
04314 upper = upper > lower ? upper : 0.;
04315
04316 }
04317
04318 config->line_wlrange = giraffe_range_create(lower, upper);
04319 cx_assert(config->line_wlrange != NULL);
04320
04321 }
04322
04323 cx_strfreev(values);
04324 values = NULL;
04325
04326 }
04327
04328
04329 p = cpl_parameterlist_find(list, "giraffe.wlcalibration.line.model");
04330 s = cpl_parameter_get_string(p);
04331
04332 if (strcmp(s, "psfexp") != 0 &&
04333 strcmp(s, "psfexp2") != 0 &&
04334 strcmp(s, "gaussian") != 0) {
04335
04336 giraffe_wlcalibration_config_destroy(config);
04337 return NULL;
04338
04339 }
04340 else {
04341 config->line_model = cx_strdup(s);
04342 }
04343
04344
04345 p = cpl_parameterlist_find(list, "giraffe.wlcalibration.line.residuals");
04346 s = cpl_parameter_get_string(p);
04347
04348 if (strcmp(s, "auto") != 0 &&
04349 strcmp(s, "enable") != 0 &&
04350 strcmp(s, "disable") != 0) {
04351
04352 giraffe_wlcalibration_config_destroy(config);
04353 return NULL;
04354
04355 }
04356 else {
04357 config->line_residuals = cx_strdup(s);
04358 }
04359
04360
04361 p = cpl_parameterlist_find(list, "giraffe.wlcalibration.line.threshold");
04362 config->line_threshold = cpl_parameter_get_double(p);
04363
04364 p = cpl_parameterlist_find(list, "giraffe.wlcalibration.line.offset");
04365 config->line_offset = cpl_parameter_get_double(p);
04366
04367 p = cpl_parameterlist_find(list, "giraffe.wlcalibration.line.iterations");
04368 config->line_niter = cpl_parameter_get_int(p);
04369
04370 p = cpl_parameterlist_find(list, "giraffe.wlcalibration.line.tests");
04371 config->line_ntest = cpl_parameter_get_int(p);
04372
04373 p = cpl_parameterlist_find(list, "giraffe.wlcalibration.line.dchisquare");
04374 config->line_dchisq = cpl_parameter_get_double(p);
04375
04376 p = cpl_parameterlist_find(list, "giraffe.wlcalibration.line.rwidthratio");
04377 config->line_rwidthratio = cpl_parameter_get_double(p);
04378
04379 p = cpl_parameterlist_find(list, "giraffe.wlcalibration.line.exponent");
04380 config->line_widthexponent = cpl_parameter_get_double(p);
04381
04382
04383 p = cpl_parameterlist_find(list, "giraffe.wlcalibration.slit.offset");
04384 s = cpl_parameter_get_string(p);
04385
04386 cx_assert(s != NULL);
04387
04388 if (cx_strncasecmp(s, "setup", 5) != 0) {
04389
04390 cxchar **values = cx_strsplit(s, ",", 4);
04391
04392
04393 config->slit_position = 0;
04394 config->slit_dx = 0.;
04395 config->slit_dy = 0.;
04396 config->slit_phi = 0.;
04397
04398 if (values == NULL || values[0] == NULL) {
04399
04400 giraffe_wlcalibration_config_destroy(config);
04401 return NULL;
04402
04403 }
04404 else {
04405
04406 cxbool eol = FALSE;
04407
04408 if (*values[0] != '\0') {
04409
04410 cxchar *last;
04411 cxdouble sdx = strtod(values[0], &last);
04412
04413 if (*last != '\0') {
04414 cx_strfreev(values);
04415 values = NULL;
04416
04417 giraffe_wlcalibration_config_destroy(config);
04418
04419 return NULL;
04420 }
04421
04422 config->slit_position |= SLIT_DX;
04423 config->slit_dx = sdx;
04424
04425 }
04426
04427 if (values[1] == NULL) {
04428 eol = TRUE;
04429 }
04430 else {
04431
04432 if (*values[1] != '\0') {
04433
04434 cxchar *last;
04435 cxdouble sdy = strtod(values[1], &last);
04436
04437 if (*last != '\0') {
04438 cx_strfreev(values);
04439 values = NULL;
04440
04441 giraffe_wlcalibration_config_destroy(config);
04442
04443 return NULL;
04444 }
04445
04446 config->slit_position |= SLIT_DY;
04447 config->slit_dy = sdy;
04448
04449 }
04450
04451 }
04452
04453 if (!eol && values[2] != NULL) {
04454
04455 if (*values[2] != '\0') {
04456
04457 cxchar *last;
04458 cxdouble sphi = strtod(values[2], &last);
04459
04460 if (*last != '\0') {
04461 cx_strfreev(values);
04462 values = NULL;
04463
04464 giraffe_wlcalibration_config_destroy(config);
04465
04466 return NULL;
04467 }
04468
04469 config->slit_position |= SLIT_PHI;
04470 config->slit_phi = sphi;
04471
04472 }
04473
04474 }
04475
04476 cx_strfreev(values);
04477 values = NULL;
04478
04479 }
04480
04481 }
04482
04483
04484 p = cpl_parameterlist_find(list, "giraffe.wlcalibration.opt.model");
04485 s = cpl_parameter_get_string(p);
04486
04487 if (strcmp(s, "xoptmod") != 0 && strcmp(s, "xoptmod2") != 0) {
04488
04489 giraffe_wlcalibration_config_destroy(config);
04490 return NULL;
04491
04492 }
04493 else {
04494 config->opt_model = cx_strdup(s);
04495 }
04496
04497
04498 p = cpl_parameterlist_find(list, "giraffe.wlcalibration.opt.direction");
04499 config->opt_direction = cpl_parameter_get_int(p);
04500
04501 p = cpl_parameterlist_find(list, "giraffe.wlcalibration.opt.solution");
04502 config->opt_solution = cpl_parameter_get_bool(p);
04503
04504 p = cpl_parameterlist_find(list, "giraffe.wlcalibration.opt.subslits");
04505 config->opt_subslits = cpl_parameter_get_bool(p);
04506
04507 p = cpl_parameterlist_find(list, "giraffe.wlcalibration.opt.flags");
04508 s = cpl_parameter_get_string(p);
04509
04510 if (s) {
04511
04512 cxchar **values = cx_strsplit(s, ",", -1);
04513
04514 if (values == NULL) {
04515
04516 giraffe_wlcalibration_config_destroy(config);
04517 return NULL;
04518
04519 }
04520 else {
04521
04522 cxint i = 0;
04523 cxint n = 0;
04524
04525 config->opt_flags = 0;
04526
04527 while (values[i] != NULL) {
04528
04529 if (strncmp(values[i], "fcoll", 5) == 0) {
04530 config->opt_flags |= OPTM_FLENGTH;
04531 ++n;
04532 }
04533 else if (strncmp(values[i], "gcam", 4) == 0) {
04534 config->opt_flags |= OPTM_GCAMERA;
04535 ++n;
04536 }
04537 else if (strncmp(values[i], "theta", 5) == 0) {
04538 config->opt_flags |= OPTM_THETA;
04539 ++n;
04540 }
04541 else if (strncmp(values[i], "sdx", 3) == 0) {
04542 config->opt_flags |= OPTM_SX;
04543 ++n;
04544 }
04545 else if (strncmp(values[i], "sdy", 3) == 0) {
04546 config->opt_flags |= OPTM_SY;
04547 ++n;
04548 }
04549 else if (strncmp(values[i], "sphi", 4) == 0) {
04550 config->opt_flags |= OPTM_SPHI;
04551 ++n;
04552 }
04553
04554 ++i;
04555
04556 }
04557
04558 cx_strfreev(values);
04559 values = NULL;
04560
04561
04562
04563
04564
04565
04566 if (n == 0) {
04567 giraffe_wlcalibration_config_destroy(config);
04568 return NULL;
04569 }
04570
04571 }
04572
04573 }
04574
04575
04576 p = cpl_parameterlist_find(list, "giraffe.wlcalibration.opt.iterations");
04577 config->opt_niter = cpl_parameter_get_int(p);
04578
04579 p = cpl_parameterlist_find(list, "giraffe.wlcalibration.opt.tests");
04580 config->opt_ntest = cpl_parameter_get_int(p);
04581
04582 p = cpl_parameterlist_find(list, "giraffe.wlcalibration.opt.dchisquare");
04583 config->opt_dchisq = cpl_parameter_get_double(p);
04584
04585
04586 p = cpl_parameterlist_find(list, "giraffe.wlcalibration.psf.sigma");
04587 config->pxw_cliplevel = cpl_parameter_get_double(p);
04588
04589 p = cpl_parameterlist_find(list, "giraffe.wlcalibration.psf.iterations");
04590 config->pxw_clipniter = cpl_parameter_get_int(p);
04591
04592 p = cpl_parameterlist_find(list, "giraffe.wlcalibration.psf.fraction");
04593 config->pxw_clipmfrac = cpl_parameter_get_double(p);
04594
04595 p = cpl_parameterlist_find(list, "giraffe.wlcalibration.psf.order");
04596 s = cpl_parameter_get_string(p);
04597
04598 if (s) {
04599
04600 cxchar **values = cx_strsplit(s, ",", 3);
04601
04602 if (values == NULL || values[1] == NULL) {
04603
04604 giraffe_wlcalibration_config_destroy(config);
04605 return NULL;
04606
04607 }
04608 else {
04609
04610 cxchar *last;
04611
04612
04613 config->pxw_xorder = strtol(values[0], &last, 10);
04614
04615 if (*last != '\0') {
04616
04617 cx_strfreev(values);
04618 giraffe_wlcalibration_config_destroy(config);
04619
04620 return NULL;
04621
04622 }
04623
04624 config->pxw_yorder = strtol(values[1], &last, 10);
04625
04626 if (*last != '\0') {
04627
04628 cx_strfreev(values);
04629 giraffe_wlcalibration_config_destroy(config);
04630
04631 return NULL;
04632
04633 }
04634
04635 }
04636
04637 cx_strfreev(values);
04638 values = NULL;
04639
04640 }
04641
04642
04643 p = cpl_parameterlist_find(list, "giraffe.wlcalibration.wsol.sigma");
04644 config->xws_cliplevel = cpl_parameter_get_double(p);
04645
04646 p = cpl_parameterlist_find(list, "giraffe.wlcalibration.wsol.iterations");
04647 config->xws_clipniter = cpl_parameter_get_int(p);
04648
04649 p = cpl_parameterlist_find(list, "giraffe.wlcalibration.wsol.fraction");
04650 config->xws_clipmfrac = cpl_parameter_get_double(p);
04651
04652 p = cpl_parameterlist_find(list, "giraffe.wlcalibration.wsol.order");
04653 s = cpl_parameter_get_string(p);
04654
04655 if (s) {
04656
04657 cxchar **values = cx_strsplit(s, ",", 3);
04658
04659 if (values == NULL || values[1] == NULL) {
04660
04661 giraffe_wlcalibration_config_destroy(config);
04662 return NULL;
04663
04664 }
04665 else {
04666
04667 cxchar *last;
04668
04669
04670 config->xws_xorder = strtol(values[0], &last, 10);
04671
04672 if (*last != '\0') {
04673
04674 cx_strfreev(values);
04675 giraffe_wlcalibration_config_destroy(config);
04676
04677 return NULL;
04678
04679 }
04680
04681 config->xws_yorder = strtol(values[1], &last, 10);
04682
04683 if (*last != '\0') {
04684
04685 cx_strfreev(values);
04686 giraffe_wlcalibration_config_destroy(config);
04687
04688 return NULL;
04689
04690 }
04691
04692 }
04693
04694 cx_strfreev(values);
04695 values = NULL;
04696
04697 }
04698
04699 return config;
04700
04701 }
04702
04703
04716 void
04717 giraffe_wlcalibration_config_destroy(GiWCalConfig *config)
04718 {
04719
04720 if (config) {
04721 if (config->line_widths) {
04722 cx_free(config->line_widths);
04723 }
04724
04725 if (config->line_wlrange) {
04726 giraffe_range_delete(config->line_wlrange);
04727 }
04728
04729 if (config->line_model) {
04730 cx_free(config->line_model);
04731 }
04732
04733 if (config->line_residuals) {
04734 cx_free(config->line_residuals);
04735 }
04736
04737 if (config->opt_model) {
04738 cx_free(config->opt_model);
04739 }
04740
04741 cx_free(config);
04742 }
04743
04744 return;
04745
04746 }
04747
04748
04760 void
04761 giraffe_wlcalibration_config_add(cpl_parameterlist *list)
04762 {
04763
04764 cpl_parameter *p;
04765
04766
04767 if (!list) {
04768 return;
04769 }
04770
04771
04772
04773
04774
04775
04776 p = cpl_parameter_new_value("giraffe.wlcalibration.line.widths",
04777 CPL_TYPE_STRING,
04778 "List of window widths [pxl] used for line "
04779 "detection and fit (e.g. '60,40,15').",
04780 "giraffe.wlcalibration",
04781 "10,10,10,10,10");
04782 cpl_parameter_set_alias(p, CPL_PARAMETER_MODE_CLI, "wcal-lswidth");
04783 cpl_parameterlist_append(list, p);
04784
04785
04786 p = cpl_parameter_new_value("giraffe.wlcalibration.line.separation",
04787 CPL_TYPE_DOUBLE,
04788 "Factor used to compute the minimum line "
04789 "separation from the window width.",
04790 "giraffe.wlcalibration",
04791 0.9);
04792 cpl_parameter_set_alias(p, CPL_PARAMETER_MODE_CLI, "wcal-lssep");
04793 cpl_parameterlist_append(list, p);
04794
04795
04796 p = cpl_parameter_new_value("giraffe.wlcalibration.line.fluxratio",
04797 CPL_TYPE_DOUBLE,
04798 "Selects only lines whose neighbours have "
04799 "a relative intensity less than "
04800 "1. / fluxratio.",
04801 "giraffe.wlcalibration",
04802 50.);
04803
04804 cpl_parameter_set_alias(p, CPL_PARAMETER_MODE_CLI, "wcal-lsfxratio");
04805 cpl_parameterlist_append(list, p);
04806
04807
04808 p = cpl_parameter_new_value("giraffe.wlcalibration.line.brightness",
04809 CPL_TYPE_DOUBLE,
04810 "Selects lines having an intensity greater "
04811 "or equal to the given intensity.",
04812 "giraffe.wlcalibration",
04813 0.);
04814
04815 cpl_parameter_set_alias(p, CPL_PARAMETER_MODE_CLI, "wcal-lsbright");
04816 cpl_parameterlist_append(list, p);
04817
04818
04819 p = cpl_parameter_new_value("giraffe.wlcalibration.line.count",
04820 CPL_TYPE_INT,
04821 "Sets the minimum number of lines to select; "
04822 "selected are lines with the highest nominal "
04823 "intensity. A value of 0 turns this selection "
04824 "off. If the value is less than 0 the "
04825 "selection is skipped if the line list does "
04826 "not contain enough lines.",
04827 "giraffe.wlcalibration",
04828 -80);
04829
04830 cpl_parameter_set_alias(p, CPL_PARAMETER_MODE_CLI, "wcal-lscount");
04831 cpl_parameterlist_append(list, p);
04832
04833
04834 p = cpl_parameter_new_value("giraffe.wlcalibration.line.wrange",
04835 CPL_TYPE_STRING,
04836 "Selects only lines within the given "
04837 "wavelength range [nm].",
04838 "giraffe.wlcalibration",
04839 "0.,0.");
04840
04841 cpl_parameter_set_alias(p, CPL_PARAMETER_MODE_CLI, "wcal-lswrange");
04842 cpl_parameterlist_append(list, p);
04843
04844
04845
04846
04847
04848
04849 p = cpl_parameter_new_enum("giraffe.wlcalibration.line.model",
04850 CPL_TYPE_STRING,
04851 "Line profile model.",
04852 "giraffe.wlcalibration",
04853 "psfexp", 3, "psfexp", "psfexp2", "gaussian");
04854
04855 cpl_parameter_set_alias(p, CPL_PARAMETER_MODE_CLI, "wcal-lfmodel");
04856 cpl_parameterlist_append(list, p);
04857
04858
04859 p = cpl_parameter_new_enum("giraffe.wlcalibration.line.residuals",
04860 CPL_TYPE_STRING,
04861 "Use optical model residuals for line "
04862 "detection.",
04863 "giraffe.wlcalibration",
04864 "auto", 3, "auto", "enable", "disable");
04865
04866 cpl_parameter_set_alias(p, CPL_PARAMETER_MODE_CLI, "wcal-lfres");
04867 cpl_parameterlist_append(list, p);
04868
04869
04870 p = cpl_parameter_new_value("giraffe.wlcalibration.line.threshold",
04871 CPL_TYPE_DOUBLE,
04872 "Line detection threshold during the "
04873 "line fitting (multiple of bias sigma)",
04874 "giraffe.wlcalibration",
04875 1.);
04876
04877 cpl_parameter_set_alias(p, CPL_PARAMETER_MODE_CLI, "wcal-lfthreshold");
04878 cpl_parameterlist_append(list, p);
04879
04880
04881 p = cpl_parameter_new_value("giraffe.wlcalibration.line.offset",
04882 CPL_TYPE_DOUBLE,
04883 "Maximum allowed difference between the "
04884 "fitted and raw line peak position.",
04885 "giraffe.wlcalibration",
04886 10.);
04887
04888 cpl_parameter_set_alias(p, CPL_PARAMETER_MODE_CLI, "wcal-lfoffset");
04889 cpl_parameterlist_append(list, p);
04890
04891
04892 p = cpl_parameter_new_value("giraffe.wlcalibration.line.iterations",
04893 CPL_TYPE_INT,
04894 "Line detection fit maximum number of "
04895 "iterations.",
04896 "giraffe.wlcalibration",
04897 50);
04898
04899 cpl_parameter_set_alias(p, CPL_PARAMETER_MODE_CLI, "wcal-lfniter");
04900 cpl_parameterlist_append(list, p);
04901
04902
04903 p = cpl_parameter_new_value("giraffe.wlcalibration.line.tests",
04904 CPL_TYPE_INT,
04905 "Line detection fit maximum number of "
04906 "tests.",
04907 "giraffe.wlcalibration",
04908 7);
04909
04910 cpl_parameter_set_alias(p, CPL_PARAMETER_MODE_CLI, "wcal-lfntest");
04911 cpl_parameterlist_append(list, p);
04912
04913
04914 p = cpl_parameter_new_value("giraffe.wlcalibration.line.dchisquare",
04915 CPL_TYPE_DOUBLE,
04916 "Line detection fit minimum chi-square "
04917 "difference.",
04918 "giraffe.wlcalibration",
04919 0.0001);
04920
04921 cpl_parameter_set_alias(p, CPL_PARAMETER_MODE_CLI, "wcal-lfdchisq");
04922 cpl_parameterlist_append(list, p);
04923
04924
04925 p = cpl_parameter_new_value("giraffe.wlcalibration.line.rwidthratio",
04926 CPL_TYPE_DOUBLE,
04927 "Line width/resolution width factor.",
04928 "giraffe.wlcalibration",
04929 0.5);
04930
04931 cpl_parameter_set_alias(p, CPL_PARAMETER_MODE_CLI, "wcal-lfreswid");
04932 cpl_parameterlist_append(list, p);
04933
04934
04935 p = cpl_parameter_new_value("giraffe.wlcalibration.line.exponent",
04936 CPL_TYPE_DOUBLE,
04937 "Exponential line profile exponent; it will "
04938 "not be fitted if it is larger than 0.",
04939 "giraffe.wlcalibration",
04940 -3.);
04941
04942 cpl_parameter_set_alias(p, CPL_PARAMETER_MODE_CLI, "wcal-lfexpwid");
04943 cpl_parameterlist_append(list, p);
04944
04945
04946
04947
04948
04949
04950
04951 p = cpl_parameter_new_value("giraffe.wlcalibration.slit.offset",
04952 CPL_TYPE_STRING,
04953 "Initial slit position offsets along the "
04954 "x and y direction and rotation angle.",
04955 "giraffe.wlcalibration",
04956 "setup");
04957
04958 cpl_parameter_set_alias(p, CPL_PARAMETER_MODE_CLI, "wcal-soffset");
04959 cpl_parameterlist_append(list, p);
04960
04961
04962
04963
04964
04965
04966 p = cpl_parameter_new_enum("giraffe.wlcalibration.opt.model",
04967 CPL_TYPE_STRING,
04968 "Optical model.",
04969 "giraffe.wlcalibration",
04970 "xoptmod2", 2, "xoptmod", "xoptmod2");
04971
04972 cpl_parameter_set_alias(p, CPL_PARAMETER_MODE_CLI, "wcal-ommodel");
04973 cpl_parameterlist_append(list, p);
04974
04975
04976 p = cpl_parameter_new_value("giraffe.wlcalibration.opt.direction",
04977 CPL_TYPE_INT,
04978 "Dispersion direction flag.",
04979 "giraffe.wlcalibration",
04980 1);
04981
04982 cpl_parameter_set_alias(p, CPL_PARAMETER_MODE_CLI, "wcal-omdir");
04983 cpl_parameterlist_append(list, p);
04984
04985
04986 p = cpl_parameter_new_value("giraffe.wlcalibration.opt.solution",
04987 CPL_TYPE_BOOL,
04988 "Controls optical model parameter fitting.",
04989 "giraffe.wlcalibration",
04990 TRUE);
04991
04992 cpl_parameter_set_alias(p, CPL_PARAMETER_MODE_CLI, "wcal-omsol");
04993 cpl_parameterlist_append(list, p);
04994
04995
04996 p = cpl_parameter_new_value("giraffe.wlcalibration.opt.flags",
04997 CPL_TYPE_STRING,
04998 "List of flags defining the set of free "
04999 "parameters used for fitting the optical "
05000 "model. Possible values are: fcoll, gcam, "
05001 "theta, sdx, sdy, sphi",
05002 "giraffe.wlcalibration",
05003 "sdx,sdy,sphi");
05004
05005 cpl_parameter_set_alias(p, CPL_PARAMETER_MODE_CLI, "wcal-omflags");
05006 cpl_parameterlist_append(list, p);
05007
05008
05009 p = cpl_parameter_new_value("giraffe.wlcalibration.opt.subslits",
05010 CPL_TYPE_BOOL,
05011 "Controls subslit geometry usage in the "
05012 "optical model fit; subslits are used if "
05013 "set to `true'.",
05014 "giraffe.wlcalibration",
05015 FALSE);
05016
05017 cpl_parameter_set_alias(p, CPL_PARAMETER_MODE_CLI, "wcal-omsslits");
05018 cpl_parameterlist_append(list, p);
05019
05020
05021 p = cpl_parameter_new_value("giraffe.wlcalibration.opt.iterations",
05022 CPL_TYPE_INT,
05023 "Optical model fit maximum number of "
05024 "iterations.",
05025 "giraffe.wlcalibration",
05026 50);
05027
05028 cpl_parameter_set_alias(p, CPL_PARAMETER_MODE_CLI, "wcal-omniter");
05029 cpl_parameterlist_append(list, p);
05030
05031
05032 p = cpl_parameter_new_value("giraffe.wlcalibration.opt.tests",
05033 CPL_TYPE_INT,
05034 "Optical model fit maximum number of "
05035 "tests",
05036 "giraffe.wlcalibration",
05037 7);
05038
05039 cpl_parameter_set_alias(p, CPL_PARAMETER_MODE_CLI, "wcal-omntest");
05040 cpl_parameterlist_append(list, p);
05041
05042
05043 p = cpl_parameter_new_value("giraffe.wlcalibration.opt.dchisquare",
05044 CPL_TYPE_DOUBLE,
05045 "Optical model fit minimum chi-square "
05046 "difference.",
05047 "giraffe.wlcalibration",
05048 0.0001);
05049
05050 cpl_parameter_set_alias(p, CPL_PARAMETER_MODE_CLI, "wcal-omdchisq");
05051 cpl_parameterlist_append(list, p);
05052
05053
05054
05055
05056
05057
05058 p = cpl_parameter_new_value("giraffe.wlcalibration.psf.sigma",
05059 CPL_TYPE_DOUBLE,
05060 "PSF width fit sigma clipping factor.",
05061 "giraffe.wlcalibration",
05062 1.25);
05063
05064 cpl_parameter_set_alias(p, CPL_PARAMETER_MODE_CLI, "wcal-xwsigma");
05065 cpl_parameterlist_append(list, p);
05066
05067
05068 p = cpl_parameter_new_value("giraffe.wlcalibration.psf.iterations",
05069 CPL_TYPE_INT,
05070 "PSF width fit sigma clipping maximum "
05071 "number of iterations.",
05072 "giraffe.wlcalibration",
05073 10);
05074
05075 cpl_parameter_set_alias(p, CPL_PARAMETER_MODE_CLI, "wcal-xwniter");
05076 cpl_parameterlist_append(list, p);
05077
05078
05079 p = cpl_parameter_new_range("giraffe.wlcalibration.psf.fraction",
05080 CPL_TYPE_DOUBLE,
05081 "PSF width fit sigma clipping minimum "
05082 "fraction of points accepted/total.",
05083 "giraffe.wlcalibration",
05084 0.9, 0., 1.);
05085
05086 cpl_parameter_set_alias(p, CPL_PARAMETER_MODE_CLI, "wcal-xwmfrac");
05087 cpl_parameterlist_append(list, p);
05088
05089
05090 p = cpl_parameter_new_value("giraffe.wlcalibration.psf.order",
05091 CPL_TYPE_STRING,
05092 "X and Y polynomial orders for PSF x-width "
05093 "Chebyshev fit.",
05094 "giraffe.wlcalibration",
05095 "2,2");
05096
05097 cpl_parameter_set_alias(p, CPL_PARAMETER_MODE_CLI, "wcal-xworder");
05098 cpl_parameterlist_append(list, p);
05099
05100
05101
05102
05103
05104
05105 p = cpl_parameter_new_value("giraffe.wlcalibration.wsol.sigma",
05106 CPL_TYPE_DOUBLE,
05107 "Chebyshev correction sigma clipping factor.",
05108 "giraffe.wlcalibration",
05109 150.0);
05110
05111 cpl_parameter_set_alias(p, CPL_PARAMETER_MODE_CLI, "wcal-wssigma");
05112 cpl_parameterlist_append(list, p);
05113
05114
05115 p = cpl_parameter_new_value("giraffe.wlcalibration.wsol.iterations",
05116 CPL_TYPE_INT,
05117 "Chebyshev correction sigma clipping "
05118 "maximum number of iterations",
05119 "giraffe.wlcalibration",
05120 10);
05121
05122 cpl_parameter_set_alias(p, CPL_PARAMETER_MODE_CLI, "wcal-wsniter");
05123 cpl_parameterlist_append(list, p);
05124
05125
05126 p = cpl_parameter_new_range("giraffe.wlcalibration.wsol.fraction",
05127 CPL_TYPE_DOUBLE,
05128 "Chebyshev correction sigma clipping "
05129 "minimum fraction of points accepted/total.",
05130 "giraffe.wlcalibration",
05131 0.9, 0., 1.);
05132
05133 cpl_parameter_set_alias(p, CPL_PARAMETER_MODE_CLI, "wcal-wsmfrac");
05134 cpl_parameterlist_append(list, p);
05135
05136
05137 p = cpl_parameter_new_value("giraffe.wlcalibration.wsol.order",
05138 CPL_TYPE_STRING,
05139 "X and Y polynomial orders for the wavelength "
05140 "solution Chebyshev correction.",
05141 "giraffe.wlcalibration",
05142 "6,4");
05143
05144 cpl_parameter_set_alias(p, CPL_PARAMETER_MODE_CLI, "wcal-wsorder");
05145 cpl_parameterlist_append(list, p);
05146
05147 return;
05148
05149 }