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: %"
03716 CX_PRINTF_FORMAT_SIZE_TYPE ". %"
03717 CX_PRINTF_FORMAT_SIZE_TYPE "of %d lines "
03718 "rejected due to line profile PSF width fit.",
03719 giraffe_linedata_accepted(line_data),
03720 giraffe_linedata_rejected(line_data) - _nreject, _ngood);
03721
03722 _ngood = giraffe_linedata_accepted(line_data);
03723 _nreject = giraffe_linedata_rejected(line_data);
03724
03725
03726
03727
03728
03729
03730
03731 if (config->opt_solution == TRUE) {
03732
03733 cxint iterations = 0;
03734 cxint df = 0;
03735
03736 cxdouble chisq = 0.;
03737 cxdouble rsquare = 0.;
03738
03739 cx_string *s = NULL;
03740
03741 GiOpticalModelParams om_setup;
03742
03743 GiModel *guess = NULL;
03744 GiModel *model = giraffe_wlsolution_model(solution);
03745
03746
03747
03748
03749
03750
03751 guess = giraffe_model_clone(model);
03752
03753 om_setup.fit.iterations = config->opt_niter;
03754 om_setup.fit.tests = config->opt_ntest;
03755 om_setup.fit.delta = config->opt_dchisq;
03756 om_setup.flags = config->opt_flags;
03757
03758 cpl_msg_info(fctid, "Optical model fit setup: iterations = %d, "
03759 "tests = %d, delta = %.4f", om_setup.fit.iterations,
03760 om_setup.fit.tests, om_setup.fit.delta);
03761
03762 status = _giraffe_opticalmodel_fit(solution, line_data, fibers,
03763 slitgeometry, &om_setup);
03764
03765 if (status != 0) {
03766 cpl_msg_error(fctid, "Optical model fit failed!");
03767
03768 giraffe_model_delete(guess);
03769
03770 cpl_table_delete(_lines);
03771 cpl_image_delete(line_status);
03772 giraffe_linedata_delete(line_data);
03773
03774 giraffe_grating_delete(setup);
03775
03776 _giraffe_lineparams_delete(line_setup);
03777
03778 giraffe_wlsolution_delete(solution);
03779
03780 return 11;
03781
03782 }
03783
03784
03785
03786
03787
03788
03789 cpl_msg_info(fctid, "Optical model parameters:");
03790
03791 s = cx_string_new();
03792
03793 _giraffe_opticalmodel_format(s, guess, GI_OPTM_PARAMETER_VALUES);
03794 cpl_msg_info(fctid, "Initial: %s", cx_string_get(s));
03795
03796 _giraffe_opticalmodel_format(s, model, GI_OPTM_PARAMETER_VALUES);
03797 cpl_msg_info(fctid, " Fitted: %s", cx_string_get(s));
03798
03799 _giraffe_opticalmodel_format(s, model, GI_OPTM_PARAMETER_ERRORS);
03800 cpl_msg_info(fctid, " Sigma: %s", cx_string_get(s));
03801
03802 _giraffe_opticalmodel_format(s, model, GI_OPTM_PARAMETER_STATUS);
03803 cpl_msg_info(fctid, " Status: %s", cx_string_get(s));
03804
03805 cx_string_delete(s);
03806 s = NULL;
03807
03808 #if 0
03809 if (strcmp(giraffe_model_get_name(model), "xoptmod2") == 0) {
03810
03811 cxdouble flength = 0.;
03812 cxdouble sdx = 0.;
03813 cxdouble sdy = 0.;
03814 cxdouble sphi = 0.;
03815
03816 cx_string *s = cx_string_new();
03817
03818
03819 flength = giraffe_model_get_parameter(guess, "FocalLength");
03820 sdx = giraffe_model_get_parameter(guess, "Sdx");
03821 sdy = giraffe_model_get_parameter(guess, "Sdy");
03822 sphi = giraffe_model_get_parameter(guess, "Sphi");
03823
03824 cx_string_sprintf(s, "Initial: focal length = %.6f, slit "
03825 "x-shift = %.9f, slit y-shift = %.9f, "
03826 "slit rotation = %.9f", flength, sdx, sdy,
03827 sphi);
03828 cpl_msg_info(fctid, "%s", cx_string_get(s));
03829
03830
03831 flength = giraffe_model_get_parameter(model, "FocalLength");
03832 sdx = giraffe_model_get_parameter(model, "Sdx");
03833 sdy = giraffe_model_get_parameter(model, "Sdy");
03834 sphi = giraffe_model_get_parameter(model, "Sphi");
03835
03836 cx_string_sprintf(s, " Fitted: focal length = %.6f, slit "
03837 "x-shift = %.9f, slit y-shift = %.9f, "
03838 "slit rotation = %.9f", flength, sdx, sdy,
03839 sphi);
03840 cpl_msg_info(fctid, "%s", cx_string_get(s));
03841
03842
03843 flength = giraffe_model_get_sigma(model, "FocalLength");
03844 sdx = giraffe_model_get_sigma(model, "Sdx");
03845 sdy = giraffe_model_get_sigma(model, "Sdy");
03846 sphi = giraffe_model_get_sigma(model, "Sphi");
03847
03848 cx_string_sprintf(s, " Sigma: focal length = %.6f, slit "
03849 "x-shift = %.9f, slit y-shift = %.9f, "
03850 "slit rotation = %.9f", flength, sdx, sdy,
03851 sphi);
03852 cpl_msg_info(fctid, "%s", cx_string_get(s));
03853
03854 cx_string_delete(s);
03855
03856 }
03857 else {
03858
03859 cxdouble flength = 0.;
03860
03861 cx_string *s = cx_string_new();
03862
03863
03864 flength = giraffe_model_get_parameter(guess, "FocalLength");
03865
03866 cx_string_sprintf(s, "Initial: focal length = %.6f", flength);
03867 cpl_msg_info(fctid, "%s", cx_string_get(s));
03868
03869
03870 flength = giraffe_model_get_parameter(model, "FocalLength");
03871
03872 cx_string_sprintf(s, " Fitted: focal length = %.6f", flength);
03873 cpl_msg_info(fctid, "%s", cx_string_get(s));
03874
03875
03876 flength = giraffe_model_get_sigma(model, "FocalLength");
03877
03878 cx_string_sprintf(s, " Sigma: focal length = %.6f", flength);
03879 cpl_msg_info(fctid, "%s", cx_string_get(s));
03880
03881 cx_string_delete(s);
03882
03883 }
03884 #endif
03885
03886 giraffe_model_delete(guess);
03887
03888
03889 iterations = giraffe_model_get_position(model);
03890 df = giraffe_model_get_df(model);
03891
03892 chisq = giraffe_model_get_chisq(model);
03893 rsquare = giraffe_model_get_rsquare(model);
03894
03895 cpl_msg_info(fctid, "Optical model fit statistics: iterations = "
03896 "%d, DoF = %d, Chi-square = %.6g, Chi-square/DoF = "
03897 "%.6g, R-square = %.6g", iterations, df, chisq,
03898 chisq / df, rsquare);
03899
03900
03901
03902
03903
03904
03905
03906 setup->fcoll = giraffe_model_get_parameter(model, "FocalLength");
03907 setup->gcam = giraffe_model_get_parameter(model, "Magnification");
03908 setup->theta = giraffe_model_get_parameter(model, "Angle");
03909 setup->order = giraffe_model_get_parameter(model, "Order");
03910 setup->space = giraffe_model_get_parameter(model, "Spacing");
03911
03912 if (strcmp(giraffe_model_get_name(model), "xoptmod2") == 0) {
03913 setup->sdx = giraffe_model_get_parameter(model, "Sdx");
03914 setup->sdy = giraffe_model_get_parameter(model, "Sdy");
03915 setup->sphi = giraffe_model_get_parameter(model, "Sphi");
03916 }
03917
03918
03919
03920
03921
03922
03923
03924
03925
03926
03927
03928
03929
03930 cpl_msg_info(fctid, "Re-computing line positions with updated "
03931 "optical model");
03932
03933 xccd = _giraffe_line_abscissa(_lines, slitgeometry, fibers,
03934 solution, localization, FALSE);
03935
03936 giraffe_linedata_set_data(line_data, "Xccd", xccd);
03937 xccd = NULL;
03938
03939 }
03940 else {
03941
03942 cx_string *s = cx_string_new();
03943
03944 GiModel *model = giraffe_wlsolution_model(solution);
03945
03946
03947 _giraffe_opticalmodel_format(s, model, GI_OPTM_PARAMETER_VALUES);
03948 cpl_msg_info(fctid, "Optical model: %s", cx_string_get(s));
03949
03950 cx_string_delete(s);
03951 s = NULL;
03952
03953 }
03954
03955 rms = _giraffe_compute_statistics(line_data, NULL, NULL);
03956
03957 cpl_msg_info(fctid, "Average RMS [pxl] of line positions using "
03958 "%d of %d lines: %.4f", _ngood, _nlines * _nfibers,
03959 rms);
03960
03961
03962
03963
03964
03965
03966
03967 cpl_msg_info(fctid, "Fit of the wavelength solution coefficients "
03968 "using %" CX_PRINTF_FORMAT_SIZE_TYPE " lines",
03969 giraffe_linedata_accepted(line_data));
03970
03971 xws_setup.subslits = giraffe_wlsolution_get_subslits(solution);
03972 xws_setup.fit.xorder = config->xws_xorder;
03973 xws_setup.fit.yorder = config->xws_yorder;
03974
03975 cpl_msg_info(fctid, "Chebyshev polynomial order is (%d, %d).",
03976 xws_setup.fit.xorder, xws_setup.fit.yorder);
03977
03978 xws_setup.clip.iterations = config->xws_clipniter;
03979 xws_setup.clip.level = config->xws_cliplevel;
03980 xws_setup.clip.fraction = config->xws_clipmfrac;
03981
03982 cpl_msg_info(fctid, "Sigma clipping: iterations = %d, level = %.4f, "
03983 "fraction = %.4f", xws_setup.clip.iterations,
03984 xws_setup.clip.level, xws_setup.clip.fraction);
03985
03986 xws_coeffs = giraffe_wlresiduals_new();
03987
03988 xws_fit = _giraffe_residuals_fit(xws_coeffs, line_data, localization,
03989 fibers, slitgeometry, &xws_setup);
03990
03991
03992 if (xws_fit == NULL) {
03993
03994 cpl_msg_error(fctid, "Fit of the wavelength solution "
03995 "coefficients failed!");
03996
03997 giraffe_wlresiduals_delete(xws_coeffs);
03998
03999 cpl_table_delete(_lines);
04000 cpl_image_delete(line_status);
04001 giraffe_linedata_delete(line_data);
04002
04003 giraffe_grating_delete(setup);
04004
04005 _giraffe_lineparams_delete(line_setup);
04006
04007 giraffe_wlsolution_delete(solution);
04008
04009 return 12;
04010
04011 }
04012
04013
04014
04015
04016
04017
04018
04019 xres = cpl_image_new(giraffe_linedata_fibers(line_data),
04020 giraffe_linedata_lines(line_data),
04021 CPL_TYPE_DOUBLE);
04022
04023 _giraffe_get_residuals(xres,
04024 giraffe_linedata_get_data(line_data, "Xccd"),
04025 xws_fit);
04026 giraffe_linedata_set_data(line_data, "Xres", xres);
04027
04028
04029 if (giraffe_linedata_accepted(line_data) == 0) {
04030 cpl_msg_error(fctid, "No lines left after wavelength solution "
04031 "coefficients fit!");
04032
04033 giraffe_wlresiduals_delete(xws_coeffs);
04034
04035 cpl_table_delete(_lines);
04036 cpl_image_delete(line_status);
04037 cpl_image_delete(xws_fit);
04038 giraffe_linedata_delete(line_data);
04039
04040 giraffe_grating_delete(setup);
04041
04042 _giraffe_lineparams_delete(line_setup);
04043
04044 giraffe_wlsolution_delete(solution);
04045
04046 return 12;
04047
04048 }
04049
04050 cpl_msg_info(fctid, "Number of good lines: %"
04051 CX_PRINTF_FORMAT_SIZE_TYPE". %"
04052 CX_PRINTF_FORMAT_SIZE_TYPE" of %d lines "
04053 "rejected due to wavelength solution coefficients fit.",
04054 giraffe_linedata_accepted(line_data),
04055 giraffe_linedata_rejected(line_data) - _nreject, _ngood);
04056
04057 _ngood = giraffe_linedata_accepted(line_data);
04058 _nreject = giraffe_linedata_rejected(line_data);
04059
04060
04061
04062
04063
04064
04065 giraffe_wlsolution_set_residuals(solution, xws_coeffs);
04066 xws_coeffs = NULL;
04067
04068
04069
04070
04071
04072
04073
04074
04075 rms = _giraffe_compute_statistics(line_data, xws_fit, line_status);
04076
04077 cpl_msg_info(fctid, "Average RMS [pxl] of line positions using "
04078 "%d of %d lines: %.4f", _ngood, _nlines * _nfibers,
04079 rms);
04080
04081
04082
04083
04084
04085
04086 info.width = width;
04087
04088 info.residuals = residuals;
04089
04090 info.nlines = _nlines;
04091 info.nfibers = _nfibers;
04092
04093 info.ngood = _ngood;
04094 info.nreject = _nreject;
04095
04096 info.rms = rms;
04097
04098
04099
04100
04101
04102
04103 cpl_image_delete(xws_fit);
04104
04105 cpl_table_delete(_lines);
04106 cpl_image_delete(line_status);
04107
04108 }
04109
04110
04111
04112
04113
04114
04115
04116 tsolution = giraffe_table_new();
04117
04118 status = _giraffe_convert_wlsolution(tsolution, solution,
04119 extraction->spectra, setup,
04120 &info, config);
04121
04122 if (status != 0) {
04123
04124 giraffe_table_delete(tsolution);
04125
04126 giraffe_grating_delete(setup);
04127
04128 _giraffe_lineparams_delete(line_setup);
04129
04130 giraffe_wlsolution_delete(solution);
04131
04132 return 13;
04133
04134 }
04135
04136
04137
04138
04139
04140
04141 result->coeffs = tsolution;
04142 tsolution = NULL;
04143
04144 result->linedata = line_data;
04145
04146
04147
04148
04149
04150
04151 giraffe_grating_delete(setup);
04152 giraffe_wlsolution_delete(solution);
04153
04154 _giraffe_lineparams_delete(line_setup);
04155
04156 return 0;
04157
04158 }
04159
04160
04171 GiWCalConfig *
04172 giraffe_wlcalibration_config_create(cpl_parameterlist *list)
04173 {
04174
04175 const cxchar *s = NULL;
04176 const cpl_parameter *p = NULL;
04177
04178 GiWCalConfig *config = NULL;
04179
04180
04181 if (!list) {
04182 return NULL;
04183 }
04184
04185 config = cx_calloc(1, sizeof *config);
04186
04187
04188
04189
04190
04191
04192
04193 config->line_saturation = 1.e7;
04194
04195
04196
04197
04198
04199
04200 p = cpl_parameterlist_find(list, "giraffe.wlcalibration.line.widths");
04201 s = cpl_parameter_get_string(p);
04202
04203 if (s) {
04204
04205 cxchar **values = cx_strsplit(s, ",", -1);
04206
04207
04208 if (values == NULL) {
04209
04210 giraffe_wlcalibration_config_destroy(config);
04211 return NULL;
04212
04213 }
04214 else {
04215
04216 cxchar *last;
04217
04218 cxint n = 0;
04219
04220
04221 while (values[n] != NULL) {
04222 ++n;
04223 }
04224
04225 config->line_nwidths = n;
04226 config->line_widths = cx_malloc(n * sizeof(cxint));
04227 cx_assert(config->line_widths != NULL);
04228
04229 n = 0;
04230 while (values[n] != NULL) {
04231
04232 cxint w = strtol(values[n], &last, 10);
04233
04234 if (*last != '\0') {
04235 cx_strfreev(values);
04236 giraffe_wlcalibration_config_destroy(config);
04237
04238 return NULL;
04239 }
04240
04241 config->line_widths[n] = w;
04242 ++n;
04243
04244 }
04245
04246 if (n > 1) {
04247 qsort(config->line_widths, config->line_nwidths,
04248 sizeof(cxint), _giraffe_window_compare);
04249 }
04250
04251 cx_strfreev(values);
04252 values = NULL;
04253
04254 }
04255
04256 }
04257
04258
04259 p = cpl_parameterlist_find(list, "giraffe.wlcalibration.line.separation");
04260 config->line_separation = fabs(cpl_parameter_get_double(p));
04261
04262 p = cpl_parameterlist_find(list, "giraffe.wlcalibration.line.fluxratio");
04263 config->line_fluxratio = cpl_parameter_get_double(p);
04264
04265 p = cpl_parameterlist_find(list, "giraffe.wlcalibration.line.brightness");
04266 config->line_brightness = cpl_parameter_get_double(p);
04267
04268 p = cpl_parameterlist_find(list, "giraffe.wlcalibration.line.count");
04269 config->line_count = cpl_parameter_get_int(p);
04270
04271 p = cpl_parameterlist_find(list, "giraffe.wlcalibration.line.wrange");
04272 s = cpl_parameter_get_string(p);
04273
04274 if (s) {
04275
04276 cxchar **values = cx_strsplit(s, ",", 3);
04277
04278 if (values == NULL) {
04279
04280 giraffe_wlcalibration_config_destroy(config);
04281 return NULL;
04282
04283 }
04284 else {
04285
04286 cxchar *last;
04287
04288 cxdouble lower = 0.;
04289 cxdouble upper = 0.;
04290
04291
04292 lower = strtod(values[0], &last);
04293
04294 if (*last != '\0') {
04295
04296 cx_strfreev(values);
04297 giraffe_wlcalibration_config_destroy(config);
04298
04299 return NULL;
04300
04301 }
04302
04303 lower = lower >= 0. ? lower : 0.;
04304
04305
04306 if (values[1] != NULL) {
04307
04308 upper = strtod(values[1], &last);
04309
04310 if (*last != '\0') {
04311
04312 cx_strfreev(values);
04313 giraffe_wlcalibration_config_destroy(config);
04314
04315 return NULL;
04316
04317 }
04318
04319 upper = upper > lower ? upper : 0.;
04320
04321 }
04322
04323 config->line_wlrange = giraffe_range_create(lower, upper);
04324 cx_assert(config->line_wlrange != NULL);
04325
04326 }
04327
04328 cx_strfreev(values);
04329 values = NULL;
04330
04331 }
04332
04333
04334 p = cpl_parameterlist_find(list, "giraffe.wlcalibration.line.model");
04335 s = cpl_parameter_get_string(p);
04336
04337 if (strcmp(s, "psfexp") != 0 &&
04338 strcmp(s, "psfexp2") != 0 &&
04339 strcmp(s, "gaussian") != 0) {
04340
04341 giraffe_wlcalibration_config_destroy(config);
04342 return NULL;
04343
04344 }
04345 else {
04346 config->line_model = cx_strdup(s);
04347 }
04348
04349
04350 p = cpl_parameterlist_find(list, "giraffe.wlcalibration.line.residuals");
04351 s = cpl_parameter_get_string(p);
04352
04353 if (strcmp(s, "auto") != 0 &&
04354 strcmp(s, "enable") != 0 &&
04355 strcmp(s, "disable") != 0) {
04356
04357 giraffe_wlcalibration_config_destroy(config);
04358 return NULL;
04359
04360 }
04361 else {
04362 config->line_residuals = cx_strdup(s);
04363 }
04364
04365
04366 p = cpl_parameterlist_find(list, "giraffe.wlcalibration.line.threshold");
04367 config->line_threshold = cpl_parameter_get_double(p);
04368
04369 p = cpl_parameterlist_find(list, "giraffe.wlcalibration.line.offset");
04370 config->line_offset = cpl_parameter_get_double(p);
04371
04372 p = cpl_parameterlist_find(list, "giraffe.wlcalibration.line.iterations");
04373 config->line_niter = cpl_parameter_get_int(p);
04374
04375 p = cpl_parameterlist_find(list, "giraffe.wlcalibration.line.tests");
04376 config->line_ntest = cpl_parameter_get_int(p);
04377
04378 p = cpl_parameterlist_find(list, "giraffe.wlcalibration.line.dchisquare");
04379 config->line_dchisq = cpl_parameter_get_double(p);
04380
04381 p = cpl_parameterlist_find(list, "giraffe.wlcalibration.line.rwidthratio");
04382 config->line_rwidthratio = cpl_parameter_get_double(p);
04383
04384 p = cpl_parameterlist_find(list, "giraffe.wlcalibration.line.exponent");
04385 config->line_widthexponent = cpl_parameter_get_double(p);
04386
04387
04388 p = cpl_parameterlist_find(list, "giraffe.wlcalibration.slit.offset");
04389 s = cpl_parameter_get_string(p);
04390
04391 cx_assert(s != NULL);
04392
04393 if (cx_strncasecmp(s, "setup", 5) != 0) {
04394
04395 cxchar **values = cx_strsplit(s, ",", 4);
04396
04397
04398 config->slit_position = 0;
04399 config->slit_dx = 0.;
04400 config->slit_dy = 0.;
04401 config->slit_phi = 0.;
04402
04403 if (values == NULL || values[0] == NULL) {
04404
04405 giraffe_wlcalibration_config_destroy(config);
04406 return NULL;
04407
04408 }
04409 else {
04410
04411 cxbool eol = FALSE;
04412
04413 if (*values[0] != '\0') {
04414
04415 cxchar *last;
04416 cxdouble sdx = strtod(values[0], &last);
04417
04418 if (*last != '\0') {
04419 cx_strfreev(values);
04420 values = NULL;
04421
04422 giraffe_wlcalibration_config_destroy(config);
04423
04424 return NULL;
04425 }
04426
04427 config->slit_position |= SLIT_DX;
04428 config->slit_dx = sdx;
04429
04430 }
04431
04432 if (values[1] == NULL) {
04433 eol = TRUE;
04434 }
04435 else {
04436
04437 if (*values[1] != '\0') {
04438
04439 cxchar *last;
04440 cxdouble sdy = strtod(values[1], &last);
04441
04442 if (*last != '\0') {
04443 cx_strfreev(values);
04444 values = NULL;
04445
04446 giraffe_wlcalibration_config_destroy(config);
04447
04448 return NULL;
04449 }
04450
04451 config->slit_position |= SLIT_DY;
04452 config->slit_dy = sdy;
04453
04454 }
04455
04456 }
04457
04458 if (!eol && values[2] != NULL) {
04459
04460 if (*values[2] != '\0') {
04461
04462 cxchar *last;
04463 cxdouble sphi = strtod(values[2], &last);
04464
04465 if (*last != '\0') {
04466 cx_strfreev(values);
04467 values = NULL;
04468
04469 giraffe_wlcalibration_config_destroy(config);
04470
04471 return NULL;
04472 }
04473
04474 config->slit_position |= SLIT_PHI;
04475 config->slit_phi = sphi;
04476
04477 }
04478
04479 }
04480
04481 cx_strfreev(values);
04482 values = NULL;
04483
04484 }
04485
04486 }
04487
04488
04489 p = cpl_parameterlist_find(list, "giraffe.wlcalibration.opt.model");
04490 s = cpl_parameter_get_string(p);
04491
04492 if (strcmp(s, "xoptmod") != 0 && strcmp(s, "xoptmod2") != 0) {
04493
04494 giraffe_wlcalibration_config_destroy(config);
04495 return NULL;
04496
04497 }
04498 else {
04499 config->opt_model = cx_strdup(s);
04500 }
04501
04502
04503 p = cpl_parameterlist_find(list, "giraffe.wlcalibration.opt.direction");
04504 config->opt_direction = cpl_parameter_get_int(p);
04505
04506 p = cpl_parameterlist_find(list, "giraffe.wlcalibration.opt.solution");
04507 config->opt_solution = cpl_parameter_get_bool(p);
04508
04509 p = cpl_parameterlist_find(list, "giraffe.wlcalibration.opt.subslits");
04510 config->opt_subslits = cpl_parameter_get_bool(p);
04511
04512 p = cpl_parameterlist_find(list, "giraffe.wlcalibration.opt.flags");
04513 s = cpl_parameter_get_string(p);
04514
04515 if (s) {
04516
04517 cxchar **values = cx_strsplit(s, ",", -1);
04518
04519 if (values == NULL) {
04520
04521 giraffe_wlcalibration_config_destroy(config);
04522 return NULL;
04523
04524 }
04525 else {
04526
04527 cxint i = 0;
04528 cxint n = 0;
04529
04530 config->opt_flags = 0;
04531
04532 while (values[i] != NULL) {
04533
04534 if (strncmp(values[i], "fcoll", 5) == 0) {
04535 config->opt_flags |= OPTM_FLENGTH;
04536 ++n;
04537 }
04538 else if (strncmp(values[i], "gcam", 4) == 0) {
04539 config->opt_flags |= OPTM_GCAMERA;
04540 ++n;
04541 }
04542 else if (strncmp(values[i], "theta", 5) == 0) {
04543 config->opt_flags |= OPTM_THETA;
04544 ++n;
04545 }
04546 else if (strncmp(values[i], "sdx", 3) == 0) {
04547 config->opt_flags |= OPTM_SX;
04548 ++n;
04549 }
04550 else if (strncmp(values[i], "sdy", 3) == 0) {
04551 config->opt_flags |= OPTM_SY;
04552 ++n;
04553 }
04554 else if (strncmp(values[i], "sphi", 4) == 0) {
04555 config->opt_flags |= OPTM_SPHI;
04556 ++n;
04557 }
04558
04559 ++i;
04560
04561 }
04562
04563 cx_strfreev(values);
04564 values = NULL;
04565
04566
04567
04568
04569
04570
04571 if (n == 0) {
04572 giraffe_wlcalibration_config_destroy(config);
04573 return NULL;
04574 }
04575
04576 }
04577
04578 }
04579
04580
04581 p = cpl_parameterlist_find(list, "giraffe.wlcalibration.opt.iterations");
04582 config->opt_niter = cpl_parameter_get_int(p);
04583
04584 p = cpl_parameterlist_find(list, "giraffe.wlcalibration.opt.tests");
04585 config->opt_ntest = cpl_parameter_get_int(p);
04586
04587 p = cpl_parameterlist_find(list, "giraffe.wlcalibration.opt.dchisquare");
04588 config->opt_dchisq = cpl_parameter_get_double(p);
04589
04590
04591 p = cpl_parameterlist_find(list, "giraffe.wlcalibration.psf.sigma");
04592 config->pxw_cliplevel = cpl_parameter_get_double(p);
04593
04594 p = cpl_parameterlist_find(list, "giraffe.wlcalibration.psf.iterations");
04595 config->pxw_clipniter = cpl_parameter_get_int(p);
04596
04597 p = cpl_parameterlist_find(list, "giraffe.wlcalibration.psf.fraction");
04598 config->pxw_clipmfrac = cpl_parameter_get_double(p);
04599
04600 p = cpl_parameterlist_find(list, "giraffe.wlcalibration.psf.order");
04601 s = cpl_parameter_get_string(p);
04602
04603 if (s) {
04604
04605 cxchar **values = cx_strsplit(s, ",", 3);
04606
04607 if (values == NULL || values[1] == NULL) {
04608
04609 giraffe_wlcalibration_config_destroy(config);
04610 return NULL;
04611
04612 }
04613 else {
04614
04615 cxchar *last;
04616
04617
04618 config->pxw_xorder = strtol(values[0], &last, 10);
04619
04620 if (*last != '\0') {
04621
04622 cx_strfreev(values);
04623 giraffe_wlcalibration_config_destroy(config);
04624
04625 return NULL;
04626
04627 }
04628
04629 config->pxw_yorder = strtol(values[1], &last, 10);
04630
04631 if (*last != '\0') {
04632
04633 cx_strfreev(values);
04634 giraffe_wlcalibration_config_destroy(config);
04635
04636 return NULL;
04637
04638 }
04639
04640 }
04641
04642 cx_strfreev(values);
04643 values = NULL;
04644
04645 }
04646
04647
04648 p = cpl_parameterlist_find(list, "giraffe.wlcalibration.wsol.sigma");
04649 config->xws_cliplevel = cpl_parameter_get_double(p);
04650
04651 p = cpl_parameterlist_find(list, "giraffe.wlcalibration.wsol.iterations");
04652 config->xws_clipniter = cpl_parameter_get_int(p);
04653
04654 p = cpl_parameterlist_find(list, "giraffe.wlcalibration.wsol.fraction");
04655 config->xws_clipmfrac = cpl_parameter_get_double(p);
04656
04657 p = cpl_parameterlist_find(list, "giraffe.wlcalibration.wsol.order");
04658 s = cpl_parameter_get_string(p);
04659
04660 if (s) {
04661
04662 cxchar **values = cx_strsplit(s, ",", 3);
04663
04664 if (values == NULL || values[1] == NULL) {
04665
04666 giraffe_wlcalibration_config_destroy(config);
04667 return NULL;
04668
04669 }
04670 else {
04671
04672 cxchar *last;
04673
04674
04675 config->xws_xorder = strtol(values[0], &last, 10);
04676
04677 if (*last != '\0') {
04678
04679 cx_strfreev(values);
04680 giraffe_wlcalibration_config_destroy(config);
04681
04682 return NULL;
04683
04684 }
04685
04686 config->xws_yorder = strtol(values[1], &last, 10);
04687
04688 if (*last != '\0') {
04689
04690 cx_strfreev(values);
04691 giraffe_wlcalibration_config_destroy(config);
04692
04693 return NULL;
04694
04695 }
04696
04697 }
04698
04699 cx_strfreev(values);
04700 values = NULL;
04701
04702 }
04703
04704 return config;
04705
04706 }
04707
04708
04721 void
04722 giraffe_wlcalibration_config_destroy(GiWCalConfig *config)
04723 {
04724
04725 if (config) {
04726 if (config->line_widths) {
04727 cx_free(config->line_widths);
04728 }
04729
04730 if (config->line_wlrange) {
04731 giraffe_range_delete(config->line_wlrange);
04732 }
04733
04734 if (config->line_model) {
04735 cx_free(config->line_model);
04736 }
04737
04738 if (config->line_residuals) {
04739 cx_free(config->line_residuals);
04740 }
04741
04742 if (config->opt_model) {
04743 cx_free(config->opt_model);
04744 }
04745
04746 cx_free(config);
04747 }
04748
04749 return;
04750
04751 }
04752
04753
04765 void
04766 giraffe_wlcalibration_config_add(cpl_parameterlist *list)
04767 {
04768
04769 cpl_parameter *p;
04770
04771
04772 if (!list) {
04773 return;
04774 }
04775
04776
04777
04778
04779
04780
04781 p = cpl_parameter_new_value("giraffe.wlcalibration.line.widths",
04782 CPL_TYPE_STRING,
04783 "List of window widths [pxl] used for line "
04784 "detection and fit (e.g. '60,40,15').",
04785 "giraffe.wlcalibration",
04786 "10,10,10,10,10");
04787 cpl_parameter_set_alias(p, CPL_PARAMETER_MODE_CLI, "wcal-lswidth");
04788 cpl_parameterlist_append(list, p);
04789
04790
04791 p = cpl_parameter_new_value("giraffe.wlcalibration.line.separation",
04792 CPL_TYPE_DOUBLE,
04793 "Factor used to compute the minimum line "
04794 "separation from the window width.",
04795 "giraffe.wlcalibration",
04796 0.9);
04797 cpl_parameter_set_alias(p, CPL_PARAMETER_MODE_CLI, "wcal-lssep");
04798 cpl_parameterlist_append(list, p);
04799
04800
04801 p = cpl_parameter_new_value("giraffe.wlcalibration.line.fluxratio",
04802 CPL_TYPE_DOUBLE,
04803 "Selects only lines whose neighbours have "
04804 "a relative intensity less than "
04805 "1. / fluxratio.",
04806 "giraffe.wlcalibration",
04807 50.);
04808
04809 cpl_parameter_set_alias(p, CPL_PARAMETER_MODE_CLI, "wcal-lsfxratio");
04810 cpl_parameterlist_append(list, p);
04811
04812
04813 p = cpl_parameter_new_value("giraffe.wlcalibration.line.brightness",
04814 CPL_TYPE_DOUBLE,
04815 "Selects lines having an intensity greater "
04816 "or equal to the given intensity.",
04817 "giraffe.wlcalibration",
04818 0.);
04819
04820 cpl_parameter_set_alias(p, CPL_PARAMETER_MODE_CLI, "wcal-lsbright");
04821 cpl_parameterlist_append(list, p);
04822
04823
04824 p = cpl_parameter_new_value("giraffe.wlcalibration.line.count",
04825 CPL_TYPE_INT,
04826 "Sets the minimum number of lines to select; "
04827 "selected are lines with the highest nominal "
04828 "intensity. A value of 0 turns this selection "
04829 "off. If the value is less than 0 the "
04830 "selection is skipped if the line list does "
04831 "not contain enough lines.",
04832 "giraffe.wlcalibration",
04833 -80);
04834
04835 cpl_parameter_set_alias(p, CPL_PARAMETER_MODE_CLI, "wcal-lscount");
04836 cpl_parameterlist_append(list, p);
04837
04838
04839 p = cpl_parameter_new_value("giraffe.wlcalibration.line.wrange",
04840 CPL_TYPE_STRING,
04841 "Selects only lines within the given "
04842 "wavelength range [nm].",
04843 "giraffe.wlcalibration",
04844 "0.,0.");
04845
04846 cpl_parameter_set_alias(p, CPL_PARAMETER_MODE_CLI, "wcal-lswrange");
04847 cpl_parameterlist_append(list, p);
04848
04849
04850
04851
04852
04853
04854 p = cpl_parameter_new_enum("giraffe.wlcalibration.line.model",
04855 CPL_TYPE_STRING,
04856 "Line profile model.",
04857 "giraffe.wlcalibration",
04858 "psfexp", 3, "psfexp", "psfexp2", "gaussian");
04859
04860 cpl_parameter_set_alias(p, CPL_PARAMETER_MODE_CLI, "wcal-lfmodel");
04861 cpl_parameterlist_append(list, p);
04862
04863
04864 p = cpl_parameter_new_enum("giraffe.wlcalibration.line.residuals",
04865 CPL_TYPE_STRING,
04866 "Use optical model residuals for line "
04867 "detection.",
04868 "giraffe.wlcalibration",
04869 "auto", 3, "auto", "enable", "disable");
04870
04871 cpl_parameter_set_alias(p, CPL_PARAMETER_MODE_CLI, "wcal-lfres");
04872 cpl_parameterlist_append(list, p);
04873
04874
04875 p = cpl_parameter_new_value("giraffe.wlcalibration.line.threshold",
04876 CPL_TYPE_DOUBLE,
04877 "Line detection threshold during the "
04878 "line fitting (multiple of bias sigma)",
04879 "giraffe.wlcalibration",
04880 1.);
04881
04882 cpl_parameter_set_alias(p, CPL_PARAMETER_MODE_CLI, "wcal-lfthreshold");
04883 cpl_parameterlist_append(list, p);
04884
04885
04886 p = cpl_parameter_new_value("giraffe.wlcalibration.line.offset",
04887 CPL_TYPE_DOUBLE,
04888 "Maximum allowed difference between the "
04889 "fitted and raw line peak position.",
04890 "giraffe.wlcalibration",
04891 10.);
04892
04893 cpl_parameter_set_alias(p, CPL_PARAMETER_MODE_CLI, "wcal-lfoffset");
04894 cpl_parameterlist_append(list, p);
04895
04896
04897 p = cpl_parameter_new_value("giraffe.wlcalibration.line.iterations",
04898 CPL_TYPE_INT,
04899 "Line detection fit maximum number of "
04900 "iterations.",
04901 "giraffe.wlcalibration",
04902 50);
04903
04904 cpl_parameter_set_alias(p, CPL_PARAMETER_MODE_CLI, "wcal-lfniter");
04905 cpl_parameterlist_append(list, p);
04906
04907
04908 p = cpl_parameter_new_value("giraffe.wlcalibration.line.tests",
04909 CPL_TYPE_INT,
04910 "Line detection fit maximum number of "
04911 "tests.",
04912 "giraffe.wlcalibration",
04913 7);
04914
04915 cpl_parameter_set_alias(p, CPL_PARAMETER_MODE_CLI, "wcal-lfntest");
04916 cpl_parameterlist_append(list, p);
04917
04918
04919 p = cpl_parameter_new_value("giraffe.wlcalibration.line.dchisquare",
04920 CPL_TYPE_DOUBLE,
04921 "Line detection fit minimum chi-square "
04922 "difference.",
04923 "giraffe.wlcalibration",
04924 0.0001);
04925
04926 cpl_parameter_set_alias(p, CPL_PARAMETER_MODE_CLI, "wcal-lfdchisq");
04927 cpl_parameterlist_append(list, p);
04928
04929
04930 p = cpl_parameter_new_value("giraffe.wlcalibration.line.rwidthratio",
04931 CPL_TYPE_DOUBLE,
04932 "Line width/resolution width factor.",
04933 "giraffe.wlcalibration",
04934 0.5);
04935
04936 cpl_parameter_set_alias(p, CPL_PARAMETER_MODE_CLI, "wcal-lfreswid");
04937 cpl_parameterlist_append(list, p);
04938
04939
04940 p = cpl_parameter_new_value("giraffe.wlcalibration.line.exponent",
04941 CPL_TYPE_DOUBLE,
04942 "Exponential line profile exponent; it will "
04943 "not be fitted if it is larger than 0.",
04944 "giraffe.wlcalibration",
04945 -3.);
04946
04947 cpl_parameter_set_alias(p, CPL_PARAMETER_MODE_CLI, "wcal-lfexpwid");
04948 cpl_parameterlist_append(list, p);
04949
04950
04951
04952
04953
04954
04955
04956 p = cpl_parameter_new_value("giraffe.wlcalibration.slit.offset",
04957 CPL_TYPE_STRING,
04958 "Initial slit position offsets along the "
04959 "x and y direction and rotation angle.",
04960 "giraffe.wlcalibration",
04961 "setup");
04962
04963 cpl_parameter_set_alias(p, CPL_PARAMETER_MODE_CLI, "wcal-soffset");
04964 cpl_parameterlist_append(list, p);
04965
04966
04967
04968
04969
04970
04971 p = cpl_parameter_new_enum("giraffe.wlcalibration.opt.model",
04972 CPL_TYPE_STRING,
04973 "Optical model.",
04974 "giraffe.wlcalibration",
04975 "xoptmod2", 2, "xoptmod", "xoptmod2");
04976
04977 cpl_parameter_set_alias(p, CPL_PARAMETER_MODE_CLI, "wcal-ommodel");
04978 cpl_parameterlist_append(list, p);
04979
04980
04981 p = cpl_parameter_new_value("giraffe.wlcalibration.opt.direction",
04982 CPL_TYPE_INT,
04983 "Dispersion direction flag.",
04984 "giraffe.wlcalibration",
04985 1);
04986
04987 cpl_parameter_set_alias(p, CPL_PARAMETER_MODE_CLI, "wcal-omdir");
04988 cpl_parameterlist_append(list, p);
04989
04990
04991 p = cpl_parameter_new_value("giraffe.wlcalibration.opt.solution",
04992 CPL_TYPE_BOOL,
04993 "Controls optical model parameter fitting.",
04994 "giraffe.wlcalibration",
04995 TRUE);
04996
04997 cpl_parameter_set_alias(p, CPL_PARAMETER_MODE_CLI, "wcal-omsol");
04998 cpl_parameterlist_append(list, p);
04999
05000
05001 p = cpl_parameter_new_value("giraffe.wlcalibration.opt.flags",
05002 CPL_TYPE_STRING,
05003 "List of flags defining the set of free "
05004 "parameters used for fitting the optical "
05005 "model. Possible values are: fcoll, gcam, "
05006 "theta, sdx, sdy, sphi",
05007 "giraffe.wlcalibration",
05008 "sdx,sdy,sphi");
05009
05010 cpl_parameter_set_alias(p, CPL_PARAMETER_MODE_CLI, "wcal-omflags");
05011 cpl_parameterlist_append(list, p);
05012
05013
05014 p = cpl_parameter_new_value("giraffe.wlcalibration.opt.subslits",
05015 CPL_TYPE_BOOL,
05016 "Controls subslit geometry usage in the "
05017 "optical model fit; subslits are used if "
05018 "set to `true'.",
05019 "giraffe.wlcalibration",
05020 FALSE);
05021
05022 cpl_parameter_set_alias(p, CPL_PARAMETER_MODE_CLI, "wcal-omsslits");
05023 cpl_parameterlist_append(list, p);
05024
05025
05026 p = cpl_parameter_new_value("giraffe.wlcalibration.opt.iterations",
05027 CPL_TYPE_INT,
05028 "Optical model fit maximum number of "
05029 "iterations.",
05030 "giraffe.wlcalibration",
05031 50);
05032
05033 cpl_parameter_set_alias(p, CPL_PARAMETER_MODE_CLI, "wcal-omniter");
05034 cpl_parameterlist_append(list, p);
05035
05036
05037 p = cpl_parameter_new_value("giraffe.wlcalibration.opt.tests",
05038 CPL_TYPE_INT,
05039 "Optical model fit maximum number of "
05040 "tests",
05041 "giraffe.wlcalibration",
05042 7);
05043
05044 cpl_parameter_set_alias(p, CPL_PARAMETER_MODE_CLI, "wcal-omntest");
05045 cpl_parameterlist_append(list, p);
05046
05047
05048 p = cpl_parameter_new_value("giraffe.wlcalibration.opt.dchisquare",
05049 CPL_TYPE_DOUBLE,
05050 "Optical model fit minimum chi-square "
05051 "difference.",
05052 "giraffe.wlcalibration",
05053 0.0001);
05054
05055 cpl_parameter_set_alias(p, CPL_PARAMETER_MODE_CLI, "wcal-omdchisq");
05056 cpl_parameterlist_append(list, p);
05057
05058
05059
05060
05061
05062
05063 p = cpl_parameter_new_value("giraffe.wlcalibration.psf.sigma",
05064 CPL_TYPE_DOUBLE,
05065 "PSF width fit sigma clipping factor.",
05066 "giraffe.wlcalibration",
05067 1.25);
05068
05069 cpl_parameter_set_alias(p, CPL_PARAMETER_MODE_CLI, "wcal-xwsigma");
05070 cpl_parameterlist_append(list, p);
05071
05072
05073 p = cpl_parameter_new_value("giraffe.wlcalibration.psf.iterations",
05074 CPL_TYPE_INT,
05075 "PSF width fit sigma clipping maximum "
05076 "number of iterations.",
05077 "giraffe.wlcalibration",
05078 10);
05079
05080 cpl_parameter_set_alias(p, CPL_PARAMETER_MODE_CLI, "wcal-xwniter");
05081 cpl_parameterlist_append(list, p);
05082
05083
05084 p = cpl_parameter_new_range("giraffe.wlcalibration.psf.fraction",
05085 CPL_TYPE_DOUBLE,
05086 "PSF width fit sigma clipping minimum "
05087 "fraction of points accepted/total.",
05088 "giraffe.wlcalibration",
05089 0.9, 0., 1.);
05090
05091 cpl_parameter_set_alias(p, CPL_PARAMETER_MODE_CLI, "wcal-xwmfrac");
05092 cpl_parameterlist_append(list, p);
05093
05094
05095 p = cpl_parameter_new_value("giraffe.wlcalibration.psf.order",
05096 CPL_TYPE_STRING,
05097 "X and Y polynomial orders for PSF x-width "
05098 "Chebyshev fit.",
05099 "giraffe.wlcalibration",
05100 "2,2");
05101
05102 cpl_parameter_set_alias(p, CPL_PARAMETER_MODE_CLI, "wcal-xworder");
05103 cpl_parameterlist_append(list, p);
05104
05105
05106
05107
05108
05109
05110 p = cpl_parameter_new_value("giraffe.wlcalibration.wsol.sigma",
05111 CPL_TYPE_DOUBLE,
05112 "Chebyshev correction sigma clipping factor.",
05113 "giraffe.wlcalibration",
05114 150.0);
05115
05116 cpl_parameter_set_alias(p, CPL_PARAMETER_MODE_CLI, "wcal-wssigma");
05117 cpl_parameterlist_append(list, p);
05118
05119
05120 p = cpl_parameter_new_value("giraffe.wlcalibration.wsol.iterations",
05121 CPL_TYPE_INT,
05122 "Chebyshev correction sigma clipping "
05123 "maximum number of iterations",
05124 "giraffe.wlcalibration",
05125 10);
05126
05127 cpl_parameter_set_alias(p, CPL_PARAMETER_MODE_CLI, "wcal-wsniter");
05128 cpl_parameterlist_append(list, p);
05129
05130
05131 p = cpl_parameter_new_range("giraffe.wlcalibration.wsol.fraction",
05132 CPL_TYPE_DOUBLE,
05133 "Chebyshev correction sigma clipping "
05134 "minimum fraction of points accepted/total.",
05135 "giraffe.wlcalibration",
05136 0.9, 0., 1.);
05137
05138 cpl_parameter_set_alias(p, CPL_PARAMETER_MODE_CLI, "wcal-wsmfrac");
05139 cpl_parameterlist_append(list, p);
05140
05141
05142 p = cpl_parameter_new_value("giraffe.wlcalibration.wsol.order",
05143 CPL_TYPE_STRING,
05144 "X and Y polynomial orders for the wavelength "
05145 "solution Chebyshev correction.",
05146 "giraffe.wlcalibration",
05147 "6,4");
05148
05149 cpl_parameter_set_alias(p, CPL_PARAMETER_MODE_CLI, "wcal-wsorder");
05150 cpl_parameterlist_append(list, p);
05151
05152 return;
05153
05154 }