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 <math.h>
00033
00034 #include <cxmacros.h>
00035 #include <cxtypes.h>
00036 #include <cxstrutils.h>
00037
00038 #include <cpl_parameter.h>
00039 #include <cpl_frameset.h>
00040
00041 #include "gimacros.h"
00042 #include "gidebug.h"
00043 #include "gialias.h"
00044 #include "giframe.h"
00045 #include "giimage.h"
00046 #include "giimagestack.h"
00047 #include "gitable.h"
00048 #include "gimatrix.h"
00049 #include "giextraction.h"
00050 #include "gimath.h"
00051 #include "gigrating.h"
00052 #include "giutils.h"
00053 #include "giwavecalib_types.h"
00054 #include "giwavecalib.h"
00055
00056 #define GI_ENABLE_DEBUG 1
00057
00058 #define GIFRAME_WAVE_CALIB_FIT_XCENT "XCENTER"
00059 #define GIFRAME_WAVE_CALIB_FIT_YCENT "YCENTER"
00060 #define GIFRAME_WAVE_CALIB_FIT_ALFIT "AMPLITUDE"
00061 #define GIFRAME_WAVE_CALIB_FIT_BBFIT "BACKGROUND"
00062 #define GIFRAME_WAVE_CALIB_FIT_WDFIT "WIDTH"
00063 #define GIFRAME_WAVE_CALIB_FIT_SDFIT "SIGWIDTH"
00064 #define GIFRAME_WAVE_CALIB_FIT_SCFIT "SIGCENTER"
00065
00066 #define WAVELENGTH_TABLE_BLEND "BLEND"
00067 #define WAVELENGTH_TABLE_SELECT "SELECT"
00068 #define WAVELENGTH_TABLE_SORT "SORT"
00069 #define WAVELENGTH_TABLE_COMMENT "COMMENT"
00070 #define WAVELENGTH_TABLE_WLEN "WLEN"
00071 #define WAVELENGTH_TABLE_WLENPIX "WLENPIX"
00072 #define WAVELENGTH_TABLE_FLUX "FLUX"
00073 #define WAVELENGTH_SETUP_DIVISOR 500.0
00074
00075
00099
00100
00101
00102
00103 enum _GiWcalLineType_ {
00104 GIWCALLINETYPE_UNDEFINED,
00105 GIWCALLINETYPE_THARNE,
00106 GIWCALLINETYPE_TELLURIC
00107 };
00108
00109 typedef enum _GiWcalLineType_ GiWcalLineType;
00110
00111
00112
00113
00114
00115
00116 struct _GiClipParams_ {
00117 cxdouble sigma;
00118 cxdouble mfrac;
00119 cxint niter;
00120 };
00121
00122 typedef struct _GiClipParams_ GiClipParams;
00123
00124
00125
00126
00127
00128
00129 struct _GiPolyDeg_ {
00130 cxint xdeg;
00131 cxint ydeg;
00132 cxint ncoeffs;
00133 };
00134
00135 typedef struct _GiPolyDeg_ GiPolyDeg;
00136
00137
00174 inline static cxint
00175 _giraffe_wavelength_setup(GiTable *wavelength_table, GiGrating *grating_setup,
00176 GiWcalConfig *wcp)
00177 {
00178
00179 const cxchar *fctid = "_giraffe_wavelength_setup";
00180
00181
00182 cpl_table *ref_wtable = NULL;
00183
00184 cxint ce_code;
00185 cxint nr_ref_wtable;
00186 cxint i;
00187 cxint j;
00188 cxint row_nulls = 0;
00189 cxint row_curr;
00190 cxint row_max;
00191 cxint tmp_select;
00192 cxint tmp_sort;
00193 cxint num_blended_lines = 0;
00194
00195 cxdouble tmp_wlmin = 0.0,
00196 tmp_wlmax = 0.0,
00197 tmp_wldelta = 0.0,
00198 tmp_wlcurr = 0.0,
00199 wldivisor = WAVELENGTH_SETUP_DIVISOR,
00200 tmp_wlen = 0.0,
00201 maxflux = 0.0,
00202 tmp_flux = 0.0;
00203
00204 cxchar *cn_blend = WAVELENGTH_TABLE_BLEND,
00205 *cn_select = WAVELENGTH_TABLE_SELECT,
00206 *cn_sort = WAVELENGTH_TABLE_SORT,
00207 *cn_comment = WAVELENGTH_TABLE_COMMENT,
00208 *cn_wlen = WAVELENGTH_TABLE_WLEN,
00209 *cn_flux = WAVELENGTH_TABLE_FLUX;
00210
00211 cxchar *tmp_comment;
00212
00213
00214
00215
00216
00217
00218 if (wavelength_table==NULL) { return 1; }
00219 if (grating_setup ==NULL) { return 1; }
00220 if (wcp ==NULL) { return 1; }
00221
00222 ref_wtable = giraffe_table_get(wavelength_table);
00223 nr_ref_wtable = cpl_table_get_nrow(ref_wtable);
00224
00225 ce_code = cpl_table_new_column_int(ref_wtable, cn_blend);
00226 ce_code = cpl_table_new_column_int(ref_wtable, cn_select);
00227 ce_code = cpl_table_new_column_int(ref_wtable, cn_sort);
00228
00229 ce_code =
00230 cpl_table_fill_column_int(ref_wtable,cn_blend,0,nr_ref_wtable-1,0);
00231 ce_code =
00232 cpl_table_fill_column_int(ref_wtable,cn_select,0,nr_ref_wtable-1,0);
00233 ce_code =
00234 cpl_table_fill_column_int(ref_wtable,cn_sort,0,nr_ref_wtable-1,-1);
00235
00236
00237
00238
00239
00240
00241
00242
00243
00244
00245 for (i=0; i<nr_ref_wtable; i++) {
00246
00247 tmp_comment =
00248 (cxchar*)cpl_table_get_string(ref_wtable, cn_comment, i);
00249
00250 if (strlen(cx_strstrip(tmp_comment))>3) {
00251 ce_code = cpl_table_set_int(ref_wtable, cn_blend, i, 1);
00252 num_blended_lines++;
00253 }
00254 }
00255
00256 cpl_msg_info(
00257 fctid,
00258 "Wavelengths Catalog initially contains %d lines",
00259 nr_ref_wtable
00260 );
00261
00262 cpl_msg_debug(
00263 fctid,
00264 "of which %d are not usable (blended etc.)",
00265 num_blended_lines
00266 );
00267
00268
00269
00270
00271
00272 cpl_msg_debug(
00273 fctid,
00274 "Standard wavelength range from grating data: [%f,%f]",
00275 grating_setup->wlenmin,
00276 grating_setup->wlenmax
00277 );
00278
00279 tmp_wlmin = grating_setup->wlenmin;
00280 tmp_wlmax = grating_setup->wlenmax;
00281
00282 if (wcp->range_wlen_min>0.0)
00283 tmp_wlmin = wcp->range_wlen_min;
00284
00285 if (wcp->range_wlen_max>0.0)
00286 tmp_wlmax = wcp->range_wlen_max;
00287
00288
00289
00290
00291
00292 tmp_wldelta = (tmp_wlmax-tmp_wlmin) / wldivisor;
00293
00294 tmp_wlmin += tmp_wldelta;
00295 tmp_wlmax -= tmp_wldelta;
00296
00297 cpl_msg_debug(fctid, "Modified Wavelength range : [%f,%f]",
00298 tmp_wlmin, tmp_wlmax);
00299
00300 cpl_msg_info(fctid, "Applying wavelength range restriction [%f,%f] on Wavelength Catalog",
00301 tmp_wlmin, tmp_wlmax);
00302
00303 cpl_msg_debug(fctid, "Removing wavelengths outside of wavelength range "
00304 "from Wavelength Catalog...");
00305
00306
00307
00308
00309
00310 for (i=0; i<nr_ref_wtable; i++) {
00311
00312 tmp_wlcurr =
00313 cpl_table_get_double(ref_wtable, cn_wlen, i, &row_nulls );
00314
00315 if ((tmp_wlcurr>=tmp_wlmin)&&(tmp_wlcurr<=tmp_wlmax)) {
00316 ce_code = cpl_table_set_int(ref_wtable, cn_select, i, 1);
00317 }
00318 }
00319
00320
00321
00322
00323
00324
00325
00326
00327
00328 row_curr = nr_ref_wtable - 1;
00329
00330 while (row_curr >= 0) {
00331
00332 tmp_select =
00333 cpl_table_get_int(ref_wtable, cn_select, row_curr, &row_nulls);
00334
00335 if (tmp_select==0) {
00336 row_curr--;
00337 } else {
00338 break;
00339 }
00340 }
00341
00342 ce_code =
00343 cpl_table_erase_segment(
00344 ref_wtable,
00345 row_curr+1,
00346 nr_ref_wtable-row_curr-1
00347 );
00348
00349 nr_ref_wtable = cpl_table_get_nrow(ref_wtable);
00350
00351 row_curr = 0;
00352
00353 while (row_curr < nr_ref_wtable) {
00354
00355 tmp_select =
00356 cpl_table_get_int(ref_wtable, cn_select, row_curr, &row_nulls);
00357
00358 if (tmp_select==0) {
00359 row_curr++;
00360 } else {
00361 break;
00362 }
00363 }
00364
00365 ce_code = cpl_table_erase_segment(ref_wtable, 0, row_curr);
00366
00367 nr_ref_wtable = cpl_table_get_nrow(ref_wtable);
00368
00369 cpl_msg_info(fctid, "Number of lines now in Wavelength Catalog : %d",
00370 nr_ref_wtable);
00371
00372
00373
00374
00375
00376 ce_code =
00377 cpl_table_fill_column_int(
00378 ref_wtable,
00379 cn_select,
00380 0,
00381 nr_ref_wtable,
00382 0
00383 );
00384
00385
00386
00387
00388
00389
00390 if ((wcp->bright_count>0)&&(wcp->bright_count<nr_ref_wtable)) {
00391
00392
00393
00394
00395
00396 cpl_msg_info(
00397 fctid,
00398 "Applying brightness criterium specified (%d brightest lines) on "
00399 "Wavelength Catalog",
00400 wcp->bright_count
00401 );
00402
00403 for (i=0; i<wcp->bright_count; i++) {
00404
00405 maxflux = -1.0;
00406 row_max = -1;
00407
00408 for(j=0; j<nr_ref_wtable;j++) {
00409
00410 tmp_sort =
00411 cpl_table_get_int(ref_wtable, cn_sort, j, &row_nulls);
00412
00413 if (tmp_sort<0) {
00414
00415 tmp_flux =
00416 cpl_table_get_double(
00417 ref_wtable,
00418 cn_flux,
00419 j,
00420 &row_nulls
00421 );
00422
00423 if (tmp_flux>maxflux) {
00424 maxflux = tmp_flux;
00425 row_max = j;
00426 }
00427 }
00428 }
00429
00430 ce_code = cpl_table_set_int(ref_wtable, cn_sort, row_max, i );
00431 ce_code = cpl_table_set_int(ref_wtable, cn_select, row_max, 1 );
00432
00433 }
00434
00435
00436
00437
00438
00439 row_curr = nr_ref_wtable - 1;
00440
00441 while (row_curr>=0) {
00442
00443 tmp_select =
00444 cpl_table_get_int(
00445 ref_wtable,
00446 cn_select,
00447 row_curr,
00448 &row_nulls
00449 );
00450
00451 if (tmp_select==0) {
00452 ce_code = cpl_table_erase_segment(ref_wtable, row_curr, 1 );
00453 }
00454
00455 row_curr--;
00456
00457 }
00458
00459 nr_ref_wtable = cpl_table_get_nrow(ref_wtable);
00460
00461 cpl_msg_info(fctid, "Number of lines now in Wavelength Catalog : %d",
00462 nr_ref_wtable);
00463
00464 } else if ( (wcp->bright_threshold>0.0 ) &&
00465 (wcp->bright_threshold!=CX_MAXDOUBLE) ) {
00466
00467
00468
00469
00470
00471 cpl_msg_info(
00472 fctid,
00473 "Applying brightness criterium specified (flux threshold %12.6f)"
00474 " on Wavelength Catalog",
00475 wcp->bright_threshold
00476 );
00477
00478 for (j=0; j<nr_ref_wtable;j++) {
00479
00480 tmp_flux =
00481 cpl_table_get_double(ref_wtable, cn_flux, j, &row_nulls);
00482
00483 if (tmp_flux>=wcp->bright_threshold) {
00484 ce_code = cpl_table_set_int(ref_wtable, cn_select, j, 1 );
00485 }
00486 }
00487
00488
00489
00490
00491
00492 row_curr = nr_ref_wtable - 1;
00493
00494 while (row_curr >= 0) {
00495
00496 tmp_select =
00497 cpl_table_get_int(
00498 ref_wtable,
00499 cn_select,
00500 row_curr,
00501 &row_nulls
00502 );
00503
00504 if (tmp_select==0) {
00505 ce_code = cpl_table_erase_segment(ref_wtable, row_curr, 1 );
00506 }
00507
00508 row_curr--;
00509 }
00510
00511 nr_ref_wtable = cpl_table_get_nrow(ref_wtable);
00512
00513 cpl_msg_info(fctid, "Number of lines now in Wavelength Catalog : %d",
00514 nr_ref_wtable);
00515
00516 } else {
00517
00518
00519
00520
00521
00522
00523 cpl_msg_warning(fctid, "Brightness criterium: None specified");
00524 }
00525
00526 nr_ref_wtable = cpl_table_get_nrow(ref_wtable);
00527
00528
00529
00530
00531
00532 for (j = 0; j < nr_ref_wtable; j++) {
00533
00534 tmp_wlen = cpl_table_get_double(ref_wtable, cn_wlen, j, &row_nulls);
00535 ce_code = cpl_table_set_double(ref_wtable, cn_wlen, j,
00536 tmp_wlen / GI_MM_TO_NM);
00537
00538 }
00539
00540 return 0;
00541
00542 }
00543
00571 static cxint
00572 giraffe_line_elimination(
00573 GiTable *wavelength_table,
00574 cxdouble wlen_conf_factor,
00575 cxdouble sep_minimum,
00576 cxdouble flux_ratio,
00577 cxdouble line_width
00578 ) {
00579
00580
00581
00582
00583
00584 const cxchar *fctid = "giraffe_line_elimination";
00585
00586 cpl_table *ref_wtable = NULL;
00587
00588 cxint ce_code;
00589 cxint nr_wtable,
00590 i,
00591 j,
00592 c1,
00593 c2,
00594 tmp_select,
00595 tmp_blend,
00596 row_nulls,
00597 row_curr,
00598 num_rows_orig,
00599 num_rows_remove;
00600
00601 cxchar *cn_select = WAVELENGTH_TABLE_SELECT,
00602 *cn_wlen = WAVELENGTH_TABLE_WLEN,
00603 *cn_wlenpix = WAVELENGTH_TABLE_WLENPIX,
00604 *cn_flux = WAVELENGTH_TABLE_FLUX,
00605 *cn_blend = WAVELENGTH_TABLE_BLEND;
00606
00607 cxdouble Ix,
00608 Lx,
00609 Iy,
00610 Ly,
00611 tmp_wlcurr;
00612
00613
00614
00615
00616
00617
00618 if (wavelength_table==NULL) { return 1; }
00619
00620 ref_wtable = giraffe_table_get(wavelength_table);
00621
00622 ce_code = cpl_table_new_column_double(ref_wtable, cn_wlenpix);
00623 nr_wtable = cpl_table_get_nrow(ref_wtable);
00624
00625 num_rows_orig = nr_wtable;
00626
00627
00628
00629
00630
00631 cpl_msg_info(
00632 fctid,
00633 "Applying crowding criteria on %d lines in Wavelength Catalog",
00634 nr_wtable
00635 );
00636
00637
00638
00639
00640
00641
00642 for (i=0; i<nr_wtable; i++) {
00643
00644 tmp_wlcurr =
00645 cpl_table_get_double(ref_wtable, cn_wlen, i, &row_nulls );
00646
00647 ce_code =
00648 cpl_table_set_double(ref_wtable, cn_wlenpix, i,
00649 tmp_wlcurr * wlen_conf_factor );
00650
00651 ce_code = cpl_table_set_int(ref_wtable, cn_select, i, 0 );
00652
00653 }
00654
00655
00656
00657
00658
00659
00660
00661
00662
00663
00664
00665
00666
00667
00668
00669
00670
00671
00672
00673 for (i=0; i<nr_wtable; i++) {
00674
00675 Ix = 0.0;
00676 Lx = 0.0;
00677
00678 Ix = cpl_table_get_double(ref_wtable, cn_flux, i, &row_nulls);
00679 Lx = cpl_table_get_double(ref_wtable, cn_wlenpix, i, &row_nulls);
00680
00681 for (j=0; j<nr_wtable; j++) {
00682
00683 if (i!=j) {
00684
00685 Iy = 0.0;
00686 Ly = 0.0;
00687
00688 Iy =
00689 cpl_table_get_double(
00690 ref_wtable,
00691 cn_flux,
00692 j,
00693 &row_nulls
00694 );
00695
00696 Ly =
00697 cpl_table_get_double(
00698 ref_wtable,
00699 cn_wlenpix,
00700 j,
00701 &row_nulls
00702 );
00703
00704 c1 = FALSE;
00705 c2 = FALSE;
00706
00707 c1 = ( fabs(Lx-Ly) < line_width * sep_minimum );
00708 c2 = ( Ix < ( flux_ratio * Iy ) );
00709
00710 if ( c1 && c2 ) {
00711 ce_code = cpl_table_set_int(ref_wtable, cn_select, i, j);
00712 }
00713 }
00714 }
00715 }
00716
00717
00718
00719
00720
00721 row_curr = cpl_table_get_nrow(ref_wtable) - 1;
00722 num_rows_remove = 0;
00723
00724 while (row_curr >= 0) {
00725
00726 tmp_select = 0;
00727 tmp_blend = 0;
00728
00729 tmp_select =
00730 cpl_table_get_int(ref_wtable, cn_select, row_curr, &row_nulls);
00731
00732 tmp_blend =
00733 cpl_table_get_int(ref_wtable, cn_blend, row_curr, &row_nulls);
00734
00735 if ((tmp_select>0)||(tmp_blend>0)) {
00736 num_rows_remove++;
00737 row_curr--;
00738 } else {
00739 row_curr--;
00740 }
00741
00742 }
00743
00744 if (num_rows_remove==num_rows_orig) {
00745 cpl_msg_error(fctid, "No lines left after line elimination!");
00746 return 2;
00747 }
00748
00749
00750
00751
00752
00753 row_curr = cpl_table_get_nrow(ref_wtable) - 1;
00754
00755 while (row_curr >= 0) {
00756
00757 tmp_select = 0;
00758 tmp_blend = 0;
00759
00760 tmp_select =
00761 cpl_table_get_int(ref_wtable, cn_select, row_curr, &row_nulls);
00762
00763 tmp_blend =
00764 cpl_table_get_int(ref_wtable, cn_blend, row_curr, &row_nulls);
00765
00766 if ((tmp_select>0)||(tmp_blend>0)) {
00767 ce_code = cpl_table_erase_segment(ref_wtable, row_curr, 1);
00768 row_curr--;
00769 } else {
00770 row_curr--;
00771 }
00772 }
00773
00774
00775
00776
00777
00778 nr_wtable = cpl_table_get_nrow(ref_wtable);
00779
00780 cpl_table_fill_column_int(
00781 ref_wtable,
00782 cn_select,
00783 0,
00784 nr_wtable,
00785 0
00786 );
00787
00788 cpl_msg_info(
00789 fctid,
00790 "Removed %d lines, Wavelength Catalog now contains %d lines",
00791 num_rows_orig - nr_wtable,
00792 nr_wtable
00793 );
00794
00795 return 0;
00796
00797 }
00798
00816 static cxint
00817 giraffe_goodlines_count(GiImageStack *lines)
00818 {
00819
00820 const cxchar *fctid = "giraffe_goodlines_count";
00821
00822 cpl_image *status = NULL;
00823 cxdouble *pd_status = NULL;
00824 cxlong goodlines = 0L,
00825 li = 0L,
00826 nr_pixels = 0L;
00827
00828 if (lines==NULL) { return -1; }
00829
00830 status = giraffe_imagestack_get(lines, LF_I_STATUS);
00831
00832 if (status==NULL) { return -1; }
00833
00834 pd_status = cpl_image_get_data_double(status);
00835 nr_pixels = cpl_image_get_nx(status) * cpl_image_get_ny(status);
00836
00837 for (li=0; li<nr_pixels; li++)
00838 if (pd_status[li] > 0.0)
00839 goodlines++;
00840
00841 cpl_msg_debug(
00842 fctid,
00843 "Valid # of Spectrum/Line Combinations now : %d",
00844 goodlines
00845 );
00846
00847 return goodlines;
00848
00849 }
00850
00867 static cxint
00868 giraffe_update_wavelengths(
00869 GiImageStack *lines_data,
00870 GiGrating *grating_data,
00871 GiTable *wavelengths
00872 ) {
00873
00874
00875
00876
00877
00878 const cxchar *fctid = "giraffe_update_wavelengths";
00879
00880 cxchar *cn_wlen = WAVELENGTH_TABLE_WLEN;
00881
00882 cxint dimx,
00883 dimy,
00884 i,
00885 j;
00886
00887 cxdouble *pd_img = NULL;
00888
00889 cpl_table *ref_wtable = NULL;
00890 cpl_image *ref_wlen = NULL;
00891
00892
00893
00894
00895
00896 if (lines_data ==NULL) { return 1; }
00897 if (grating_data==NULL) { return 1; }
00898 if (wavelengths ==NULL) { return 1; }
00899
00900
00901
00902
00903
00904 ref_wtable = giraffe_table_get(wavelengths);
00905 ref_wlen = giraffe_imagestack_get(lines_data, LF_I_WLEN);
00906 pd_img = cpl_image_get_data_double(ref_wlen);
00907 dimx = cpl_image_get_nx(ref_wlen);
00908 dimy = cpl_image_get_ny(ref_wlen);
00909
00910 if (cpl_table_get_nrow(ref_wtable)!=dimx) {
00911 cpl_msg_debug(
00912 fctid,
00913 "Oops mismatch in wavelength array size [%d vs. %d]",
00914 cpl_table_get_nrow(ref_wtable),
00915 dimx
00916 );
00917 return 2;
00918 }
00919
00920 for (i=0; i<dimy; i++) {
00921 for (j=0; j<dimx; j++) {
00922 pd_img[i*dimx+j] = 1000000.0 *
00923 cpl_table_get_double(ref_wtable, cn_wlen, j, NULL);
00924 }
00925 }
00926
00927 return 0;
00928
00929 }
00930
00931
00952 static GiImage *
00953 giraffe_compute_pixel_abcissa_wrapper(GiImage *ext_sp_frame,
00954 GiTable *wavelength_table,
00955 GiSlitGeometry *fiber_slit_position,
00956 cpl_matrix *m_opt_mod_params,
00957 lmrq_model_id opt_mod_id)
00958 {
00959
00960
00961
00962
00963
00964 const cxchar *fctid = "giraffe_compute_pixel_abcissa_wrapper";
00965
00966 GiImage *result = NULL;
00967
00968 cpl_image *tmp = NULL;
00969
00970 lmrq_model opticalModel = lmrq_models[LMRQ_XOPTMOD2];
00971
00972 cxint nr_m_opt_mod_params = 0,
00973 status = 0,
00974 nr_wlen = 0,
00975 i = 0,
00976 row_nulls;
00977
00978 cxdouble tmp_wlen = 0.0;
00979
00980 cpl_matrix *m_wavelengths = NULL;
00981
00982 cpl_table *ref_wtable = NULL;
00983
00984 cpl_plist *ref_presult = NULL;
00985
00986 cxchar *cn_wlen = WAVELENGTH_TABLE_WLEN;
00987
00988 cpl_image_stats *stats = NULL;
00989
00990
00991
00992
00993
00994 if (ext_sp_frame == NULL) { return NULL; }
00995 if (wavelength_table == NULL) { return NULL; }
00996 if (fiber_slit_position == NULL) { return NULL; }
00997 if (m_opt_mod_params == NULL) { return NULL; }
00998
00999 if (opt_mod_id == LMRQ_UNDEFINED) {
01000 cpl_msg_error(fctid, "Invalid Optical model, aborting...");
01001 return NULL;
01002 }
01003
01004 opticalModel = lmrq_models[opt_mod_id];
01005
01006 nr_m_opt_mod_params = cpl_matrix_get_nrow(m_opt_mod_params);
01007
01008 if (nr_m_opt_mod_params != opticalModel.nparams) {
01009 cpl_msg_error(
01010 fctid,
01011 "Invalid number of parameters, aborting..."
01012 );
01013 return NULL;
01014 }
01015
01016 ref_wtable = giraffe_table_get(wavelength_table);
01017 nr_wlen = cpl_table_get_nrow(ref_wtable);
01018
01019 m_wavelengths = cpl_matrix_new(nr_wlen,1);
01020
01021 for (i=0; i<nr_wlen; i++) {
01022 tmp_wlen = cpl_table_get(ref_wtable, cn_wlen, i, &row_nulls);
01023 cpl_matrix_set(m_wavelengths, i, 0, tmp_wlen);
01024 }
01025
01026
01027
01028
01029
01030 tmp = giraffe_compute_pixel_abcissa(m_wavelengths, fiber_slit_position,
01031 m_opt_mod_params, opticalModel);
01032
01033 if (tmp==NULL) {
01034 cpl_msg_error(
01035 fctid,
01036 "Unable to compute pixel abcissa, aborting..."
01037 );
01038 cpl_matrix_delete(m_wavelengths);
01039 return NULL;
01040 }
01041
01042 result = giraffe_image_new(CPL_TYPE_DOUBLE);
01043
01044 giraffe_image_set(result, tmp);
01045
01046 status = giraffe_image_set_properties(result,
01047 giraffe_image_get_properties(ext_sp_frame));
01048
01049 ref_presult = giraffe_image_get_properties(result);
01050
01051 stats = cpl_image_stat(tmp, CPL_STAT_MIN | CPL_STAT_MAX);
01052
01053 status =
01054 giraffe_plist_update_double(
01055 ref_presult,
01056 GIALIAS_DATAMIN,
01057 cpl_image_stats_get_min(stats)
01058 );
01059
01060 status =
01061 giraffe_plist_update_double(
01062 ref_presult,
01063 GIALIAS_DATAMAX,
01064 cpl_image_stats_get_max(stats)
01065 );
01066
01067 status =
01068 giraffe_plist_update_string(
01069 ref_presult,
01070 GIALIAS_WSOL_OMNAME,
01071 lmrq_models[opt_mod_id].name
01072 );
01073
01074 cpl_matrix_delete(m_wavelengths);
01075 cpl_image_delete(tmp);
01076 cx_free(stats);
01077
01078 return result;
01079
01080 }
01081
01116 cpl_image *
01117 giraffe_compute_pixel_abcissa(cpl_matrix *m_wavelengths,
01118 GiSlitGeometry *fiber_slit_position,
01119 cpl_matrix *m_opt_mod_params,
01120 lmrq_model lmrq_opt_mod_x)
01121 {
01122
01123
01124
01125
01126
01127 const cxchar *fctid = "giraffe_compute_pixel_abcissa";
01128
01129 register cxint n,
01130 line,
01131 nwlen,
01132 ns;
01133
01134 cxint nr_m_opt_mod_params = 0;
01135
01136 cxdouble xccd = 0.0,
01137 *pd_xref = NULL,
01138 *pd_m_inputs = NULL,
01139 *pd_m_yfibre = NULL,
01140 *pd_m_xfibre = NULL,
01141 *pd_m_wavelengths = NULL,
01142 *pd_m_opt_mod_params = NULL;
01143
01144 cpl_image *xref = NULL;
01145
01146 cpl_matrix *m_inputs = NULL;
01147
01148
01149
01150
01151
01152 if (m_wavelengths ==NULL) { return NULL; }
01153 if (fiber_slit_position ==NULL) { return NULL; }
01154 if (m_opt_mod_params ==NULL) { return NULL; }
01155
01156 nwlen = cpl_matrix_get_nrow(m_wavelengths);
01157 ns = cpl_matrix_get_nrow(fiber_slit_position->yf);
01158
01159
01160
01161
01162
01163 xref = cpl_image_new_double(ns, nwlen, NULL, NULL);
01164 pd_xref = cpl_image_get_data_double(xref);
01165
01166 m_inputs = cpl_matrix_new(lmrq_opt_mod_x.ninputs, 1);
01167 pd_m_inputs = cpl_matrix_get_data(m_inputs);
01168
01169 pd_m_yfibre = cpl_matrix_get_data(fiber_slit_position->yf);
01170 pd_m_xfibre = cpl_matrix_get_data(fiber_slit_position->xf);
01171 pd_m_wavelengths = cpl_matrix_get_data(m_wavelengths);
01172
01173 pd_m_opt_mod_params = cpl_matrix_get_data(m_opt_mod_params);
01174 nr_m_opt_mod_params = cpl_matrix_get_nrow(m_opt_mod_params);
01175
01176
01177
01178
01179
01180 for (n=0; n<ns; n++) {
01181
01182 pd_m_inputs[2] = pd_m_yfibre[n];
01183 pd_m_inputs[1] = pd_m_xfibre[n];
01184
01185 for (line=0; line<nwlen; line++) {
01186
01187 pd_m_inputs[0] = pd_m_wavelengths[line];
01188
01189 lmrq_opt_mod_x.cfunc(
01190 pd_m_inputs,
01191 pd_m_opt_mod_params,
01192 NULL,
01193 &xccd,
01194 NULL,
01195 nr_m_opt_mod_params
01196 );
01197
01198 pd_xref[line*ns+n] = xccd;
01199
01200 }
01201 }
01202
01203 cpl_matrix_delete(m_inputs);
01204
01205 cpl_msg_debug(
01206 fctid,
01207 "Processing completed: Returning image [x,y] = [%d,%d]",
01208 cpl_image_get_nx(xref),
01209 cpl_image_get_ny(xref)
01210 );
01211
01212 return xref;
01213
01214 }
01215
01216
01280 static cxint
01281 giraffe_fit_opt_mod(GiImageStack *lines, cpl_matrix *wavelengths,
01282 GiSlitGeometry *fiber_slit_position,
01283 cpl_matrix *opt_mod_params, cpl_matrix *opt_mod_flags,
01284 lmrq_model_id opt_mod_id, lmrq_params *fit_params,
01285 cpl_matrix *opt_mod_fit_res)
01286 {
01287
01288
01289
01290
01291
01292 const cxchar *fctid = "giraffe_fit_opt_mod";
01293
01294 lmrq_model lmrq_opt_mod = lmrq_models[LMRQ_XOPTMOD2];
01295
01296 cxint nlines,
01297 ns,
01298 nlineparams,
01299 index_center,
01300 index_center_sigma,
01301 ngoodlines,
01302 nc_m_alpha,
01303 nc_m_x,
01304 nr_opt_mod_params,
01305 i,
01306 n,
01307 line,
01308 niter,
01309 k,
01310 df,
01311 *ia_fit_flags = NULL;
01312
01313 cpl_matrix *m_x = NULL,
01314 *m_y = NULL,
01315 *m_sig = NULL,
01316 *m_alpha = NULL;
01317
01318 cxdouble *pd_m_x = NULL,
01319 *pd_m_y = NULL,
01320 *pd_m_sig = NULL,
01321 *pd_m_alpha = NULL,
01322 *pd_opt_mod_fit_res = NULL,
01323 *pd_m_xfibre = NULL,
01324 *pd_m_yfibre = NULL,
01325 *pd_wavelengths = NULL,
01326 *pd_opt_mod_params = NULL,
01327 **qa2imgs = NULL,
01328 xf,
01329 yf,
01330 chisq = 0.0;
01331
01332 cxulong nn, ll, ndata;
01333
01334
01335
01336
01337
01338 if (lines ==NULL) { return 1; }
01339 if (wavelengths ==NULL) { return 1; }
01340 if (fiber_slit_position==NULL) { return 1; }
01341 if (opt_mod_params ==NULL) { return 1; }
01342 if (opt_mod_flags ==NULL) { return 1; }
01343 if (fit_params ==NULL) { return 1; }
01344 if (opt_mod_fit_res ==NULL) { return 1; }
01345
01346 nlines = cpl_matrix_get_nrow(wavelengths);
01347 ns = cpl_image_get_ny(giraffe_imagestack_get(lines, LF_I_STATUS));
01348 nlineparams = giraffe_imagestack_size(lines);
01349 ndata = nlines * ns;
01350
01351 nr_opt_mod_params = cpl_matrix_get_nrow(opt_mod_params);
01352
01353 qa2imgs = cx_calloc(nlineparams, sizeof(cxdouble*));
01354
01355 for (i=0;i<nlineparams;i++) {
01356 cxdouble *tmpdbl;
01357 tmpdbl = cpl_image_get_data_double(giraffe_imagestack_get(lines, i));
01358 qa2imgs[i] = tmpdbl;
01359 }
01360
01361 lmrq_opt_mod = lmrq_models[opt_mod_id];
01362
01363
01364
01365
01366
01367 cpl_msg_info(
01368 fctid,
01369 "Performing Optical Model fit of spectra/reference lines using "
01370 "'%s' model, %d spectra and %d lines",
01371 lmrq_models[opt_mod_id].name,
01372 ns,
01373 nlines
01374 );
01375
01376 cpl_msg_debug(
01377 fctid,
01378 "Using : maxiter=%4i, maxtests=%4i, maxchisq=%12.6f",
01379 fit_params->imax,
01380 fit_params->tmax,
01381 fit_params->dchsq
01382 );
01383
01384 if (nlineparams == LF_G_NPARAMS) {
01385
01386 index_center = LF_O_PARAMS + LF_G_CENTER;
01387 index_center_sigma = LF_O_PARAMS + LF_G_SCENTER;
01388 } else if (nlineparams == LF_E_NPARAMS) {
01389
01390 index_center = LF_O_PARAMS + LF_E_CENTER;
01391 index_center_sigma = LF_O_PARAMS + LF_E_SCENTER;
01392 } else {
01393
01394 cpl_msg_error(fctid, "Unknown line model, aborting...");
01395 cx_free(qa2imgs);
01396 return 2;
01397 }
01398
01399
01400
01401
01402
01403 m_x = cpl_matrix_new(ndata, lmrq_opt_mod.ninputs);
01404 m_y = cpl_matrix_new(ndata, 1);
01405 m_sig = cpl_matrix_new(ndata, 1);
01406 m_alpha = cpl_matrix_new(lmrq_opt_mod.nparams, lmrq_opt_mod.nparams);
01407
01408 pd_m_x = cpl_matrix_get_data(m_x);
01409 pd_m_y = cpl_matrix_get_data(m_y);
01410 pd_m_sig = cpl_matrix_get_data(m_sig);
01411 pd_m_alpha = cpl_matrix_get_data(m_alpha);
01412
01413 nc_m_x = cpl_matrix_get_ncol(m_x);
01414 nc_m_alpha = cpl_matrix_get_ncol(m_alpha);
01415
01416 pd_wavelengths = cpl_matrix_get_data(wavelengths);
01417 pd_opt_mod_params = cpl_matrix_get_data(opt_mod_params);
01418
01419
01420 cpl_matrix_resize(opt_mod_fit_res, lmrq_opt_mod.nparams * 2 + 3, 1);
01421 pd_opt_mod_fit_res = cpl_matrix_get_data(opt_mod_fit_res);
01422
01423
01424 pd_m_xfibre = cpl_matrix_get_data(fiber_slit_position->xf);
01425 pd_m_yfibre = cpl_matrix_get_data(fiber_slit_position->yf);
01426
01427 ngoodlines = 0;
01428
01429 for (n = 0; n < ns; n++) {
01430
01431 xf = pd_m_xfibre[n];
01432 yf = pd_m_yfibre[n];
01433 nn = n * nlines;
01434
01435 for (line = 0; line < nlines; line++) {
01436
01437 ll = nn + line;
01438
01439 if (qa2imgs[LF_I_STATUS][ll] <= 0.0) continue;
01440 if (qa2imgs[index_center_sigma][ll] <= 0.0) continue;
01441
01442 pd_m_x[ngoodlines*nc_m_x] = pd_wavelengths[line];
01443 pd_m_x[ngoodlines*nc_m_x+1] = xf;
01444 pd_m_x[ngoodlines*nc_m_x+2] = yf;
01445
01446 pd_m_y[ngoodlines] = qa2imgs[index_center][ll];
01447 pd_m_sig[ngoodlines] = qa2imgs[index_center_sigma][ll];
01448 ngoodlines++;
01449 }
01450 }
01451
01452 cpl_msg_debug(
01453 fctid,
01454 "Optical Model Fit will be based on %d lines out of a possible %d",
01455 ngoodlines,
01456 ndata
01457 );
01458
01459
01460 cpl_matrix_resize(m_x, ngoodlines, lmrq_opt_mod.ninputs);
01461 cpl_matrix_resize(m_y, ngoodlines, 1);
01462 cpl_matrix_resize(m_sig, ngoodlines, 1);
01463
01464 pd_m_x = cpl_matrix_get_data(m_x);
01465 pd_m_y = cpl_matrix_get_data(m_y);
01466 pd_m_sig = cpl_matrix_get_data(m_sig);
01467
01468
01469 ia_fit_flags =
01470 (cxint*) cx_calloc(cpl_matrix_get_nrow(opt_mod_flags), sizeof(cxint));
01471
01472 for (i=0; i<cpl_matrix_get_nrow(opt_mod_flags); i++) {
01473 if (cpl_matrix_get(opt_mod_flags, i, 0)>DOUBLE2BOOLEAN)
01474 ia_fit_flags[i] = 1;
01475 else
01476 ia_fit_flags[i] = 0;
01477 }
01478
01479
01480 niter =
01481 mrqnlfit(
01482 m_x,
01483 m_y,
01484 m_sig,
01485 ngoodlines,
01486 opt_mod_params,
01487 NULL,
01488 ia_fit_flags,
01489 nr_opt_mod_params,
01490 m_alpha,
01491 &chisq,
01492 *fit_params,
01493 lmrq_opt_mod.cfunc
01494 );
01495
01496 if (niter<0) {
01497 cpl_msg_error(
01498 fctid,
01499 "Error during fit of physical optical model, aborting..."
01500 );
01501
01502 cx_free(ia_fit_flags);
01503 cpl_matrix_delete(m_alpha);
01504 cpl_matrix_delete(m_sig);
01505 cpl_matrix_delete(m_y);
01506 cpl_matrix_delete(m_x);
01507 cx_free(qa2imgs);
01508 return 3;
01509 }
01510
01511
01512
01513
01514
01515
01516
01517
01518 k = 0;
01519 for (i=0; i<nr_opt_mod_params; i++) {
01520 pd_opt_mod_fit_res[k+i] = pd_opt_mod_params[i];
01521 }
01522
01523 k += nr_opt_mod_params;
01524 for (i=0; i<nr_opt_mod_params; i++) {
01525 pd_opt_mod_fit_res[k+i] = sqrt(fabs(pd_m_alpha[i * nc_m_alpha + i]));
01526 if (isnan(pd_opt_mod_fit_res[k+i]))
01527 pd_opt_mod_fit_res[k+i] = 0.0;
01528 }
01529
01530 k += nr_opt_mod_params;
01531 pd_opt_mod_fit_res[k++] = (cxdouble) niter;
01532 pd_opt_mod_fit_res[k++] = chisq;
01533 pd_opt_mod_fit_res[k] = r_squared(chisq, m_y, ngoodlines);
01534
01535
01536 df = ndata;
01537 for (i=0; i<nr_opt_mod_params; i++)
01538 df -= ia_fit_flags[i];
01539
01540 cpl_msg_info(
01541 fctid,
01542 "Fit completed, fit statistics: iterations=%d, chisq=%12.6g, df=%d, sd=%12.6g, "
01543 "R-squared=%12.6g",
01544 niter,
01545 chisq,
01546 df,
01547 sqrt(chisq/df),
01548 r_squared(chisq, m_y, ngoodlines)
01549 );
01550
01551 cpl_msg_debug(
01552 fctid,
01553 "Returning matrix: r,c = [%d,%d]",
01554 cpl_matrix_get_nrow(opt_mod_fit_res),
01555 cpl_matrix_get_ncol(opt_mod_fit_res)
01556 );
01557
01558 cx_free(ia_fit_flags);
01559 cpl_matrix_delete(m_alpha);
01560 cpl_matrix_delete(m_sig);
01561 cpl_matrix_delete(m_y);
01562 cpl_matrix_delete(m_x);
01563 cx_free(qa2imgs);
01564
01565 return 0;
01566
01567 }
01568
01590 static cxint
01591 giraffe_fit_opt_mod_wrapper(GiImageStack *lines, GiTable *wavelength_table,
01592 GiSlitGeometry *fiber_slit_position,
01593 cpl_matrix *opt_mod_params,
01594 cpl_matrix *opt_mod_flags,
01595 lmrq_params *fit_params, lmrq_model_id opt_mod_id,
01596 cpl_matrix *opt_mod_fit_res)
01597 {
01598
01599
01600
01601
01602
01603 const cxchar *fctid = "giraffe_fit_opt_mod_wrapper";
01604 const cxchar *cn_wlen = WAVELENGTH_TABLE_WLEN;
01605
01606 cpl_table *ref_wtable = NULL;
01607 cpl_matrix *lines_wlen = NULL;
01608
01609 cxint status,
01610 i;
01611
01612 cxdouble tmp_wlen;
01613
01614 lmrq_model lmrq_opt_mod = lmrq_models[LMRQ_XOPTMOD2];
01615
01616
01617
01618
01619
01620 if (lines ==NULL) { return 1; }
01621 if (wavelength_table ==NULL) { return 1; }
01622 if (fiber_slit_position ==NULL) { return 1; }
01623 if (opt_mod_params ==NULL) { return 1; }
01624 if (opt_mod_flags ==NULL) { return 1; }
01625 if (fit_params ==NULL) { return 1; }
01626 if (opt_mod_fit_res ==NULL) { return 1; }
01627
01628 if (opt_mod_id==LMRQ_UNDEFINED) {
01629 cpl_msg_error(
01630 fctid,
01631 "Invalid Optical Model, aborting..."
01632 );
01633 return 2;
01634 }
01635
01636 lmrq_opt_mod = lmrq_models[opt_mod_id];
01637
01638 if (cpl_matrix_get_nrow(opt_mod_params)!=lmrq_opt_mod.nparams) {
01639 cpl_msg_error(
01640 fctid,
01641 "Invalid list of optical model parameters %d [%d expected], "
01642 "aborting...",
01643 cpl_matrix_get_nrow(opt_mod_params),
01644 lmrq_opt_mod.nparams
01645 );
01646 return 3;
01647 }
01648
01649 if (cpl_matrix_get_nrow(opt_mod_flags)!=lmrq_opt_mod.nparams) {
01650 cpl_msg_error(
01651 fctid,
01652 "Invalid list of optical model flags %d [%d expected], "
01653 "aborting...",
01654 cpl_matrix_get_nrow(opt_mod_flags),
01655 lmrq_opt_mod.nparams
01656 );
01657 return 3;
01658 }
01659
01660 ref_wtable = giraffe_table_get(wavelength_table);
01661
01662 lines_wlen = cpl_matrix_new(cpl_table_get_nrow(ref_wtable),1);
01663
01664 for (i=0; i<cpl_table_get_nrow(ref_wtable); i++) {
01665 tmp_wlen = cpl_table_get_double(ref_wtable, cn_wlen, i, NULL);
01666 cpl_matrix_set(lines_wlen, i, 0, tmp_wlen);
01667 }
01668
01669
01670
01671
01672
01673 status = giraffe_fit_opt_mod(lines, lines_wlen, fiber_slit_position,
01674 opt_mod_params, opt_mod_flags, opt_mod_id,
01675 fit_params, opt_mod_fit_res);
01676
01677 if (status != 0) {
01678 cpl_matrix_delete(lines_wlen);
01679 return 6;
01680 }
01681
01682
01683
01684
01685
01686
01687
01688
01689
01690
01691 switch ((cxint)cpl_matrix_get(opt_mod_fit_res, 2 * lmrq_opt_mod.nparams,0)) {
01692 case -1:
01693 cpl_msg_error(fctid, "singular matrix-1 in Gauss-Jordan elimination");
01694 cpl_matrix_delete(lines_wlen);
01695 return 4;
01696 case -2:
01697 cpl_msg_error(fctid, "singular matrix-2 in Gauss-Jordan elimination");
01698 cpl_matrix_delete(lines_wlen);
01699 return 4;
01700 case -3:
01701 cpl_msg_error(fctid, "not enough memory for fit");
01702 cpl_matrix_delete(lines_wlen);
01703 return 4;
01704 case -4:
01705 cpl_msg_error(fctid, "unknown error in fit");
01706 cpl_matrix_delete(lines_wlen);
01707 return 4;
01708 }
01709
01710 if (cpl_matrix_get_nrow(opt_mod_fit_res)<3) {
01711 cpl_msg_error(fctid, "Error during Optical Model Fit, aborting...");
01712 cpl_matrix_delete(lines_wlen);
01713 return 5;
01714 }
01715
01716 cpl_matrix_delete(lines_wlen);
01717
01718 return 0;
01719
01720 }
01721
01722
01797 static GiImageStack*
01798 giraffe_fit_lines_lmrq(
01799 cpl_image *ext_sp,
01800 cpl_image *ext_sp_err,
01801 cpl_image *loc_y,
01802 cpl_image *ref_lines,
01803 cpl_matrix *line_params,
01804 lmrq_model lmrq_line_model,
01805 lmrq_params fit_params
01806 ) {
01807
01808
01809
01810
01811
01812 const cxchar *fctid = "giraffe_fit_lines_lmrq";
01813
01814
01815
01816 cxdouble *pd_ext_sp = NULL,
01817 *pd_ext_sp_err = NULL,
01818 *pd_loc_y = NULL,
01819 *pd_ref_lines = NULL,
01820 *pd_line_params = NULL;
01821
01822 cxint nc_loc_y = 0,
01823 nc_ext_sp_err = 0,
01824 spec_size = 0,
01825 spec_count = 0,
01826 numreflines = 0,
01827 nummodelparams = 0,
01828 numlineparams = 0;
01829
01830
01831
01832 cpl_matrix *mX = NULL,
01833 *mY = NULL,
01834 *mYs = NULL,
01835 *mSig = NULL,
01836 *mFitParams = NULL,
01837 *mAlpha = NULL;
01838
01839 cxdouble *pd_mX = NULL,
01840 *pd_mY = NULL,
01841 *pd_mYs = NULL,
01842 *pd_mSig = NULL,
01843 *pd_mFitParams = NULL,
01844 *pd_mAlpha = NULL;
01845
01846 cxint nc_mAlpha = 0;
01847
01848
01849 cxdouble log2 = log(2.0);
01850 cxdouble fwhmRatio = 2.0 * sqrt(2.0 * log(2.0));
01851 cxdouble fwhmRatio2 = 8.0 * log(2.0);
01852
01853
01854 cxint *iFitflags = NULL;
01855 cxdouble chisq = 0.0;
01856
01857
01858
01859 GiImageStack *lines = NULL;
01860 cxdouble **qa2imgs = NULL;
01861
01862 register cxint i, j, niter, line;
01863 register cxdouble xccd, yccd, gwidth = 0.0, gwidth2;
01864
01865 register cxint spec_curr = 0,
01866 numfitpoints = 0,
01867 numrejected = 0,
01868 xline = 0,
01869 lineOK = 0,
01870 lineKO = 0,
01871 xmin = 0,
01872 xmax = 0,
01873 curr_pixel = 0;
01874
01875
01876
01877
01878
01879 if (ext_sp ==NULL) { return NULL; }
01880 if (ext_sp_err ==NULL) { return NULL; }
01881 if (loc_y ==NULL) { return NULL; }
01882 if (ref_lines ==NULL) { return NULL; }
01883 if (line_params==NULL) { return NULL; }
01884
01885 pd_ext_sp = cpl_image_get_data_double(ext_sp);
01886 pd_ext_sp_err = cpl_image_get_data_double(ext_sp_err);
01887 pd_loc_y = cpl_image_get_data_double(loc_y);
01888 pd_ref_lines = cpl_image_get_data_double(ref_lines);
01889 pd_line_params = cpl_matrix_get_data(line_params);
01890
01891 nc_loc_y = cpl_image_get_nx(loc_y);
01892 nc_ext_sp_err = cpl_image_get_nx(ext_sp_err);
01893
01894 spec_size = cpl_image_get_ny(ext_sp);
01895 spec_count = cpl_image_get_nx(ext_sp);
01896
01897 numreflines = cpl_image_get_ny(ref_lines);
01898
01899 nummodelparams = lmrq_line_model.nparams;
01900 numlineparams = 2 * nummodelparams + LF_O_PARAMS;
01901
01902 numfitpoints = (cxint) cpl_matrix_get_data(line_params)[LP_WIDTH];
01903
01904
01905
01906
01907
01908 cpl_msg_info(
01909 fctid,
01910 "Performing detection fit of spectra/reference lines using "
01911 "'%s' model, %d spectra and %d lines",
01912 lmrq_line_model.name,
01913 spec_count,
01914 numreflines
01915 );
01916
01917 mX = cpl_matrix_new(numfitpoints, 1);
01918 mY = cpl_matrix_new(numfitpoints, 1);
01919 mYs = cpl_matrix_new(numfitpoints, 1);
01920 mSig = cpl_matrix_new(numfitpoints, 1);
01921 mFitParams = cpl_matrix_new(nummodelparams, 1);
01922 mAlpha = cpl_matrix_new(nummodelparams, nummodelparams);
01923
01924
01925
01926
01927
01928 lines = giraffe_imagestack_new(numlineparams);
01929
01930 for (i=0; i<numlineparams; i++) {
01931 cpl_image *tmpimg = NULL;
01932 tmpimg = cpl_image_new_double(numreflines, spec_count, NULL, NULL);
01933 giraffe_imagestack_set(lines, i, tmpimg);
01934 }
01935
01936
01937
01938
01939
01940 qa2imgs = cx_calloc(numlineparams, sizeof(cxdouble*));
01941
01942 for (i=0;i<numlineparams;i++) {
01943 cxdouble *tmpdbl;
01944 tmpdbl = cpl_image_get_data_double(giraffe_imagestack_get(lines, i));
01945 qa2imgs[i] = tmpdbl;
01946 }
01947
01948
01949
01950
01951
01952 iFitflags = (cxint *) cx_calloc(nummodelparams, sizeof(cxint));
01953 for (i=0; i<nummodelparams; i++) {
01954 iFitflags[i] = 1;
01955 }
01956
01957
01958
01959
01960
01961 curr_pixel = 0;
01962
01963 for (spec_curr = 0; spec_curr < spec_count; spec_curr++) {
01964
01965 for (line = 0; line < numreflines; line++) {
01966
01967 cpl_matrix_resize(mX, (cxint)pd_line_params[LP_WIDTH], 1);
01968 cpl_matrix_resize(mY, (cxint)pd_line_params[LP_WIDTH], 1);
01969 cpl_matrix_resize(mYs, (cxint)pd_line_params[LP_WIDTH], 1);
01970 cpl_matrix_resize(mSig, (cxint)pd_line_params[LP_WIDTH], 1);
01971
01972 giraffe_matrix_clear(mX);
01973 giraffe_matrix_clear(mY);
01974 giraffe_matrix_clear(mYs);
01975 giraffe_matrix_clear(mSig);
01976
01977 cpl_matrix_resize(mFitParams, nummodelparams, 1);
01978 cpl_matrix_fill(mFitParams, 0.0);
01979
01980 cpl_matrix_resize(mAlpha, nummodelparams, nummodelparams);
01981 cpl_matrix_fill(mAlpha, 0.0);
01982
01983 pd_mFitParams = cpl_matrix_get_data(mFitParams);
01984 pd_mAlpha = cpl_matrix_get_data(mAlpha);
01985 nc_mAlpha = cpl_matrix_get_ncol(mAlpha);
01986
01987 lineOK = 1;
01988 lineKO = 0;
01989 niter = 0;
01990 numfitpoints = 0;
01991 chisq = 0.0;
01992
01993
01994
01995
01996
01997 xccd = pd_ref_lines[line * spec_count + spec_curr];
01998
01999 xmin = xccd;
02000 xmax = xccd;
02001 yccd = 0.0;
02002
02003 if ((0 < xccd) && (xccd < spec_size)) {
02004
02005 cxint d1, d2;
02006
02007
02008
02009
02010 xmin = (cxint) (xccd - (pd_line_params[LP_WIDTH]/2.0) + 0.5);
02011 xmax = (cxint) (xccd + (pd_line_params[LP_WIDTH]/2.0) + 0.5);
02012
02013
02014 xmin = MAX(MIN(xmin, spec_size - 1), 0);
02015 xmax = MAX(MIN(xmax, spec_size - 1), 0);
02016
02017 numfitpoints = xmax - xmin;
02018
02019 cpl_matrix_resize(mX, numfitpoints, 1);
02020 cpl_matrix_resize(mY, numfitpoints, 1);
02021 cpl_matrix_resize(mYs, numfitpoints, 1);
02022 cpl_matrix_resize(mSig, numfitpoints, 1);
02023
02024
02025
02026
02027
02028
02029
02030 d1 = ((cxint) floor(xccd) * nc_loc_y ) + spec_curr;
02031 d2 = ((cxint) ceil(xccd) * nc_loc_y ) + spec_curr;
02032
02033 yccd = pd_loc_y[d1];
02034 yccd = yccd + ((pd_loc_y[d2]-yccd) * (xccd-floor(xccd)));
02035
02036 }
02037
02038 pd_mX = cpl_matrix_get_data(mX);
02039 pd_mY = cpl_matrix_get_data(mY);
02040 pd_mYs = cpl_matrix_get_data(mYs);
02041 pd_mSig = cpl_matrix_get_data(mSig);
02042
02043
02044
02045
02046
02047 for (i=0; i<numfitpoints; i++) {
02048
02049 j = xmin + i;
02050
02051
02052 pd_mX[i] = (cxdouble) j;
02053
02054
02055 j *= spec_count;
02056 j += spec_curr;
02057
02058 pd_mY[i] = pd_ext_sp[j];
02059
02060
02061 pd_mYs[i] = pd_ext_sp[j];
02062
02063
02064 pd_mSig[i] = pd_ext_sp_err[j];
02065
02066 }
02067
02068
02069
02070
02071
02072 if (numfitpoints<=0) {
02073
02074 lineKO |= LF_R_XCCD;
02075
02076 } else if (lmrq_line_model.id == LMRQ_GAUSSUM) {
02077
02078
02079
02080
02081
02082
02083
02084 pd_mFitParams[LMP_WID1] =
02085 pd_line_params[LP_GRWID] / fwhmRatio;
02086
02087
02088 giraffe_matrix_sort(mYs);
02089 pd_mFitParams[LMP_BACK] = (pd_mYs[0] + pd_mYs[1]) / 2.0;
02090
02091
02092 pd_mFitParams[LMP_AMPL] = pd_mYs[numfitpoints - 1];
02093
02094 } else if ( (lmrq_line_model.id == LMRQ_PSFEXP) ||
02095 (lmrq_line_model.id == LMRQ_PSFEXP2) )
02096 {
02097
02098
02099 if (pd_line_params[LP_PSFEXP] >= 0.0) {
02100
02101 pd_mFitParams[LMP_WID2] = pd_line_params[LP_PSFEXP];
02102 iFitflags[LMP_WID2] = 0;
02103 } else {
02104
02105 pd_mFitParams[LMP_WID2] = -(pd_line_params[LP_PSFEXP]);
02106 iFitflags[LMP_WID2] = 1;
02107 }
02108
02109 if (lmrq_line_model.id == LMRQ_PSFEXP2) {
02110
02111 pd_mFitParams[LMP_WID1] =
02112 pd_line_params[LP_GRWID] /
02113 (2 * pow(log2, 1.0/pd_mFitParams[LMP_WID2]));
02114
02115 } else {
02116
02117 pd_mFitParams[LMP_WID1] =
02118 pow(pd_line_params[LP_GRWID] / 2.0,
02119 pd_mFitParams[LMP_WID2] ) / log2;
02120
02121 }
02122
02123
02124 giraffe_matrix_sort(mYs);
02125
02126 pd_mFitParams[LMP_BACK] = (pd_mYs[0] + pd_mYs[1]) / 2.0;
02127
02128
02129 pd_mFitParams[LMP_AMPL] = pd_mYs[numfitpoints - 1];
02130
02131 }
02132
02133
02134
02135
02136
02137 xline = xmin;
02138 for (i = 0; i<numfitpoints; i++) {
02139 if (pd_mY[i] >= pd_mFitParams[LMP_AMPL]) {
02140 xline = xmin + i;
02141 pd_mFitParams[LMP_CENT] = xline;
02142 }
02143 }
02144
02145
02146
02147
02148
02149
02150
02151
02152
02153
02154
02155
02156 if (((pd_ext_sp_err[(cxint)pd_mFitParams[LMP_CENT]*nc_ext_sp_err+spec_curr] *
02157 pd_line_params[LP_THRES]) >= pd_mFitParams[LMP_AMPL]) ||
02158 (pd_mFitParams[LMP_AMPL] > pd_line_params[LP_SATLV]) )
02159 {
02160
02161
02162 if (lineKO == 0)
02163 lineKO |= LF_R_AMPLI;
02164
02165 } else if (lineKO == 0) {
02166
02167
02168 pd_mFitParams[LMP_AMPL] -= pd_mFitParams[LMP_BACK];
02169
02170
02171
02172
02173
02174
02175 niter =
02176 mrqnlfit(
02177 mX,
02178 mY,
02179 mSig,
02180 numfitpoints,
02181 mFitParams,
02182 NULL,
02183 iFitflags,
02184 nummodelparams,
02185 mAlpha,
02186 &chisq,
02187 fit_params,
02188 lmrq_line_model.cfunc
02189 );
02190
02191 if (lmrq_line_model.id == LMRQ_PSFEXP) {
02192
02193
02194 gwidth =
02195 pow( pd_mFitParams[LMP_WID1] * log2,
02196 1.0 / pd_mFitParams[LMP_WID2]
02197 );
02198
02199 pd_mFitParams[LMP_WID1] = gwidth;
02200
02201 } else if (lmrq_line_model.id == LMRQ_PSFEXP2) {
02202
02203
02204 gwidth =
02205 pow( log2,
02206 1.0 / pd_mFitParams[LMP_WID2]
02207 ) * pd_mFitParams[LMP_WID1];
02208
02209 pd_mFitParams[LMP_WID1] = gwidth;
02210
02211 } else if (lmrq_line_model.id == LMRQ_GAUSSUM) {
02212
02213
02214 pd_mFitParams[LMP_WID1] *= fwhmRatio;
02215 gwidth = pd_mFitParams[LMP_WID1];
02216 pd_mAlpha[LMP_WID1 * nc_mAlpha + LMP_WID1] *= fwhmRatio2;
02217
02218 }
02219
02220
02221
02222
02223
02224 gwidth2 = gwidth / 2.0;
02225 if (niter >= fit_params.imax) {
02226
02227 lineKO |= LF_R_NITER;
02228 }
02229 if ( (xmin > pd_mFitParams[LMP_CENT]) ||
02230 (pd_mFitParams[LMP_CENT] > xmax) )
02231 {
02232
02233 lineKO |= LF_R_CENTR;
02234 }
02235 if (gwidth > (xmax - xmin)) {
02236
02237 lineKO |= LF_R_WIDTH;
02238 }
02239 if ((pd_mFitParams[LMP_CENT] - gwidth2) < xmin) {
02240
02241 lineKO |= LF_R_LEFT;
02242 }
02243 if ((pd_mFitParams[LMP_CENT] + gwidth2) > xmax) {
02244
02245 lineKO |= LF_R_RIGHT;
02246 }
02247 if (fabs(pd_mFitParams[LMP_CENT] - xline) >=
02248 pd_line_params[LP_OFFST] )
02249 {
02250
02251 lineKO |= LF_R_OFFST;
02252 }
02253 if (gwidth < (pd_line_params[LP_GRWID] *
02254 pd_line_params[LP_WFACT])
02255 ) {
02256
02257 lineKO |= LF_R_RESOL;
02258 }
02259 if (gwidth > (pd_line_params[LP_GRWID] /
02260 pd_line_params[LP_WFACT])
02261 ) {
02262
02263 lineKO |= LF_R_RESOL;
02264 }
02265 if (niter <= 0) {
02266
02267 lineKO |= LF_R_ERROR;
02268 }
02269
02270 }
02271
02272 if (lineKO != 0) {
02273 lineOK = -lineKO;
02274 numrejected++;
02275 }
02276
02277
02278
02279
02280
02281
02282
02283
02284
02285
02286
02287 qa2imgs[LF_I_STATUS][curr_pixel] =
02288 (cxdouble) lineOK;
02289 qa2imgs[LF_I_NITER][curr_pixel] =
02290 (cxdouble) niter;
02291 qa2imgs[LF_I_CHISQ][curr_pixel] =
02292 chisq;
02293 qa2imgs[LF_I_RSQ][curr_pixel] =
02294 r_squared(chisq, mY, numfitpoints);
02295 qa2imgs[LF_I_XCCD][curr_pixel] =
02296 xccd;
02297 qa2imgs[LF_I_YCCD][curr_pixel] =
02298 yccd;
02299
02300
02301 for (i = 0; i < nummodelparams; i++) {
02302 qa2imgs[i+LF_O_PARAMS][curr_pixel] = pd_mFitParams[i];
02303 }
02304
02305
02306 for (i = 0; i < nummodelparams; i++) {
02307 qa2imgs[i+nummodelparams+LF_O_PARAMS][curr_pixel] =
02308 sqrt(fabs(pd_mAlpha[i * nc_mAlpha + i]));
02309
02310 if (isnan(qa2imgs[i+nummodelparams+LF_O_PARAMS][curr_pixel]))
02311 qa2imgs[i+nummodelparams+LF_O_PARAMS][curr_pixel] = 0.0;
02312
02313 }
02314
02315 curr_pixel++;
02316
02317 }
02318 }
02319
02320 cx_free(iFitflags);
02321 cx_free(qa2imgs);
02322 cpl_matrix_delete(mAlpha);
02323 cpl_matrix_delete(mFitParams);
02324 cpl_matrix_delete(mSig);
02325 cpl_matrix_delete(mYs);
02326 cpl_matrix_delete(mY);
02327 cpl_matrix_delete(mX);
02328
02329 cpl_msg_info(
02330 fctid,
02331 "Fit completed, Spectra/Lines Combinations : good/rejected/total = %d/%d/%d",
02332 spec_count * numreflines - numrejected,
02333 numrejected,
02334 spec_count * numreflines
02335 );
02336
02337 cpl_msg_debug(
02338 fctid,
02339 "Processing completed: Returning image array [x,y] = [%d,%d]",
02340 numreflines,
02341 spec_count
02342 );
02343
02344 return lines;
02345
02346 }
02347
02373 static GiImageStack*
02374 giraffe_fit_lines_lmrq_wrapper(
02375 GiImage *ext_sp_frame,
02376 GiImage *ext_sp_err_frame,
02377 GiImage *locy_frame,
02378 GiImage *ref_line_frame,
02379 cpl_matrix *lines_params,
02380 lmrq_params fit_params,
02381 lmrq_model_id line_mod_id
02382 ) {
02383
02384
02385
02386
02387
02388 const cxchar *fctid = "giraffe_fit_lines_lmrq_wrapper";
02389
02390 cxint tsize = 0;
02391
02392 lmrq_model lmrq_line_model = lmrq_models[LMRQ_PSFEXP];
02393
02394 GiImageStack *result = NULL;
02395
02396
02397
02398
02399
02400 if (ext_sp_frame ==NULL) { return NULL; }
02401 if (ext_sp_err_frame==NULL) { return NULL; }
02402 if (locy_frame ==NULL) { return NULL; }
02403 if (ref_line_frame ==NULL) { return NULL; }
02404 if (lines_params ==NULL) { return NULL; }
02405
02406 if (line_mod_id == LMRQ_UNDEFINED) {
02407 cpl_msg_error(fctid, "Invalid Line Model, aborting...");
02408 return NULL;
02409 }
02410
02411 lmrq_line_model = lmrq_models[line_mod_id];
02412
02413 tsize = cpl_matrix_get_nrow(lines_params);
02414
02415 if ((lmrq_line_model.id == LMRQ_PSFEXP) ||
02416 (lmrq_line_model.id == LMRQ_PSFEXP2) )
02417 {
02418 if (LP_E_NPRMS != tsize) {
02419 cpl_msg_error(
02420 fctid,
02421 "Invalid number of line parameters for PSF EXP, aborting..."
02422 );
02423 return NULL;
02424 }
02425 } else {
02426
02427 if (LP_G_NPRMS != tsize) {
02428 cpl_msg_error(
02429 fctid,
02430 "Invalid number of line parameters for PSF GAUSS, aborting..."
02431 );
02432 return NULL;
02433 }
02434 }
02435
02436
02437
02438
02439
02440 result =
02441 giraffe_fit_lines_lmrq(
02442 giraffe_image_get(ext_sp_frame),
02443 giraffe_image_get(ext_sp_err_frame),
02444 giraffe_image_get(locy_frame),
02445 giraffe_image_get(ref_line_frame),
02446 lines_params,
02447 lmrq_line_model,
02448 fit_params
02449 );
02450
02451 return result;
02452
02453 }
02454
02455
02498 static cxint
02499 giraffe_fit_x_optm_residuals(
02500 GiLocPosition loc_pos,
02501 GiImageStack *lines,
02502 GiSlitGeometry *slit_geo,
02503 GiPolyDeg xor_poly_params,
02504 GiClipParams xor_clip_params,
02505 cpl_image *xor_fit,
02506 GiSlitGeometry *xor_coeff
02507
02508 ) {
02509
02510
02511
02512
02513
02514 const cxchar *fctid = "giraffe_fit_x_optm_residuals";
02515
02516 cpl_matrix *m_ss = NULL,
02517 *xss = NULL,
02518 *yss = NULL,
02519 *rss = NULL,
02520 *sss = NULL,
02521 *nss = NULL,
02522 *mss = NULL,
02523 *base = NULL,
02524 *cheb = NULL,
02525 *fit = NULL;
02526
02527 cxdouble *pd_m_ss,
02528 *pd_xss,
02529 *pd_yss,
02530 *pd_rss,
02531 *pd_sss,
02532 *pd_nss,
02533 *pd_mss,
02534 *pd_m_y,
02535 *pd_m_w,
02536 *pd_fit,
02537 *pd_xor_fit,
02538 **qa2imgs = NULL,
02539 medsss,
02540 *buffer = NULL;
02541
02542 cxint nlineparams,
02543 nc_fit,
02544 nr_fit,
02545 nr_mss,
02546 nc_rss,
02547 i,
02548 nlines,
02549 index_center,
02550 index_center_sigma;
02551
02552 register cxint subslit, nfibers, n, nn, nx, ns, nmin, nmax, ndata,
02553 nlen, ngoodlines;
02554 register cxint k, l, ll, m, x, xx, nlines_accepted, nlines_total, niter;
02555 register cxdouble ymin, ymax, y_upper, y_lower, nlines_ratio;
02556
02557
02558
02559
02560
02561 if (lines ==NULL) { return -1; }
02562 if (slit_geo ==NULL) { return -1; }
02563 if (xor_fit ==NULL) { return -1; }
02564 if (xor_coeff==NULL) { return -1; }
02565
02566 nlineparams = giraffe_imagestack_size(lines);
02567 nlines = cpl_image_get_nx(giraffe_imagestack_get(lines, LF_I_STATUS));
02568
02569 nx = cpl_image_get_ny(loc_pos.centroids);
02570 ns = cpl_image_get_nx(loc_pos.centroids);
02571
02572 qa2imgs = (cxdouble**) cx_calloc(nlineparams, sizeof(cxdouble*));
02573
02574 for (i=0;i<nlineparams;i++) {
02575 cxdouble *tmpdbl;
02576 tmpdbl = cpl_image_get_data_double(giraffe_imagestack_get(lines, i));
02577 qa2imgs[i] = tmpdbl;
02578 }
02579
02580
02581
02582
02583
02584 cpl_msg_info(
02585 fctid,
02586 "Performing X Optical Residuals fit of spectra/reference wavelengths using "
02587 "'%s' model, %d spectra and %d lines",
02588 nlineparams == LF_G_NPARAMS ? "Gaussian" : "Exponential",
02589 ns,
02590 nlines
02591 );
02592
02593 cpl_msg_debug(
02594 fctid,
02595 "Using : Chebyshev polynomial (%d,%d), Sigma Clipping : sigma=%4.1f, niter=%4i, mfrac=%4.2f",
02596 xor_poly_params.xdeg,
02597 xor_poly_params.ydeg,
02598 xor_clip_params.sigma,
02599 xor_clip_params.niter,
02600 xor_clip_params.mfrac
02601 );
02602
02603 if (nlineparams == LF_G_NPARAMS) {
02604
02605 index_center = LF_O_PARAMS + LF_G_CENTER;
02606 index_center_sigma = LF_O_PARAMS + LF_G_SCENTER;
02607 } else if (nlineparams == LF_E_NPARAMS) {
02608
02609 index_center = LF_O_PARAMS + LF_E_CENTER;
02610 index_center_sigma = LF_O_PARAMS + LF_E_SCENTER;
02611 } else {
02612 cpl_msg_error(fctid, "Unknown line model, aborting...." );
02613 cx_free(qa2imgs);
02614 return -2;
02615 }
02616
02617 ngoodlines = 0;
02618
02619 for (subslit = 0; subslit<giraffe_slitgeometry_size(slit_geo); subslit++) {
02620
02621 m_ss = giraffe_slitgeometry_get(slit_geo, subslit);
02622 pd_m_ss = cpl_matrix_get_data(m_ss);
02623
02624 giraffe_matrix_sort(m_ss);
02625
02626 giraffe_slitgeometry_set(xor_coeff, subslit, NULL);
02627
02628
02629 nfibers = cpl_matrix_get_nrow(m_ss);
02630
02631 nmin = (cxint) pd_m_ss[0];
02632 nmax = (cxint) pd_m_ss[nfibers - 1];
02633
02634 nlen = nmax - nmin + 1;
02635 ymax = 0.0;
02636 ymin = CX_MAXDOUBLE;
02637
02638 cpl_msg_debug(fctid, "Slit geometry : nmin, nmax = [%d,%d], "
02639 "#spectra=%d", nmin, nmax, ns);
02640
02641 pd_m_y = cpl_image_get_data_double(loc_pos.centroids);
02642 pd_m_w = cpl_image_get_data_double(loc_pos.widths);
02643
02644
02645 for (k = 0, n = nmin; n <= nmax; n++, k++) {
02646 for (x = 0; x < nx; x++) {
02647 xx = x * ns + n;
02648 y_upper = pd_m_y[xx] + pd_m_w[xx];
02649 y_lower = pd_m_y[xx] - pd_m_w[xx];
02650 if (ymax<y_upper) ymax = y_upper;
02651 if (ymin>y_lower) ymin = y_lower;
02652 }
02653 }
02654
02655
02656 ndata = nlines * nlen;
02657
02658 xss = cpl_matrix_new(ndata, 1);
02659 yss = cpl_matrix_new(ndata, 1);
02660 rss = cpl_matrix_new(1, ndata);
02661 sss = cpl_matrix_new(ndata, 1);
02662 nss = cpl_matrix_new(ndata, 1);
02663
02664 pd_xss = cpl_matrix_get_data(xss);
02665 pd_yss = cpl_matrix_get_data(yss);
02666 pd_rss = cpl_matrix_get_data(rss);
02667 pd_sss = cpl_matrix_get_data(sss);
02668 pd_nss = cpl_matrix_get_data(nss);
02669
02670
02671
02672
02673
02674
02675
02676
02677 for (k = 0, m = 0, n = nmin; n <= nmax; n++, m++) {
02678 nn = n * nlines;
02679 for (l = 0; l < nlines; l++) {
02680 ll = l + nn;
02681
02682 if (qa2imgs[LF_I_STATUS][ll] <= 0.0) continue;
02683 if (qa2imgs[LF_I_YCCD][ll] > ymax) continue;
02684 if (qa2imgs[LF_I_YCCD][ll] < ymin) continue;
02685
02686 pd_xss[k] = qa2imgs[LF_I_XCCD][ll];
02687 pd_yss[k] = qa2imgs[LF_I_YCCD][ll];
02688 pd_rss[k] = qa2imgs[LF_I_XCCD][ll] - qa2imgs[index_center][ll];
02689 pd_sss[k] = qa2imgs[index_center_sigma][ll];
02690 pd_nss[k] = (cxdouble) ll;
02691 k++;
02692 }
02693 }
02694
02695
02696
02697
02698
02699 cpl_matrix_resize(xss, k, 1);
02700 cpl_matrix_resize(yss, k, 1);
02701 cpl_matrix_resize(rss, 1, k);
02702 cpl_matrix_resize(sss, k, 1);
02703 cpl_matrix_resize(nss, k, 1);
02704
02705 pd_xss = cpl_matrix_get_data(xss);
02706 pd_yss = cpl_matrix_get_data(yss);
02707 pd_rss = cpl_matrix_get_data(rss);
02708 pd_sss = cpl_matrix_get_data(sss);
02709 pd_nss = cpl_matrix_get_data(nss);
02710
02711
02712
02713
02714
02715 mss = cpl_matrix_duplicate(sss);
02716
02717 pd_mss = cpl_matrix_get_data(mss);
02718 nr_mss = cpl_matrix_get_nrow(mss);
02719
02720 giraffe_matrix_sort(mss);
02721
02722 if (nr_mss & 1) {
02723 medsss = pd_mss[(nr_mss-1)/2];
02724 } else {
02725 medsss = (pd_mss[(nr_mss>>1)-1] + pd_mss[nr_mss>>1])/2.0;
02726 }
02727
02728
02729
02730
02731
02732 nc_rss = cpl_matrix_get_ncol(rss);
02733
02734 nlines_ratio = 1.0;
02735 nlines_total = nc_rss;
02736 nlines_accepted = nc_rss;
02737 niter = 0;
02738
02739 while ( (nlines_accepted>0 ) &&
02740 (niter<xor_clip_params.niter ) &&
02741 (nlines_ratio>xor_clip_params.mfrac) )
02742 {
02743
02744 cpl_msg_debug(fctid,"Lines Accepted: %d>0, Iteration: %d<%d, "
02745 "Ratio: %12.6f > %12.6f",
02746 nlines_accepted, niter, xor_clip_params.niter,
02747 nlines_ratio, xor_clip_params.mfrac);
02748
02749 base =
02750 giraffe_chebyshev_base2d(
02751 0.0,
02752 ymin,
02753 (cxdouble) nx,
02754 (ymax - ymin + 1.0),
02755 xor_poly_params.xdeg + 1,
02756 xor_poly_params.ydeg + 1,
02757 xss,
02758 yss
02759 );
02760
02761 cpl_matrix_delete(cheb); cheb = NULL;
02762
02763 cheb = giraffe_matrix_leastsq(base, rss);
02764
02765 if (cheb==NULL) {
02766 cpl_msg_error(
02767 fctid,
02768 "Error in leastsq solve subslit[%d], skipping...",
02769 subslit
02770 );
02771 break;
02772 }
02773
02774 fit = cpl_matrix_product(cheb, base);
02775 nc_fit = cpl_matrix_get_ncol(fit);
02776 pd_fit = cpl_matrix_get_data(fit);
02777
02778 k = 0;
02779 for (l=0; l<nc_fit; l++) {
02780 if (fabs(pd_fit[l] - pd_rss[l]) >=
02781 xor_clip_params.sigma * medsss )
02782 {
02783
02784
02785 qa2imgs[LF_I_STATUS][(cxint)pd_nss[l]] =
02786 -1.0 * (cxdouble) LF_R_XRFIT;
02787
02788
02789 continue;
02790 }
02791
02792
02793 pd_xss[k] = pd_xss[l];
02794 pd_yss[k] = pd_yss[l];
02795 pd_rss[k] = pd_rss[l];
02796 pd_sss[k] = pd_sss[l];
02797 pd_nss[k] = pd_nss[l];
02798 k++;
02799
02800 }
02801
02802 cpl_matrix_delete(fit); fit = NULL;
02803 cpl_matrix_delete(base); base = NULL;
02804
02805
02806
02807
02808
02809
02810 if (k == nlines_accepted) break;
02811
02812
02813 nlines_accepted = k;
02814 nlines_ratio = (cxdouble) nlines_accepted / (cxdouble) nlines_total;
02815
02816
02817 cpl_matrix_resize(xss, k, 1);
02818 cpl_matrix_resize(yss, k, 1);
02819 cpl_matrix_resize(rss, 1, k);
02820 cpl_matrix_resize(sss, k, 1);
02821 cpl_matrix_resize(nss, k, 1);
02822
02823 pd_xss = cpl_matrix_get_data(xss);
02824 pd_yss = cpl_matrix_get_data(yss);
02825 pd_rss = cpl_matrix_get_data(rss);
02826 pd_sss = cpl_matrix_get_data(sss);
02827 pd_nss = cpl_matrix_get_data(nss);
02828
02829 niter++;
02830 }
02831
02832
02833 if (nlines_accepted==0) {
02834 cpl_msg_info(fctid, "subslit[%d]: no lines accepted", subslit);
02835 continue;
02836 }
02837
02838 if (cheb==NULL) {
02839 cpl_msg_info(fctid, "subslit[%d]: error in least square",
02840 subslit);
02841 continue;
02842 }
02843
02844 ngoodlines += nlines_accepted;
02845
02846 cpl_matrix_delete(nss); nss = NULL;
02847 cpl_matrix_delete(sss); sss = NULL;
02848 cpl_matrix_delete(rss); rss = NULL;
02849 cpl_matrix_delete(yss); yss = NULL;
02850 cpl_matrix_delete(xss); xss = NULL;
02851
02852
02853 xss = cpl_matrix_new(nx * nlen, 1);
02854
02855 giraffe_compute_image_coordinates(nx, nlen, xss, NULL);
02856
02857 yss = cpl_matrix_new(nx * nlen, 1);
02858 pd_yss = cpl_matrix_get_data(yss);
02859
02860 for (k = 0, n = nmin; n <= nmax; n++, k++) {
02861 for (x = 0; x < nx; x++) {
02862 pd_yss[k + x * nlen] = pd_m_y[n + x * ns];
02863 }
02864 }
02865
02866 base =
02867 giraffe_chebyshev_base2d(
02868 0.0,
02869 ymin,
02870 (cxdouble) nx,
02871 (ymax - ymin + 1.0),
02872 xor_poly_params.xdeg + 1,
02873 xor_poly_params.ydeg + 1,
02874 xss,
02875 yss
02876 );
02877
02878 cpl_matrix_delete(yss); yss = NULL;
02879 cpl_matrix_delete(xss); xss = NULL;
02880
02881 fit = cpl_matrix_product(cheb, base);
02882
02883 giraffe_slitgeometry_set(xor_coeff, subslit, cheb);
02884
02885
02886 cpl_msg_debug(
02887 fctid,
02888 "XResid subslit %d matrix r,c=:%d,%d",
02889 subslit,
02890 cpl_matrix_get_nrow(giraffe_slitgeometry_get(xor_coeff, subslit)),
02891 cpl_matrix_get_ncol(giraffe_slitgeometry_get(xor_coeff, subslit))
02892 );
02893
02894 cpl_matrix_delete(base); base = NULL;
02895 cpl_matrix_delete(cheb); cheb = NULL;
02896
02897
02898
02899 buffer = cpl_matrix_get_data(fit);
02900
02901 cpl_matrix_delete_but_data(fit); fit = NULL;
02902 fit = cpl_matrix_new_from_data(buffer,nx, nlen);
02903
02904 pd_fit = cpl_matrix_get_data(fit);
02905 nr_fit = cpl_matrix_get_nrow(fit);
02906 nc_fit = cpl_matrix_get_ncol(fit);
02907
02908 pd_xor_fit = cpl_image_get_data_double(xor_fit);
02909
02910
02911 for (x = 0; x < nr_fit; x++) {
02912 for (k = nmin, n = 0; n < nc_fit; n++, k++) {
02913 pd_xor_fit[k + x * ns] = pd_fit[n + x * nc_fit];
02914 }
02915 }
02916
02917 cpl_matrix_delete(fit); fit = NULL;
02918
02919 }
02920
02921 cpl_msg_debug(fctid, "Found %d goodlines", ngoodlines);
02922
02923 cpl_msg_info(
02924 fctid,
02925 "Processing completed, Spectrum/Line Combinations : good/rejected/total = %d/%d/%d",
02926 ngoodlines,
02927 ns * nlines - ngoodlines,
02928 ns * nlines
02929 );
02930
02931 cx_free(qa2imgs); qa2imgs = NULL;
02932
02933 return ngoodlines;
02934
02935 }
02936
02969 static cxint
02970 giraffe_fit_x_optm_residuals_wrapper(
02971 GiImage *locy_frame,
02972 GiImage *locw_frame,
02973 GiImageStack *lines,
02974 GiSlitGeometry *slit_geo,
02975 GiClipParams xor_clip_params,
02976 GiPolyDeg xor_poly_params,
02977 GiWcalSolution *wavcoeff,
02978 GiImage *xor_fit_frame,
02979 GiTable *xor_cheb_table,
02980 GiWcalConfig *wcalib_config,
02981 GiGrating *grating_data,
02982 cxdouble curr_line_width
02983 ) {
02984
02985
02986
02987
02988
02989 const cxchar *fctid = "giraffe_fit_x_optm_residuals_wrapper";
02990
02991 cpl_image *opt_mod_resid = NULL,
02992 *_locy = NULL,
02993 *_locw = NULL;
02994
02995 cxint ce_code;
02996 cxint ssfs = 0,
02997 countlines = 0,
02998 status = 0,
02999 numslits = 0,
03000 i = 0,
03001 j = 0,
03002 num_coeff = 0,
03003 mcol = 0,
03004 mrow = 0,
03005 maxcount = 0;
03006
03007 cxdouble *dblbuffer = NULL,
03008 *pd_m = NULL,
03009 val = 0.0;
03010
03011 cpl_table *ref_wtable = NULL;
03012
03013 GiSlitGeometry *opt_mod_resid_coeff = NULL;
03014
03015 cpl_plist *ref_presult = NULL,
03016 *ref_plist = NULL;
03017
03018 cpl_matrix *m = NULL;
03019
03020 cpl_image_stats *stats = NULL;
03021
03022 cxchar buffer[68],
03023 colnamebuffer[80],
03024 wspoly[80];
03025
03026 GiLocPosition loc_pos;
03027
03028
03029
03030
03031
03032
03033 if (locy_frame ==NULL) { return 1; }
03034 if (locw_frame ==NULL) { return 1; }
03035 if (lines ==NULL) { return 1; }
03036 if (slit_geo ==NULL) { return 1; }
03037 if (wavcoeff ==NULL) { return 1; }
03038 if (xor_fit_frame ==NULL) { return 1; }
03039 if (xor_cheb_table==NULL) { return 1; }
03040 if (wcalib_config ==NULL) { return 1; }
03041 if (grating_data ==NULL) { return 1; }
03042
03043 _locy = giraffe_image_get(locy_frame);
03044 _locw = giraffe_image_get(locw_frame);
03045
03046 xor_poly_params.ncoeffs =
03047 (xor_poly_params.xdeg+1) * (xor_poly_params.ydeg+1);
03048
03049 opt_mod_resid =
03050 cpl_image_new_double(
03051 cpl_image_get_nx(_locy),
03052 cpl_image_get_ny(_locy),
03053 NULL,
03054 NULL
03055 );
03056
03057 ssfs = giraffe_slitgeometry_size(slit_geo);
03058 opt_mod_resid_coeff = giraffe_slitgeometry_new();
03059 giraffe_slitgeometry_resize(opt_mod_resid_coeff, ssfs);
03060
03061 loc_pos.type = GILOCDATATYPE_FITTED_DATA;
03062 loc_pos.centroids = _locy;
03063 loc_pos.widths = _locw;
03064
03065
03066
03067
03068
03069 countlines =
03070 giraffe_fit_x_optm_residuals(
03071 loc_pos,
03072 lines,
03073 slit_geo,
03074 xor_poly_params,
03075 xor_clip_params,
03076 opt_mod_resid,
03077 opt_mod_resid_coeff
03078 );
03079
03080 if (countlines<0) {
03081 cpl_msg_error(fctid, "Error computing X residuals, aborting..." );
03082
03083
03084 giraffe_image_set(xor_fit_frame, NULL);
03085 giraffe_image_set_properties(xor_fit_frame, NULL);
03086 cpl_image_delete(opt_mod_resid);
03087
03088
03089 giraffe_slitgeometry_delete(opt_mod_resid_coeff);
03090
03091 return 2;
03092 }
03093
03094 giraffe_image_set(xor_fit_frame, opt_mod_resid);
03095
03096 cpl_image_delete(opt_mod_resid); opt_mod_resid = NULL;
03097
03098 status =
03099 giraffe_image_set_properties(
03100 xor_fit_frame,
03101 giraffe_image_get_properties(locy_frame)
03102 );
03103
03104 ref_presult = giraffe_image_get_properties(xor_fit_frame);
03105
03106
03107
03108
03109
03110 stats =
03111 cpl_image_stat(giraffe_image_get(xor_fit_frame),
03112 CPL_STAT_MIN | CPL_STAT_MAX );
03113
03114 status =
03115 giraffe_plist_update_double(
03116 ref_presult,
03117 GIALIAS_DATAMIN,
03118 cpl_image_stats_get_min(stats)
03119 );
03120
03121 status =
03122 giraffe_plist_update_double(
03123 ref_presult,
03124 GIALIAS_DATAMAX,
03125 cpl_image_stats_get_max(stats)
03126 );
03127
03128 status =
03129 giraffe_plist_update_double(
03130 ref_presult,
03131 GIALIAS_XRES_SIG,
03132 xor_clip_params.sigma
03133 );
03134
03135 status =
03136 giraffe_plist_update_int(
03137 ref_presult,
03138 GIALIAS_XRES_NIT,
03139 xor_clip_params.niter
03140 );
03141
03142 status =
03143 giraffe_plist_update_double(
03144 ref_presult,
03145 GIALIAS_XRES_MFR,
03146 xor_clip_params.mfrac
03147 );
03148
03149 cx_snprintf(buffer, 68, "%d,%d", xor_poly_params.xdeg+1,
03150 xor_poly_params.ydeg+1);
03151
03152 status =
03153 giraffe_plist_update_string(
03154 ref_presult,
03155 GIALIAS_XRES_PDEG,
03156 buffer
03157 );
03158
03159 status =
03160 giraffe_plist_update_int(
03161 ref_presult,
03162 GIALIAS_XRES_SSN,
03163 giraffe_slitgeometry_size(slit_geo)
03164 );
03165
03166 cx_free(stats);
03167
03168
03169
03170
03171
03172 ref_plist = giraffe_table_get_properties(xor_cheb_table);
03173
03174 status =
03175 giraffe_plist_update_string(
03176 ref_plist,
03177 GIALIAS_EXTNAME,
03178 "XRESCOEFF"
03179 );
03180
03181 status =
03182 giraffe_plist_update_double(
03183 ref_plist,
03184 GIALIAS_XRES_SIG,
03185 wcalib_config->xws_clip_level
03186 );
03187
03188 status =
03189 giraffe_plist_update_int(
03190 ref_plist,
03191 GIALIAS_XRES_NIT,
03192 wcalib_config->xws_clip_niter
03193 );
03194
03195 status =
03196 giraffe_plist_update_double(
03197 ref_plist,
03198 GIALIAS_XRES_MFR,
03199 wcalib_config->xws_clip_mfrac
03200 );
03201
03202 status =
03203 giraffe_plist_update_int(
03204 ref_plist,
03205 GIALIAS_XRES_SSN,
03206 giraffe_slitgeometry_size(slit_geo)
03207 );
03208
03209 if (wcalib_config->opt_model==LMRQ_XOPTMOD2) {
03210
03211 status =
03212 giraffe_plist_update_string(
03213 ref_plist,
03214 GIALIAS_WSOL_OMNAME,
03215 "xoptmod2"
03216 );
03217
03218 } else if (wcalib_config->opt_model==LMRQ_XOPTMOD) {
03219
03220 status =
03221 giraffe_plist_update_string(
03222 ref_plist,
03223 GIALIAS_WSOL_OMNAME,
03224 "xoptmod"
03225 );
03226
03227 } else {
03228
03229 status =
03230 giraffe_plist_update_string(
03231 ref_plist,
03232 GIALIAS_WSOL_OMNAME,
03233 "unknown"
03234 );
03235 }
03236
03237 sprintf(wspoly, "%d:%d", wcalib_config->xws_poly_x_deg+1,
03238 wcalib_config->xws_poly_y_deg+1);
03239
03240 status = giraffe_plist_update_string(ref_plist, GIALIAS_XRES_PDEG,
03241 wspoly);
03242 status = giraffe_plist_update_string(ref_plist, GIALIAS_GIRFTYPE,
03243 "WAVCOEFTAB");
03244
03245 status = giraffe_plist_update_string(ref_plist, GIALIAS_SETUPNAME,
03246 cx_string_get(grating_data->setup));
03247 cpl_plist_set_comment(ref_plist, GIALIAS_SETUPNAME, "Exposure mode.");
03248
03249 status = giraffe_plist_update_string(ref_plist, GIALIAS_SLITNAME,
03250 cx_string_get(grating_data->slit));
03251 cpl_plist_set_comment(ref_plist, GIALIAS_SLITNAME, "Slit name.");
03252
03253 status = giraffe_plist_update_string(ref_plist, GIALIAS_SLITS_ID,
03254 cx_string_get(grating_data->slit));
03255 status = giraffe_plist_update_string(ref_plist, GIALIAS_SLITS_NAME,
03256 cx_string_get(grating_data->slit));
03257 status = giraffe_plist_update_string(ref_plist, GIALIAS_GRATNAME,
03258 cx_string_get(grating_data->name));
03259 cpl_plist_set_comment(ref_plist, GIALIAS_GRATNAME, "Grating common name.");
03260
03261 status = giraffe_plist_update_double(ref_plist, GIALIAS_GRATWLEN,
03262 grating_data->wlen0);
03263 cpl_plist_set_comment(ref_plist, GIALIAS_GRATWLEN, "Grating central "
03264 "wavelength [nm].");
03265
03266 status = giraffe_plist_update_int(ref_plist, GIALIAS_GRATORDER,
03267 (cxint)grating_data->order);
03268 cpl_plist_set_comment(ref_plist, GIALIAS_GRATORDER, "Grating order "
03269 "number.");
03270
03271 status = giraffe_plist_update_string(ref_plist, GIALIAS_FILTNAME,
03272 cx_string_get(grating_data->filter));
03273 cpl_plist_set_comment(ref_plist, GIALIAS_FILTNAME, "Filter name.");
03274
03275 status = giraffe_plist_update_int(ref_plist, GIALIAS_OPTSOL,
03276 wcalib_config->opt_solution == TRUE ? 1 : 0);
03277 status =
03278 giraffe_plist_update_int(
03279 ref_plist,
03280 GIALIAS_WSOL_OMDIR,
03281 wcalib_config->opt_direction
03282 );
03283
03284 status =
03285 giraffe_plist_update_int(
03286 ref_plist,
03287 GIALIAS_WSOL_SUBSLITS,
03288 wcalib_config->fit_subslits==TRUE ? 1 : 0
03289 );
03290
03291 status =
03292 giraffe_plist_update_double(
03293 ref_plist,
03294 GIALIAS_WSOL_OMFCOLL,
03295 grating_data->fcoll
03296 );
03297
03298 status =
03299 giraffe_plist_update_double(
03300 ref_plist,
03301 GIALIAS_WSOL_OMGCAM,
03302 grating_data->gcam
03303 );
03304
03305 status =
03306 giraffe_plist_update_double(
03307 ref_plist,
03308 GIALIAS_WSOL_OMGTHETA,
03309 grating_data->theta
03310 );
03311
03312 status =
03313 giraffe_plist_update_double(
03314 ref_plist,
03315 GIALIAS_WSOL_OMSDX,
03316 grating_data->sdx
03317 );
03318
03319 status =
03320 giraffe_plist_update_double(
03321 ref_plist,
03322 GIALIAS_WSOL_OMSDY,
03323 grating_data->sdy
03324 );
03325
03326 status =
03327 giraffe_plist_update_double(
03328 ref_plist,
03329 GIALIAS_WSOL_OMSPHI,
03330 grating_data->sphi
03331 );
03332
03333 if (wcalib_config->line_model==LMRQ_PSFEXP2) {
03334
03335 status =
03336 giraffe_plist_update_string(
03337 ref_plist,
03338 GIALIAS_WSOL_LINEM,
03339 "psfexp2"
03340 );
03341
03342 } else if (wcalib_config->line_model==LMRQ_PSFEXP) {
03343
03344 status =
03345 giraffe_plist_update_string(
03346 ref_plist,
03347 GIALIAS_WSOL_LINEM,
03348 "psfexp"
03349 );
03350
03351 } else if (wcalib_config->line_model==LMRQ_GAUSSUM) {
03352
03353 status =
03354 giraffe_plist_update_string(
03355 ref_plist,
03356 GIALIAS_WSOL_LINEM,
03357 "gaussum"
03358 );
03359
03360 } else {
03361
03362 status =
03363 giraffe_plist_update_string(
03364 ref_plist,
03365 GIALIAS_WSOL_LINEM,
03366 "unknown"
03367 );
03368 }
03369
03370 status =
03371 giraffe_plist_update_double(
03372 ref_plist,
03373 GIALIAS_WSOL_LINEWDTH,
03374 curr_line_width
03375 );
03376
03377 status =
03378 giraffe_plist_update_double(
03379 ref_plist,
03380 GIALIAS_WSOL_LINETHOLD,
03381 wcalib_config->line_threshold
03382 );
03383
03384 status =
03385 giraffe_plist_update_int(
03386 ref_plist,
03387 GIALIAS_WSOL_LINENIT,
03388 wcalib_config->line_niter
03389 );
03390
03391 status =
03392 giraffe_plist_update_int(
03393 ref_plist,
03394 GIALIAS_WSOL_LINENTST,
03395 wcalib_config->line_ntest
03396 );
03397
03398 status =
03399 giraffe_plist_update_double(
03400 ref_plist,
03401 GIALIAS_WSOL_LINEDCHQ,
03402 wcalib_config->line_dchsq
03403 );
03404
03405 status =
03406 giraffe_plist_update_double(
03407 ref_plist,
03408 GIALIAS_WSOL_GRTHETA,
03409 grating_data->theta
03410 );
03411
03412 status =
03413 giraffe_plist_update_double(
03414 ref_plist,
03415 GIALIAS_WSOL_GRORDER,
03416 grating_data->order
03417 );
03418 status =
03419 giraffe_plist_update_double(
03420 ref_plist,
03421 GIALIAS_WSOL_GRSPACE,
03422 grating_data->space
03423 );
03424
03425
03426
03427
03428
03429 num_coeff = ((xor_poly_params.xdeg+1)*(xor_poly_params.ydeg+1));
03430 numslits = giraffe_slitgeometry_size(opt_mod_resid_coeff);
03431
03432
03433
03434
03435
03436 for (i=0; i<numslits; i++) {
03437
03438 cpl_matrix *dummy;
03439 cxint count = 0;
03440
03441 dummy = giraffe_slitgeometry_get(opt_mod_resid_coeff, i);
03442
03443 count = cpl_matrix_get_ncol(dummy);
03444 count *= cpl_matrix_get_nrow(dummy);
03445
03446 if (count>maxcount) {
03447 maxcount = count;
03448 }
03449 }
03450
03451 if (maxcount!=num_coeff) {
03452 cpl_msg_warning(fctid, "Actual # of coefficients not equal "
03453 "to expected #...");
03454 }
03455
03456 ref_wtable = cpl_table_new(1);
03457
03458 ce_code = cpl_table_new_column_int(ref_wtable, "SUBSLIT");
03459
03460 for (i=0; i<num_coeff; i++) {
03461 snprintf(colnamebuffer, sizeof(cxchar)*80, "XC%d", i);
03462 ce_code =
03463 cpl_table_new_column_double(
03464 ref_wtable,
03465 (const char*)colnamebuffer
03466 );
03467 }
03468
03469
03470
03471 for (j=0; j<numslits; j++) {
03472
03473 cxint coeff_count = 0;
03474
03475 ce_code =
03476 cpl_table_set_int(
03477 ref_wtable,
03478 "SUBSLIT",
03479 j,
03480 j
03481 );
03482
03483 m = cpl_matrix_duplicate(giraffe_slitgeometry_get(opt_mod_resid_coeff, j));
03484
03485 if (m==NULL) break;
03486
03487 pd_m = cpl_matrix_get_data(m);
03488 mcol = cpl_matrix_get_ncol(m);
03489 mrow = cpl_matrix_get_nrow(m);
03490
03491 coeff_count = mcol * mrow;
03492
03493
03494
03495
03496
03497
03498
03499
03500 dblbuffer = cpl_matrix_get_data(m);
03501 cpl_matrix_delete_but_data(m); m = NULL;
03502
03503 m =
03504 cpl_matrix_new_from_data(
03505 dblbuffer,
03506 xor_poly_params.xdeg+1,
03507 xor_poly_params.ydeg+1
03508 );
03509
03510 if (coeff_count>num_coeff) {
03511 cpl_msg_warning(
03512 fctid,
03513 "More entries in matrix than expected! Only using first %d!",
03514 num_coeff
03515 );
03516 }
03517
03518 for (i=0; i<num_coeff; i++) {
03519
03520 if (i<coeff_count) {
03521
03522 val = pd_m[i];
03523 snprintf(colnamebuffer, sizeof(cxchar)*80, "XC%d", i);
03524
03525 ce_code =
03526 cpl_table_set_double(
03527 ref_wtable,
03528 (const char*) colnamebuffer,
03529 j,
03530 val
03531 );
03532
03533 val =
03534 cpl_table_get_double(
03535 ref_wtable,
03536 (const char*) colnamebuffer,
03537 j,
03538 NULL
03539 );
03540
03541 } else {
03542
03543 snprintf(colnamebuffer, sizeof(cxchar)*80, "XC%d", i);
03544 ce_code =
03545 cpl_table_set_double(
03546 ref_wtable,
03547 (const char*) colnamebuffer,
03548 j,
03549 0.0
03550 );
03551
03552 }
03553 }
03554
03555 cpl_matrix_delete(m);
03556
03557 }
03558
03559 giraffe_table_set(xor_cheb_table, ref_wtable);
03560 cpl_table_delete(ref_wtable);
03561
03562
03563
03564
03565
03566 {
03567
03568 cxdouble *pd = NULL;
03569 cpl_matrix *m = NULL;
03570
03571 numslits = giraffe_slitgeometry_size(opt_mod_resid_coeff);
03572
03573
03574
03575 for (i=0; i<numslits; i++) {
03576
03577 m = cpl_matrix_duplicate(giraffe_slitgeometry_get(opt_mod_resid_coeff, i));
03578
03579 pd = cpl_matrix_get_data(m);
03580 cpl_matrix_delete_but_data(m); m = NULL;
03581 m =
03582 cpl_matrix_new_from_data(
03583 pd,
03584 xor_poly_params.xdeg+1,
03585 xor_poly_params.ydeg+1
03586 );
03587
03588 giraffe_slitgeometry_set(opt_mod_resid_coeff, i, m);
03589 cpl_matrix_delete(m);
03590 }
03591
03592
03593
03594 if (wavcoeff->wav_coeffs==NULL) {
03595 wavcoeff->wav_coeffs = giraffe_slitgeometry_duplicate(opt_mod_resid_coeff);
03596 } else {
03597 giraffe_slitgeometry_delete(wavcoeff->wav_coeffs);
03598 wavcoeff->wav_coeffs = giraffe_slitgeometry_duplicate(opt_mod_resid_coeff);
03599 }
03600 }
03601
03602 giraffe_slitgeometry_delete(opt_mod_resid_coeff);
03603
03604 return 0;
03605
03606 }
03607
03608
03648 static cxint
03649 giraffe_fit_psf_x_width(
03650 GiLocPosition loc_pos,
03651 GiImageStack *lines,
03652 GiSlitGeometry *slit_geo,
03653 GiPolyDeg pxw_poly_params,
03654 GiClipParams pxw_clip_params,
03655 lmrq_model_id lmrq_line_model,
03656 cpl_image *pxw_fit,
03657 GiSlitGeometry *pxw_coeff
03658 ) {
03659
03660
03661
03662
03663
03664 const cxchar *fctid = "_fit_psf_x_width";
03665
03666 cxint nlineparams,
03667 nc_wss,
03668 nc_fit,
03669 nr_fit,
03670 nlines,
03671 index_width,
03672 index_width_sigma,
03673 index_expon,
03674 i;
03675
03676 cpl_matrix *m_ss = NULL,
03677 *xss = NULL,
03678 *yss = NULL,
03679 *wss = NULL,
03680 *sss = NULL,
03681 *nss = NULL,
03682 *base = NULL,
03683 *cheb = NULL,
03684 *fit = NULL;
03685
03686 cxdouble *pd_m_ss = NULL,
03687 *pd_xss = NULL,
03688 *pd_yss = NULL,
03689 *pd_wss = NULL,
03690 *pd_sss = NULL,
03691 *pd_nss = NULL,
03692 *pd_mY = NULL,
03693 *pd_mW = NULL,
03694 *pd_fit = NULL,
03695 *pd_pxw_fit = NULL,
03696 **qa2imgs = NULL,
03697 *buffer = NULL;
03698
03699 register cxint subslit, nfibers, n, nn, nx, ns, nmin, nmax, ndata, nlen,
03700 ngoodlines;
03701 register cxint k, l, ll, m, x, xx, nlines_accepted, niter,nlines_total = 0;
03702 register cxdouble ymin, ymax, y_upper, y_lower, nlines_ratio, fwhm_ratio;
03703
03704 cpl_image *refimg = NULL;
03705
03706
03707
03708
03709
03710 if (lines ==NULL) { return -1; }
03711 if (slit_geo ==NULL) { return -1; }
03712 if (pxw_fit ==NULL) { return -1; }
03713 if (pxw_coeff==NULL) { return -1; }
03714
03715 nlineparams = giraffe_imagestack_size(lines);
03716
03717 refimg = giraffe_imagestack_get(lines, LF_I_STATUS);
03718 nlines = cpl_image_get_nx(refimg);
03719
03720 nx = cpl_image_get_ny(loc_pos.centroids);
03721 ns = cpl_image_get_nx(loc_pos.centroids);
03722
03723 qa2imgs = cx_calloc(nlineparams, sizeof(cxdouble *));
03724
03725 for (i = 0; i < nlineparams; i++) {
03726
03727 cpl_image *image = giraffe_imagestack_get(lines, i);
03728
03729 qa2imgs[i] = cpl_image_get_data_double(image);
03730
03731 }
03732
03733
03734
03735
03736
03737 cpl_msg_info(
03738 fctid,
03739 "Performing PSF fit of spectra/reference lines using "
03740 "'%s' model, %d spectra and %d lines",
03741 lmrq_models[lmrq_line_model].name,
03742 ns,
03743 nlines
03744 );
03745
03746 cpl_msg_debug(
03747 fctid,
03748 "Using : Chebyshev polynomial (%d,%d), Sigma Clipping : "
03749 "sigma=%4.1f, niter=%4i, mfrac=%4.2f",
03750 pxw_poly_params.xdeg,
03751 pxw_poly_params.ydeg,
03752 pxw_clip_params.sigma,
03753 pxw_clip_params.niter,
03754 pxw_clip_params.mfrac
03755 );
03756
03757 if (nlineparams == LF_G_NPARAMS) {
03758
03759 index_width = LF_O_PARAMS + LF_G_WIDTH;
03760 index_width_sigma = LF_O_PARAMS + LF_G_SWIDTH;
03761 fwhm_ratio = 2.0 * sqrt(2.0 * log(2.0));
03762 } else if (nlineparams == LF_E_NPARAMS) {
03763
03764 index_width = LF_O_PARAMS + LF_E_WIDTH;
03765 index_width_sigma = LF_O_PARAMS + LF_E_SWIDTH;
03766 index_expon = LF_O_PARAMS + LF_E_EXPON;
03767 } else {
03768 cpl_msg_error(fctid, "Unknown line model, aborting...." );
03769 cx_free(qa2imgs);
03770 return -1;
03771 }
03772
03773 ngoodlines = 0;
03774
03775 for (subslit = 0; subslit < giraffe_slitgeometry_size(slit_geo);
03776 subslit++) {
03777
03778 cpl_msg_debug(fctid, "Processing subslit %d of %d", subslit + 1,
03779 giraffe_slitgeometry_size(slit_geo));
03780
03781 m_ss = giraffe_slitgeometry_get(slit_geo, subslit);
03782 pd_m_ss = cpl_matrix_get_data(m_ss);
03783
03784 giraffe_matrix_sort(m_ss);
03785
03786 giraffe_slitgeometry_set(pxw_coeff, subslit, NULL);
03787
03788
03789 nfibers = cpl_matrix_get_nrow(m_ss);
03790 nmin = (cxint) pd_m_ss[0];
03791 nmax = (cxint) pd_m_ss[nfibers - 1];
03792 nlen = nmax - nmin + 1;
03793 ymax = 0.0;
03794 ymin = CX_MAXDOUBLE;
03795
03796 cpl_msg_debug(fctid, "Slit geometry : nmin, nmax = [%d,%d], "
03797 "#spectra=%d", nmin, nmax, ns);
03798
03799 pd_mY = cpl_image_get_data_double(loc_pos.centroids);
03800 pd_mW = cpl_image_get_data_double(loc_pos.widths);
03801
03802
03803 for (m = 0, n = nmin; n <= nmax; n++, m++) {
03804 for (x = 0; x < nx; x++) {
03805 xx = x * ns + n;
03806 y_upper = pd_mY[xx] + pd_mW[xx];
03807 y_lower = pd_mY[xx] - pd_mW[xx];
03808
03809 if (ymax < y_upper) {
03810 ymax = y_upper;
03811 }
03812
03813 if (ymin > y_lower) {
03814 ymin = y_lower;
03815 }
03816 }
03817 }
03818
03819
03820 ndata = nlines * nlen;
03821
03822 xss = cpl_matrix_new(ndata, 1);
03823 yss = cpl_matrix_new(ndata, 1);
03824 wss = cpl_matrix_new(1, ndata);
03825 sss = cpl_matrix_new(ndata, 1);
03826 nss = cpl_matrix_new(ndata, 1);
03827
03828 pd_xss = cpl_matrix_get_data(xss);
03829 pd_yss = cpl_matrix_get_data(yss);
03830 pd_wss = cpl_matrix_get_data(wss);
03831 pd_sss = cpl_matrix_get_data(sss);
03832 pd_nss = cpl_matrix_get_data(nss);
03833
03834
03835
03836
03837
03838
03839 for (k = 0, m = 0, n = nmin; n <= nmax; n++, m++) {
03840 nn = n * nlines;
03841 for (l = 0; l < nlines; l++) {
03842 ll = l + nn;
03843
03844 if (qa2imgs[LF_I_STATUS][ll] <= 0.0 ) continue;
03845 if (qa2imgs[LF_I_YCCD][ll] > ymax) continue;
03846 if (qa2imgs[LF_I_YCCD][ll] < ymin) continue;
03847
03848 pd_xss[k] = qa2imgs[LF_I_XCCD][ll];
03849 pd_yss[k] = qa2imgs[LF_I_YCCD][ll];
03850 pd_wss[k] = qa2imgs[index_width][ll];
03851 pd_sss[k] = qa2imgs[index_width_sigma][ll];
03852 pd_nss[k] = (cxdouble) ll;
03853 k++;
03854 }
03855 }
03856
03857
03858 cpl_matrix_resize(xss, k, 1);
03859 cpl_matrix_resize(yss, k, 1);
03860 cpl_matrix_resize(wss, 1, k);
03861 cpl_matrix_resize(sss, k, 1);
03862 cpl_matrix_resize(nss, k, 1);
03863
03864 pd_xss = cpl_matrix_get_data(xss);
03865 pd_yss = cpl_matrix_get_data(yss);
03866 pd_wss = cpl_matrix_get_data(wss);
03867 pd_sss = cpl_matrix_get_data(sss);
03868 pd_nss = cpl_matrix_get_data(nss);
03869
03870
03871
03872 nc_wss = cpl_matrix_get_ncol(wss);
03873
03874 nlines_ratio = 1.0;
03875 nlines_accepted = nc_wss;
03876 nlines_total = nc_wss;
03877 niter = 0;
03878
03879 cpl_msg_debug(fctid, "SC: Iteration, Lines accepted, Line Ratio "
03880 ": %d/%d/%12.6f", niter, nlines_accepted, nlines_ratio);
03881
03882 while ((nlines_accepted > 0) && (niter < pxw_clip_params.niter) &&
03883 (nlines_ratio>pxw_clip_params.mfrac)) {
03884
03885 base =
03886 giraffe_chebyshev_base2d(
03887 0.0,
03888 ymin,
03889 (cxdouble) nx,
03890 (ymax - ymin + 1.0),
03891 pxw_poly_params.xdeg + 1,
03892 pxw_poly_params.ydeg + 1,
03893 xss,
03894 yss
03895 );
03896
03897 cpl_matrix_delete(cheb); cheb = NULL;
03898
03899 cheb = giraffe_matrix_leastsq(base, wss);
03900
03901 if (cheb==NULL) {
03902 cpl_msg_info(fctid, "Error in leastsq solve for cheyshev "
03903 "matrix subslit[%d], skipping...", subslit);
03904 break;
03905 }
03906
03907 fit = cpl_matrix_product(cheb, base);
03908
03909 nc_fit = cpl_matrix_get_ncol(fit);
03910 pd_fit = cpl_matrix_get_data(fit);
03911
03912 k = 0;
03913
03914 for (l = 0; l < nc_fit; l++) {
03915
03916 if ( fabs(pd_fit[l] - pd_wss[l]) >=
03917 pxw_clip_params.sigma * pd_sss[l]
03918 ) {
03919
03920
03921 qa2imgs[LF_I_STATUS][(cxint)pd_nss[l]] =
03922 -1.0 * (cxdouble) LF_R_PSFIT;
03923
03924 continue;
03925 }
03926
03927
03928 pd_xss[k] = pd_xss[l];
03929 pd_yss[k] = pd_yss[l];
03930 pd_wss[k] = pd_wss[l];
03931 pd_sss[k] = pd_sss[l];
03932 pd_nss[k] = pd_nss[l];
03933 k++;
03934 }
03935
03936 cpl_matrix_delete(fit); fit = NULL;
03937 cpl_matrix_delete(base); base = NULL;
03938
03939
03940
03941
03942
03943
03944 if (k == nlines_accepted) break;
03945
03946
03947 nlines_accepted = k;
03948 nlines_ratio = (cxdouble) nlines_accepted / (cxdouble) nlines_total;
03949
03950
03951
03952 cpl_matrix_resize(xss, k, 1);
03953 cpl_matrix_resize(yss, k, 1);
03954 cpl_matrix_resize(wss, 1, k);
03955 cpl_matrix_resize(sss, k, 1);
03956 cpl_matrix_resize(nss, k, 1);
03957
03958 pd_xss = cpl_matrix_get_data(xss);
03959 pd_yss = cpl_matrix_get_data(yss);
03960 pd_wss = cpl_matrix_get_data(wss);
03961 pd_sss = cpl_matrix_get_data(sss);
03962 pd_nss = cpl_matrix_get_data(nss);
03963
03964 niter++;
03965
03966 cpl_msg_debug(fctid, "SC: Iteration, Lines accepted, Line Ratio "
03967 ": %d/%d/%12.6f", niter, nlines_accepted, nlines_ratio);
03968
03969 }
03970
03971 if (nlines_accepted==0) {
03972 cpl_msg_info(fctid, "subslit[%d]: no lines accepted", subslit);
03973 continue;
03974 }
03975
03976 if (cheb==NULL) {
03977 cpl_msg_info(fctid, "subslit[%d]: error in least square, no "
03978 "chebyshev matrix found", subslit);
03979 continue;
03980 }
03981
03982 ngoodlines += nlines_accepted;
03983
03984 cpl_msg_debug(
03985 fctid,
03986 "subslit=%d : good lines=%d, iterations=%d, lines accepted=%d, "
03987 "lines total=%d, lines ratio=%.2f",
03988 subslit,
03989 ngoodlines,
03990 niter,
03991 nlines_accepted,
03992 nlines_total,
03993 nlines_ratio
03994 );
03995
03996 cpl_matrix_delete(nss); nss = NULL;
03997 cpl_matrix_delete(sss); sss = NULL;
03998 cpl_matrix_delete(wss); wss = NULL;
03999 cpl_matrix_delete(yss); yss = NULL;
04000 cpl_matrix_delete(xss); xss = NULL;
04001
04002
04003 xss = cpl_matrix_new(nx * nlen, 1);
04004
04005 giraffe_compute_image_coordinates(nx, nlen, xss, NULL);
04006
04007 yss = cpl_matrix_new(nx * nlen, 1);
04008 pd_yss = cpl_matrix_get_data(yss);
04009
04010 for (k = 0, n = nmin; n <= nmax; n++, k++) {
04011 for (x = 0; x < nx; x++) {
04012 pd_yss[k + x * nlen] = pd_mY[n + x * ns];
04013 }
04014 }
04015
04016
04017 base =
04018 giraffe_chebyshev_base2d(
04019 0.0,
04020 ymin,
04021 (cxdouble) nx,
04022 (ymax - ymin + 1.0),
04023 pxw_poly_params.xdeg + 1,
04024 pxw_poly_params.ydeg + 1,
04025 xss,
04026 yss
04027 );
04028
04029 cpl_matrix_delete(yss); yss = NULL;
04030 cpl_matrix_delete(xss); xss = NULL;
04031
04032 fit = cpl_matrix_product(cheb, base);
04033
04034 giraffe_slitgeometry_set(pxw_coeff, subslit, cheb);
04035
04036 cpl_matrix_delete(base); base = NULL;
04037 cpl_matrix_delete(cheb); cheb = NULL;
04038
04039
04040
04041 buffer = cpl_matrix_get_data(fit);
04042 cpl_matrix_delete_but_data(fit); fit = NULL;
04043 fit = cpl_matrix_new_from_data(buffer,nx, nlen);
04044
04045 pd_fit = cpl_matrix_get_data(fit);
04046 nr_fit = cpl_matrix_get_nrow(fit);
04047 nc_fit = cpl_matrix_get_ncol(fit);
04048
04049 pd_pxw_fit = cpl_image_get_data_double(pxw_fit);
04050
04051
04052 for (x = 0; x < nr_fit; x++) {
04053 for (k = nmin, n = 0; n < nc_fit; n++, k++) {
04054 pd_pxw_fit[k + x * ns] = pd_fit[n + x * nc_fit];
04055 }
04056 }
04057
04058 cpl_matrix_delete(fit); fit = NULL;
04059
04060 }
04061
04062 cx_free(qa2imgs); qa2imgs = NULL;
04063
04064 cpl_msg_info(
04065 fctid,
04066 "Fit completed, Spectra/Lines Combinations : good/rejected/total = %d/%d/%d",
04067 ngoodlines,
04068 nlines_total - ngoodlines,
04069 nlines_total
04070 );
04071
04072 return ngoodlines;
04073
04074 }
04075
04103 static cxint
04104 giraffe_fit_psf_x_width_wrapper(
04105 GiImage *locy_frame,
04106 GiImage *locw_frame,
04107 GiImageStack *lines,
04108 GiSlitGeometry *slit_geo,
04109 GiClipParams pxw_clip_params,
04110 GiPolyDeg pxw_poly_params,
04111 GiImage *pxw_fit_frame,
04112 GiTable *pxw_cheb_table,
04113 lmrq_model_id lmrq_line_model
04114 ) {
04115
04116
04117
04118
04119
04120 GiSlitGeometry *psf_width_var_table = NULL;
04121
04122 GiLocPosition loc_pos;
04123
04124 cpl_image *_locy = NULL,
04125 *_locw = NULL,
04126 *psf_width_var = NULL;
04127
04128 cxint nx_locy,
04129 ny_locy,
04130 size_nx,
04131 size_ny,
04132 nr_good_lines = -1,
04133 status = 0;
04134
04135 cpl_plist *ref_presult = NULL;
04136
04137 cxchar buffer[68];
04138
04139 cpl_image_stats *stats = NULL;
04140
04141
04142
04143
04144
04145 if (locy_frame ==NULL) { return 1; }
04146 if (locw_frame ==NULL) { return 1; }
04147 if (lines ==NULL) { return 1; }
04148 if (slit_geo ==NULL) { return 1; }
04149 if (pxw_fit_frame ==NULL) { return 1; }
04150 if (pxw_cheb_table==NULL) { return 1; }
04151
04152 _locy = giraffe_image_get(locy_frame);
04153 _locw = giraffe_image_get(locw_frame);
04154
04155 nx_locy = cpl_image_get_nx(_locy);
04156 ny_locy = cpl_image_get_ny(_locy);
04157
04158 psf_width_var = cpl_image_new_double(nx_locy, ny_locy, NULL, NULL);
04159
04160 psf_width_var_table = giraffe_slitgeometry_new();
04161 giraffe_slitgeometry_resize(psf_width_var_table, giraffe_slitgeometry_size(slit_geo));
04162
04163 loc_pos.type = GILOCDATATYPE_FITTED_DATA;
04164 loc_pos.centroids = _locy;
04165 loc_pos.widths = _locw;
04166
04167
04168
04169
04170
04171 nr_good_lines =
04172 giraffe_fit_psf_x_width(
04173 loc_pos,
04174 lines,
04175 slit_geo,
04176 pxw_poly_params,
04177 pxw_clip_params,
04178 lmrq_line_model,
04179 psf_width_var,
04180 psf_width_var_table
04181 );
04182
04183 giraffe_image_set(pxw_fit_frame, psf_width_var);
04184
04185 status =
04186 giraffe_image_set_properties(
04187 pxw_fit_frame,
04188 giraffe_image_get_properties(locy_frame)
04189 );
04190
04191 ref_presult = giraffe_image_get_properties(pxw_fit_frame);
04192
04193 status =
04194 giraffe_plist_update_string(
04195 ref_presult,
04196 GIALIAS_WSOL_OMNAME,
04197 lmrq_models[lmrq_line_model].name
04198 );
04199
04200 status =
04201 giraffe_plist_update_int(
04202 ref_presult,
04203 GIALIAS_NAXIS1,
04204 size_nx
04205 );
04206
04207 status =
04208 giraffe_plist_update_int(
04209 ref_presult,
04210 GIALIAS_NAXIS2,
04211 size_ny
04212 );
04213
04214 stats =
04215 cpl_image_stat(
04216 giraffe_image_get(pxw_fit_frame),
04217 CPL_STAT_MIN | CPL_STAT_MAX
04218 );
04219
04220 status =
04221 giraffe_plist_update_double(
04222 ref_presult,
04223 GIALIAS_DATAMIN,
04224 cpl_image_stats_get_min(stats)
04225 );
04226
04227 status =
04228 giraffe_plist_update_double(
04229 ref_presult,
04230 GIALIAS_DATAMAX,
04231 cpl_image_stats_get_max(stats)
04232 );
04233
04234 cx_free(stats);
04235
04236 status =
04237 giraffe_plist_update_double(
04238 ref_presult,
04239 GIALIAS_PSFW_SIG,
04240 pxw_clip_params.sigma
04241 );
04242
04243 status =
04244 giraffe_plist_update_int(
04245 ref_presult,
04246 GIALIAS_PSFW_NIT,
04247 pxw_clip_params.niter
04248 );
04249
04250 status =
04251 giraffe_plist_update_double(
04252 ref_presult,
04253 GIALIAS_PSFW_MFR,
04254 pxw_clip_params.mfrac
04255 );
04256
04257 cx_snprintf(buffer, 68, "%d,%d", pxw_poly_params.xdeg+1,
04258 pxw_poly_params.ydeg+1);
04259
04260 status =
04261 giraffe_plist_update_string(
04262 ref_presult,
04263 GIALIAS_PSFW_PDEG,
04264 buffer
04265 );
04266
04267 status =
04268 giraffe_plist_update_int(
04269 ref_presult,
04270 GIALIAS_PSFW_SSNR,
04271 giraffe_slitgeometry_size(slit_geo)
04272 );
04273
04274
04275
04276
04277
04278
04279
04280
04281
04282
04283
04284
04285
04286
04287
04288
04289
04290
04291
04292
04293
04294
04295
04296
04297
04298
04299
04300
04301
04302
04303
04304
04305
04306
04307
04308
04309 giraffe_slitgeometry_delete(psf_width_var_table);
04310
04311 return 0;
04312
04313 }
04314
04332 static cpl_image*
04333 giraffe_map_wavelength_to_residuals(
04334 cpl_image *x_pos,
04335 cpl_image *resid
04336 ) {
04337
04338 register cxint spec, line, pos;
04339 register cxdouble lbound, ubound, indx;
04340
04341 cxint nspectra,
04342 nlines,
04343 nx_resid,
04344 ny_resid;
04345
04346 cxdouble *pd_xcheb = NULL,
04347 *pd_x_pos = NULL,
04348 *pd_resid = NULL;
04349
04350 cpl_image *xcheb = NULL;
04351
04352
04353 if (x_pos==NULL) { return NULL; }
04354 if (resid==NULL) { return NULL; }
04355
04356 pd_x_pos = cpl_image_get_data_double(x_pos);
04357 pd_resid = cpl_image_get_data_double(resid);
04358
04359 nspectra = cpl_image_get_nx(x_pos);
04360 nlines = cpl_image_get_ny(x_pos);
04361
04362 nx_resid = cpl_image_get_nx(resid);
04363 ny_resid = cpl_image_get_ny(resid);
04364
04365 xcheb = cpl_image_new_double(nspectra, nlines, NULL, NULL);
04366 pd_xcheb = cpl_image_get_data_double(xcheb);
04367
04368 lbound = 0.0;
04369 ubound = (cxdouble) (nx_resid - 1);
04370
04371 for(spec=0; spec<nspectra; spec++) {
04372 for(line=0; line<nlines; line++) {
04373
04374 indx = pd_x_pos[line*nspectra+spec];
04375
04376 if (indx<lbound) indx = lbound;
04377 if (indx>ubound) indx = ubound;
04378
04379 pos = (cxint) indx;
04380
04381 pd_xcheb[line*nspectra+spec] = pd_resid[spec*nx_resid+pos];
04382
04383 }
04384 }
04385
04386 return xcheb;
04387 }
04388
04389
04407 static void
04408 giraffe_calculate_chebyshev_statistics(
04409 cpl_image *x_pos,
04410 GiImageStack *lines_data,
04411 cpl_image *x_center_pos,
04412 cpl_image *x_center_optm_cheb
04413 ){
04414
04415 const cxchar *fctid = "giraffe_calculate_chebyshev_statistics";
04416
04417 cxint nlines = 0,
04418 nspectra = 0,
04419 line,
04420 spec,
04421 gl_per_spec,
04422 pix,
04423 npixels = 0;
04424
04425 cxdouble *pd_goodlines = NULL,
04426 *pd_status = NULL,
04427 *pd_x_center_pos = NULL,
04428 *pd_x_center_optm_cheb = NULL,
04429 total_goodlines = 0.0,
04430 numerator = 0.0,
04431 denominator = 0.0,
04432 rms = 0.0;
04433
04434 cpl_matrix *lngood = NULL;
04435
04436 cpl_image *goodlines = NULL,
04437 *status_img = NULL;
04438
04439
04440 if (x_pos ==NULL) { return; }
04441 if (lines_data ==NULL) { return; }
04442 if (x_center_pos ==NULL) { return; }
04443 if (x_center_optm_cheb==NULL) { return; }
04444
04445 nlines = cpl_image_get_nx(x_pos);
04446 nspectra = cpl_image_get_ny(x_pos);
04447 npixels = nspectra*nlines;
04448
04449 goodlines = cpl_image_new_double(nlines, nspectra, NULL, NULL);
04450 pd_goodlines = cpl_image_get_data_double(goodlines);
04451
04452 status_img = giraffe_imagestack_get(lines_data, LF_I_STATUS);
04453 pd_status = cpl_image_get_data_double(status_img);
04454
04455 for (pix=0; pix<npixels;pix++) {
04456 if (pd_status[pix]>0.0)
04457 pd_goodlines[pix] = 1.0;
04458 else
04459 pd_goodlines[pix] = 0.0;
04460 }
04461
04462 lngood = cpl_matrix_new(nlines,1);
04463
04464 for (line=0; line<nlines; line++) {
04465 gl_per_spec = 0.0;
04466 for (spec=0; spec<nspectra; spec++) {
04467 if (pd_goodlines[spec*nlines+line] > 0.5)
04468 gl_per_spec += 1.0;
04469 }
04470 cpl_matrix_set(lngood, line, 0, gl_per_spec);
04471 }
04472
04473 for (line=0;line<nlines;line++)
04474 total_goodlines += cpl_matrix_get(lngood, line, 0);
04475
04476 pd_x_center_pos = cpl_image_get_data_double(x_center_pos);
04477 pd_x_center_optm_cheb = cpl_image_get_data_double(x_center_optm_cheb);
04478
04479 for (pix=0; pix<npixels; pix++) {
04480 if (pd_goodlines[pix]>0.5) {
04481 numerator +=
04482 pow(pd_x_center_pos[pix] - pd_x_center_optm_cheb[pix], 2.0);
04483 }
04484 }
04485
04486
04487 if (total_goodlines<0.5)
04488 denominator = 1.0;
04489 else
04490 denominator = total_goodlines;
04491
04492 rms = pow(numerator / denominator, 0.5);
04493
04494 cpl_msg_info(
04495 fctid,
04496 "Total Wavelength Calibration Statistics : good lines %d out of %d, RMS=%12.6f",
04497 (cxint) floor(total_goodlines),
04498 npixels,
04499 rms
04500 );
04501
04502 cpl_matrix_delete(lngood);
04503 cpl_image_delete(goodlines);
04504
04505 }
04506
04507
04524 static void
04525 giraffe_calculate_statistics_entire_fit(
04526 GiImage *x_opt_mod_resids,
04527 GiImage *x_ref_wlens,
04528 cpl_image *fitted_status,
04529 GiImageStack *lines_data,
04530 cpl_image *fitted_x_wlen
04531 ) {
04532
04533 cpl_image *x_pos_cheb_corr = NULL,
04534 *x_pos_cheb_delta = NULL,
04535 *xomr_transpose = NULL;
04536
04537 cxdouble *pd_x_pos_cheb_delta,
04538 *pd_fitted_status;
04539
04540 cxint pix,
04541 npixels;
04542
04543 if (x_opt_mod_resids == NULL) { return; }
04544 if (x_ref_wlens == NULL) { return; }
04545 if (fitted_status == NULL) { return; }
04546 if (lines_data == NULL) { return; }
04547 if (fitted_x_wlen == NULL) { return; }
04548
04549 xomr_transpose = giraffe_image_get(x_opt_mod_resids);
04550 cpl_image_flip_local(xomr_transpose, 1);
04551
04552
04553
04554
04555
04556 x_pos_cheb_corr =
04557 giraffe_map_wavelength_to_residuals(
04558 giraffe_image_get(x_ref_wlens),
04559 xomr_transpose
04560 );
04561
04562
04563
04564
04565
04566 x_pos_cheb_delta =
04567 cpl_image_subtract(giraffe_image_get(x_ref_wlens), x_pos_cheb_corr);
04568
04569 cpl_image_flip_local(x_pos_cheb_delta,1);
04570
04571 pd_x_pos_cheb_delta =
04572 cpl_image_get_data_double(x_pos_cheb_delta);
04573
04574
04575
04576
04577
04578 pd_fitted_status = cpl_image_get_data_double(fitted_status);
04579
04580 npixels =
04581 cpl_image_get_nx(fitted_status) *
04582 cpl_image_get_ny(fitted_status);
04583
04584 for (pix=0; pix<npixels; pix++) {
04585 if (pd_fitted_status[pix]<=0.0)
04586 pd_x_pos_cheb_delta[pix] = 0.0;
04587 }
04588
04589
04590
04591
04592
04593 giraffe_calculate_chebyshev_statistics(
04594 giraffe_image_get(x_ref_wlens),
04595 lines_data,
04596 fitted_x_wlen,
04597 x_pos_cheb_delta
04598 );
04599
04600 cpl_image_delete(x_pos_cheb_delta);
04601 cpl_image_delete(x_pos_cheb_corr);
04602
04603 }
04604
04605
04606
04642 cxint
04643 giraffe_wavelength_calibration(GiTable *result, GiExtraction *extraction,
04644 GiLocalization *localization, GiTable *grating,
04645 GiTable *slitgeo, GiTable *wavelengths,
04646 GiWcalConfig *config,
04647 GiWcalSolution *wavcoeff)
04648 {
04649
04650 const cxchar *fctid = "giraffe_wavelength_calibration";
04651
04652
04653 cxint ny = 0;
04654 cxint ext_sp_chipx = 0;
04655 cxint irefit = 0;
04656 cxint nrefit = 0;
04657 cxint status = 0;
04658
04659 cxdouble xpixsize = 0.0;
04660 cxdouble ypixsize = 0.0;
04661 cxdouble bias_sigma = 0.0;
04662 cxdouble pixel_per_mm = 0.0;
04663 cxdouble lwidth0 = 0.0;
04664 cxdouble w2fwhm = 0.0;
04665 cxdouble sep_minimum = 0.0;
04666 cxdouble saturation_level = 0.0;
04667
04668 cpl_plist *properties = NULL;
04669
04670 cpl_matrix *opt_mod_params = NULL;
04671 cpl_matrix *wlen_offset = NULL;
04672
04673 cpl_image *_extsp = NULL;
04674 cpl_image *dummy = NULL;
04675
04676 GiImage *extsp = NULL;
04677 GiImage *extsp_err = NULL;
04678 GiImage *_locy = NULL;
04679 GiImage *_locw = NULL;
04680
04681 GiGrating *grating_data = NULL;
04682
04683 GiSlitGeometry *subslitfibers = NULL;
04684
04685
04686
04687
04688
04689
04690
04691 if (result == NULL) { return 1; }
04692 if (extraction == NULL) { return 1; }
04693 if (localization == NULL) { return 1; }
04694 if (grating == NULL) { return 1; }
04695 if (slitgeo == NULL) { return 1; }
04696 if (wavelengths == NULL) { return 1; }
04697 if (config == NULL) { return 1; }
04698 if (wavcoeff == NULL) { return 1; }
04699
04700 if (extraction->spectra == NULL) { return 1; }
04701 if (extraction->error == NULL) { return 1; }
04702 if (localization->locy == NULL) { return 1; }
04703 if (localization->locw == NULL) { return 1; }
04704
04705
04706
04707
04708
04709
04710 extsp = extraction->spectra;
04711 extsp_err = extraction->error;
04712 _locy = localization->locy;
04713 _locw = localization->locw;
04714
04715 properties = giraffe_image_get_properties(extsp);
04716 _extsp = giraffe_image_get(extsp);
04717
04718
04719
04720
04721
04722
04723 if (cpl_plist_contains(properties, GIALIAS_PIXSIZX) == TRUE) {
04724 xpixsize = cpl_plist_get_double(properties, GIALIAS_PIXSIZX);
04725 }
04726 else {
04727 cpl_msg_error(fctid, "Property (%s) not found in extracted spectra "
04728 "image, aborting ...", GIALIAS_PIXSIZX);
04729 return 2;
04730 }
04731
04732
04733 if (cpl_plist_contains(properties, GIALIAS_PIXSIZY) == TRUE) {
04734 ypixsize = cpl_plist_get_double(properties, GIALIAS_PIXSIZY);
04735
04736 }
04737 else {
04738 cpl_msg_error(fctid, "Property (%s) not found in extracted spectra "
04739 "image, aborting ...", GIALIAS_PIXSIZY);
04740 return 2;
04741 }
04742
04743
04744
04745 {
04746 cxint ext_sp_chip_nx = -1, ext_sp_out_nx = -1, ext_sp_hc_nx;
04747
04748 ext_sp_hc_nx = 2048;
04749
04750 if (cpl_plist_contains(properties, GIALIAS_CHIPX) == TRUE) {
04751 ext_sp_chip_nx = cpl_plist_get_int(properties, GIALIAS_CHIPX);
04752 }
04753
04754 if (cpl_plist_contains(properties, GIALIAS_OUTX) == TRUE) {
04755 ext_sp_out_nx = cpl_plist_get_int(properties, GIALIAS_OUTX);
04756 }
04757 else {
04758 ext_sp_out_nx = ext_sp_hc_nx;
04759 }
04760
04761 if ((ext_sp_chip_nx == -1) && (ext_sp_out_nx == -1)) {
04762
04763 ext_sp_chipx = ext_sp_hc_nx;
04764 cpl_msg_warning(fctid, "Detector width FITS keywords %s and "
04765 "%s missing, using internal value of %d pixels "
04766 "instead", GIALIAS_CHIPX, GIALIAS_OUTX,
04767 ext_sp_hc_nx);
04768
04769 }
04770 else if ((ext_sp_chip_nx == -1) && (ext_sp_out_nx > -1)) {
04771
04772 ext_sp_chipx = ext_sp_out_nx;
04773 cpl_msg_warning(fctid, "Detector width FITS Keyword %s is "
04774 "missing, using %s with value %d instead",
04775 GIALIAS_CHIPX, GIALIAS_OUTX, ext_sp_out_nx);
04776
04777 if (ext_sp_chipx != ext_sp_hc_nx) {
04778 cpl_msg_warning(fctid, "Detector width read from FITS "
04779 "Keywords does not match internal value %d",
04780 ext_sp_hc_nx);
04781 }
04782
04783 }
04784 else if ((ext_sp_chip_nx > -1) && (ext_sp_out_nx == -1)) {
04785
04786
04787 ext_sp_chipx = ext_sp_chip_nx;
04788
04789 if (ext_sp_chipx != ext_sp_hc_nx) {
04790 cpl_msg_warning(fctid, "Detector width read from FITS "
04791 "Keywords does not match internal value %d",
04792 ext_sp_hc_nx);
04793 }
04794
04795 }
04796 else if ((ext_sp_chip_nx > -1) && (ext_sp_out_nx > -1)) {
04797
04798
04799 ext_sp_chipx = ext_sp_chip_nx;
04800
04801 if (ext_sp_chip_nx != ext_sp_out_nx) {
04802
04803
04804
04805
04806 ext_sp_chipx = ext_sp_out_nx;
04807
04808 cpl_msg_warning(fctid, "Detector width FITS Keyword %s "
04809 "value %d does not match keyword %s value "
04810 "%d, using %d", GIALIAS_CHIPX, ext_sp_chip_nx,
04811 GIALIAS_OUTX, ext_sp_out_nx, ext_sp_out_nx);
04812 }
04813
04814 if (ext_sp_chipx != ext_sp_hc_nx) {
04815 cpl_msg_warning(fctid, "Detector width read from FITS "
04816 "Keywords does not match internal value %d",
04817 ext_sp_hc_nx);
04818 }
04819 }
04820 }
04821
04822
04823
04824 if (cpl_plist_contains(properties, GIALIAS_BIASSIGMA) == TRUE) {
04825 bias_sigma = cpl_plist_get_double(properties, GIALIAS_BIASSIGMA);
04826 }
04827 else {
04828 cpl_msg_error(fctid, "Property (%s) not found in extracted spectra "
04829 "image, aborting ...", GIALIAS_BIASSIGMA);
04830 return 2;
04831 }
04832
04833 ny = cpl_image_get_ny(_extsp);
04834
04835 if (xpixsize > 1.0) {
04836 xpixsize /= 1000.0;
04837 }
04838
04839 if (ypixsize > 1.0) {
04840 ypixsize /= 1000.0;
04841 }
04842
04843
04844
04845
04846
04847
04848
04849
04850
04851
04852
04853 cpl_msg_info(fctid, "Retrieving Grating Information...");
04854
04855 grating_data = giraffe_grating_new();
04856
04857 status = giraffe_grating_setup(grating, extsp, grating_data);
04858
04859 if (status != 0) {
04860 cpl_msg_error(fctid, "Unable to retrieve grating data from grating "
04861 "table, aborting...");
04862 giraffe_grating_delete(grating_data);
04863 return 3;
04864 }
04865
04866
04867
04868
04869
04870
04871
04872
04873
04874
04875
04876
04877 cpl_msg_info(fctid, "Retrieving Slit Geometry Information...");
04878
04879 subslitfibers = giraffe_slitgeometry_create(slitgeo,
04880 config->fit_subslits);
04881
04882 if (subslitfibers == NULL) {
04883 cpl_msg_error(fctid, "Unable to retrieve slit geometry data from "
04884 "slit geometry table, aborting...");
04885
04886 giraffe_grating_delete(grating_data);
04887 return 4;
04888 }
04889
04890
04891
04892
04893
04894
04895
04896 cpl_msg_info(fctid, "Retrieving Reference Wavelengths Catalog...");
04897
04898 status = _giraffe_wavelength_setup(wavelengths, grating_data,
04899 config);
04900
04901 if (status != 0) {
04902 cpl_msg_error(fctid, "Unable to retrieve Reference Wavelengths "
04903 "Catalog, aborting...");
04904
04905 giraffe_grating_delete(grating_data);
04906 giraffe_slitgeometry_delete(subslitfibers);
04907 return 5;
04908 }
04909
04910
04911
04912
04913
04914
04915
04916 opt_mod_params = cpl_matrix_new(10,1);
04917
04918 cpl_matrix_set(opt_mod_params, 0, 0, abs(ny) * config->opt_direction);
04919 cpl_matrix_set(opt_mod_params, 1, 0, xpixsize);
04920 cpl_matrix_set(opt_mod_params, 2, 0, grating_data->fcoll);
04921 cpl_matrix_set(opt_mod_params, 3, 0, grating_data->gcam);
04922 cpl_matrix_set(opt_mod_params, 4, 0, grating_data->theta);
04923 cpl_matrix_set(opt_mod_params, 5, 0, grating_data->order);
04924 cpl_matrix_set(opt_mod_params, 6, 0, grating_data->space);
04925 cpl_matrix_set(opt_mod_params, 7, 0, grating_data->sdx);
04926 cpl_matrix_set(opt_mod_params, 8, 0, grating_data->sdy);
04927 cpl_matrix_set(opt_mod_params, 9, 0, grating_data->sphi);
04928
04929
04930
04931
04932
04933 nrefit = cpl_matrix_get_ncol(config->line_widths);
04934 pixel_per_mm = abs(ny) * GI_MM_TO_NM / grating_data->band;
04935 lwidth0 = abs(ny) * grating_data->wlen0 /
04936 ( grating_data->band * grating_data->resol );
04937 w2fwhm = pow(2.0 * log(2.0), 0.5);
04938 sep_minimum = 0.9;
04939
04940 saturation_level = pow(10.0,6.0);
04941
04942
04943
04944
04945
04946
04947 giraffe_table_set_properties(result, properties);
04948
04949
04950 for (irefit=0; irefit<nrefit; irefit++) {
04951
04952
04953
04954
04955
04956 GiImage *x_ref_wlens = NULL,
04957 *x_opt_mod_resids = NULL;
04958
04959 GiTable *wavelengths_copy = NULL;
04960 GiTable *x_opt_mod_resids_table = NULL;
04961
04962 cpl_matrix *lines_params = NULL,
04963 *fit_opt_mod = NULL;
04964
04965 GiImageStack *lines_data = NULL;
04966
04967 cpl_image *x_wlen = NULL,
04968 *fitted_x_wlen = NULL,
04969 *fitted_status = NULL;
04970
04971 cxbool last_refit = FALSE;
04972
04973 cxdouble line_width = 0.0;
04974
04975 cxint i = 0,
04976 ngoodlines = 0;
04977
04978 lmrq_params lf_lmrq_params;
04979
04980 GiClipParams xws_sigma_clip;
04981 GiPolyDeg xws_poly_deg;
04982
04983
04984
04985
04986
04987 last_refit = (irefit==(nrefit-1));
04988 line_width = cpl_matrix_get(config->line_widths, 0, irefit);
04989
04990 cpl_msg_info(
04991 fctid,
04992 "Performing line width iteration [%d of %d], current line "
04993 "width: %12.6f",
04994 irefit + 1,
04995 nrefit,
04996 line_width
04997 );
04998
04999 wavelengths_copy = giraffe_table_duplicate(wavelengths);
05000
05001
05002
05003
05004
05005
05006
05007
05008
05009
05010 status =
05011 giraffe_line_elimination(
05012 wavelengths_copy,
05013 pixel_per_mm,
05014 sep_minimum,
05015 config->flux_ratio,
05016 line_width
05017 );
05018
05019 if (status!=0) {
05020 cpl_msg_error(fctid, "Unable to remove 'crowded' wavelengths, "
05021 "aborting...");
05022 giraffe_table_delete(wavelengths_copy);
05023 giraffe_grating_delete(grating_data);
05024 giraffe_slitgeometry_delete(subslitfibers);
05025 cpl_matrix_delete(opt_mod_params);
05026 return 6;
05027 }
05028
05029
05030
05031
05032
05033
05034
05035
05036
05037
05038
05039
05040
05041
05042 cpl_msg_info(fctid, "Calculating position of reference lines using "
05043 "'%s' model, %d spectra and %d wavelengths",
05044 lmrq_models[config->opt_model].name,
05045 cpl_matrix_get_nrow(subslitfibers->yf),
05046 cpl_table_get_nrow(giraffe_table_get(wavelengths_copy)));
05047
05048 x_ref_wlens = giraffe_compute_pixel_abcissa_wrapper(extsp,
05049 wavelengths_copy,
05050 subslitfibers,
05051 opt_mod_params,
05052 config->opt_model);
05053
05054 if (x_ref_wlens==NULL) {
05055 cpl_msg_error(fctid, "Unable to compute position of reference "
05056 "wavelengths, aborting...");
05057 giraffe_image_delete(x_ref_wlens);
05058 giraffe_table_delete(wavelengths_copy);
05059 giraffe_grating_delete(grating_data);
05060 giraffe_slitgeometry_delete(subslitfibers);
05061 cpl_matrix_delete(opt_mod_params);
05062 return 14;
05063 }
05064
05065
05066
05067
05068
05069
05070
05071
05072
05073 if ( (config->line_model == LMRQ_PSFEXP ) ||
05074 (config->line_model == LMRQ_PSFEXP2) )
05075 {
05076
05077 lines_params = cpl_matrix_new(8,1);
05078
05079 cpl_matrix_set(
05080 lines_params,
05081 0,
05082 0,
05083 abs(ny) * grating_data->wlen0 /
05084 ( 2.0 * grating_data->band * grating_data->resol )
05085 );
05086
05087 cpl_matrix_set(lines_params, 1, 0, saturation_level);
05088 cpl_matrix_set(lines_params, 2, 0, line_width );
05089 cpl_matrix_set(lines_params, 3, 0, config->line_threshold );
05090 cpl_matrix_set(lines_params, 4, 0, config->line_offset );
05091 cpl_matrix_set(lines_params, 5, 0, (cxdouble) GIWCALLINETYPE_THARNE );
05092 cpl_matrix_set(lines_params, 6, 0, config->line_reswidratio );
05093 cpl_matrix_set(lines_params, 7, 0, config->line_widexpo );
05094
05095 } else if (config->line_model == LMRQ_GAUSSUM) {
05096
05097 lines_params = cpl_matrix_new(7,1);
05098
05099 cpl_matrix_set(
05100 lines_params,
05101 0,
05102 0,
05103 abs(ny) * grating_data->wlen0 /
05104 ( 2.0 * grating_data->band * grating_data->resol )
05105 );
05106
05107 cpl_matrix_set(lines_params, 1, 0, saturation_level );
05108 cpl_matrix_set(lines_params, 2, 0, line_width );
05109 cpl_matrix_set(lines_params, 3, 0, config->line_threshold );
05110 cpl_matrix_set(lines_params, 4, 0, config->line_offset );
05111 cpl_matrix_set(lines_params, 5, 0, (cxdouble) GIWCALLINETYPE_THARNE );
05112 cpl_matrix_set(lines_params, 6, 0, config->line_reswidratio );
05113
05114 } else {
05115
05116 cpl_msg_error(fctid, "Invalid line model, aborting ...");
05117 giraffe_image_delete(x_ref_wlens);
05118 giraffe_table_delete(wavelengths_copy);
05119 giraffe_grating_delete(grating_data);
05120 giraffe_slitgeometry_delete(subslitfibers);
05121 cpl_matrix_delete(opt_mod_params);
05122 return 7;
05123 }
05124
05125 lf_lmrq_params.imax = config->line_niter;
05126 lf_lmrq_params.tmax = config->line_ntest;
05127 lf_lmrq_params.dchsq = config->line_dchsq;
05128
05129
05130
05131
05132
05133 lines_data =
05134 giraffe_fit_lines_lmrq_wrapper(
05135 extsp,
05136 extsp_err,
05137 _locy,
05138 x_ref_wlens,
05139 lines_params,
05140 lf_lmrq_params,
05141 config->line_model
05142 );
05143
05144 giraffe_image_delete(x_ref_wlens); x_ref_wlens = NULL;
05145
05146 if (lines_data==NULL) {
05147 cpl_msg_error(fctid, "Line fitting produced empty result set, "
05148 "aborting...");
05149 cpl_matrix_delete(lines_params);
05150 giraffe_table_delete(wavelengths_copy);
05151 giraffe_grating_delete(grating_data);
05152 giraffe_slitgeometry_delete(subslitfibers);
05153 cpl_matrix_delete(opt_mod_params);
05154 return 8;
05155
05156 }
05157
05158
05159
05160
05161
05162 status =
05163 giraffe_update_wavelengths(
05164 lines_data,
05165 grating_data,
05166 wavelengths_copy
05167 );
05168
05169 if (status!=0) {
05170 cpl_msg_error(
05171 fctid,
05172 "Could not update wavelength information, aborting..."
05173 );
05174 giraffe_imagestack_delete(lines_data);
05175 cpl_matrix_delete(lines_params);
05176 giraffe_table_delete(wavelengths_copy);
05177 giraffe_grating_delete(grating_data);
05178 giraffe_slitgeometry_delete(subslitfibers);
05179 cpl_matrix_delete(opt_mod_params);
05180 return 9;
05181
05182 }
05183
05184 if (last_refit==TRUE) {
05185 fitted_status =
05186 cpl_image_duplicate(
05187 giraffe_imagestack_get(lines_data, LF_I_STATUS)
05188 );
05189 }
05190
05191
05192
05193
05194
05195 ngoodlines = giraffe_goodlines_count(lines_data);
05196
05197 if (ngoodlines==0) {
05198 cpl_image_delete(fitted_status);
05199 cpl_msg_error(fctid, "No good lines found, aborting...");
05200 giraffe_imagestack_delete(lines_data);
05201 cpl_matrix_delete(lines_params);
05202 giraffe_table_delete(wavelengths_copy);
05203 giraffe_grating_delete(grating_data);
05204 giraffe_slitgeometry_delete(subslitfibers);
05205 cpl_matrix_delete(opt_mod_params);
05206 return 8;
05207 }
05208
05209
05210
05211
05212
05213 {
05214 GiImage *psf_widths = NULL;
05215 GiTable *psf_widths_table = NULL;
05216 GiClipParams pxw_sigma_clip;
05217 GiPolyDeg pxw_poly_deg;
05218
05219 psf_widths = giraffe_image_new(CPL_TYPE_DOUBLE);
05220 psf_widths_table = giraffe_table_new();
05221
05222 pxw_sigma_clip.sigma = config->pxw_clip_level;
05223 pxw_sigma_clip.niter = config->pxw_clip_niter;
05224 pxw_sigma_clip.mfrac = config->pxw_clip_mfrac;
05225
05226 pxw_poly_deg.xdeg = config->pxw_poly_x_deg;
05227 pxw_poly_deg.ydeg = config->pxw_poly_y_deg;
05228 pxw_poly_deg.ncoeffs = (pxw_poly_deg.xdeg+1)*(pxw_poly_deg.ydeg+1);
05229
05230
05231
05232
05233
05234
05235
05236
05237 status =
05238 giraffe_fit_psf_x_width_wrapper(
05239 _locy,
05240 _locw,
05241 lines_data,
05242 subslitfibers,
05243 pxw_sigma_clip,
05244 pxw_poly_deg,
05245 psf_widths,
05246 psf_widths_table,
05247 config->line_model
05248 );
05249
05250 if (status!=0) {
05251 cpl_msg_error(fctid, "PSF Fitting failed, aborting...");
05252 cpl_image_delete(fitted_status);
05253 giraffe_image_delete(psf_widths);
05254 giraffe_table_delete(psf_widths_table);
05255 giraffe_imagestack_delete(lines_data);
05256 cpl_matrix_delete(lines_params);
05257 giraffe_table_delete(wavelengths_copy);
05258 giraffe_grating_delete(grating_data);
05259 giraffe_slitgeometry_delete(subslitfibers);
05260 cpl_matrix_delete(opt_mod_params);
05261 return 10;
05262 }
05263
05264 giraffe_table_delete(psf_widths_table);
05265 giraffe_image_delete(psf_widths);
05266 }
05267
05268
05269
05270
05271
05272 if (config->opt_solution==TRUE) {
05273
05274 cpl_matrix *opt_mod_fit_flags = NULL,
05275 *params_result = NULL;
05276
05277 lmrq_params os_lmrq_params;
05278
05279 cxint nfitparams = 0;
05280
05281
05282
05283
05284
05285 os_lmrq_params.imax = config->opt_mod_niter;
05286 os_lmrq_params.tmax = config->opt_mod_ntest;
05287 os_lmrq_params.dchsq = config->opt_mod_dchsq;
05288
05289 opt_mod_fit_flags = cpl_matrix_new(10, 1);
05290
05291 cpl_matrix_set(opt_mod_fit_flags, 0, 0, 0.0);
05292 cpl_matrix_set(opt_mod_fit_flags, 1, 0, 0.0);
05293 cpl_matrix_set(opt_mod_fit_flags, 2, 0, 0.0);
05294 cpl_matrix_set(opt_mod_fit_flags, 3, 0, 0.0);
05295 cpl_matrix_set(opt_mod_fit_flags, 4, 0, 0.0);
05296 cpl_matrix_set(opt_mod_fit_flags, 5, 0, 0.0);
05297 cpl_matrix_set(opt_mod_fit_flags, 6, 0, 0.0);
05298 cpl_matrix_set(opt_mod_fit_flags, 7, 0, 1.0);
05299 cpl_matrix_set(opt_mod_fit_flags, 8, 0, 1.0);
05300 cpl_matrix_set(opt_mod_fit_flags, 9, 0, 1.0);
05301
05302 nfitparams = cpl_matrix_get_nrow(opt_mod_fit_flags);
05303 params_result = cpl_matrix_new(1,1);
05304
05305
05306
05307
05308
05309 status = giraffe_fit_opt_mod_wrapper(lines_data, wavelengths_copy,
05310 subslitfibers, opt_mod_params,
05311 opt_mod_fit_flags,
05312 &os_lmrq_params,
05313 config->opt_model,
05314 params_result);
05315
05316 if (status!=0) {
05317 cpl_msg_error(fctid, "Unable to perform optical model fit, "
05318 "aborting...");
05319 cpl_image_delete(fitted_status);
05320 cpl_matrix_delete(params_result);
05321 cpl_matrix_delete(opt_mod_fit_flags);
05322 giraffe_imagestack_delete(lines_data);
05323 cpl_matrix_delete(lines_params);
05324 giraffe_table_delete(wavelengths_copy);
05325 giraffe_grating_delete(grating_data);
05326 giraffe_slitgeometry_delete(subslitfibers);
05327 cpl_matrix_delete(opt_mod_params);
05328 return 11;
05329 }
05330
05331
05332
05333
05334
05335
05336
05337 cpl_matrix_resize(opt_mod_params, nfitparams, 1);
05338
05339 for (i=0; i<nfitparams; i++) {
05340 cpl_matrix_set(
05341 opt_mod_params,
05342 i,
05343 0,
05344 cpl_matrix_get(params_result, i, 0)
05345 );
05346 }
05347
05348
05349
05350
05351
05352 grating_data->fcoll = cpl_matrix_get(opt_mod_params, 2, 0);
05353 grating_data->gcam = cpl_matrix_get(opt_mod_params, 3, 0);
05354 grating_data->theta = cpl_matrix_get(opt_mod_params, 4, 0);
05355 grating_data->order = cpl_matrix_get(opt_mod_params, 5, 0);
05356 grating_data->space = cpl_matrix_get(opt_mod_params, 6, 0);
05357 grating_data->sdx = cpl_matrix_get(opt_mod_params, 7, 0);
05358 grating_data->sdy = cpl_matrix_get(opt_mod_params, 8, 0);
05359 grating_data->sphi = cpl_matrix_get(opt_mod_params, 9, 0);
05360
05361 cpl_msg_info(
05362 fctid,
05363 "Fitted Slit Parameters : new dx,dy,dphi="
05364 "%12.6f,%12.6f,%12.6f",
05365 cpl_matrix_get(opt_mod_params, 7, 0),
05366 cpl_matrix_get(opt_mod_params, 8, 0),
05367 cpl_matrix_get(opt_mod_params, 9, 0)
05368 );
05369
05370 cpl_matrix_delete(opt_mod_fit_flags); opt_mod_fit_flags = NULL;
05371 cpl_matrix_delete(params_result); params_result = NULL;
05372
05373
05374
05375
05376
05377
05378
05379 cpl_matrix_set(opt_mod_params, 0, 0, abs(ny) * config->opt_direction);
05380 cpl_matrix_set(opt_mod_params, 1, 0, xpixsize);
05381
05382 }
05383
05384
05385
05386
05387
05388
05389
05390
05391
05392
05393
05394 cpl_msg_debug(
05395 fctid,
05396 "Computing corrected X Coordinates based on current "
05397 "optical model"
05398 );
05399
05400 x_ref_wlens = giraffe_compute_pixel_abcissa_wrapper(extsp,
05401 wavelengths_copy,
05402 subslitfibers,
05403 opt_mod_params,
05404 config->opt_model);
05405
05406 if (x_ref_wlens==NULL) {
05407 cpl_msg_error(fctid, "Unable to compute position of reference "
05408 "wavelengths, aborting...");
05409 giraffe_image_delete(x_ref_wlens);
05410 cpl_image_delete(fitted_status);
05411 giraffe_imagestack_delete(lines_data);
05412 cpl_matrix_delete(lines_params);
05413 giraffe_table_delete(wavelengths_copy);
05414 giraffe_grating_delete(grating_data);
05415 giraffe_slitgeometry_delete(subslitfibers);
05416 cpl_matrix_delete(opt_mod_params);
05417 return 14;
05418 }
05419
05420
05421
05422
05423
05424 if (last_refit==TRUE) {
05425 if ( (config->line_model == LMRQ_PSFEXP ) ||
05426 (config->line_model == LMRQ_PSFEXP2) )
05427 {
05428 fitted_x_wlen =
05429 cpl_image_duplicate(
05430 giraffe_imagestack_get(lines_data, LF_O_PARAMS + LF_E_CENTER)
05431 );
05432 } else if (config->line_model == LMRQ_GAUSSUM) {
05433 fitted_x_wlen =
05434 cpl_image_duplicate(
05435 giraffe_imagestack_get(lines_data, LF_O_PARAMS + LF_G_CENTER)
05436 );
05437 }
05438 }
05439
05440
05441
05442
05443
05444
05445 cpl_msg_debug(
05446 fctid,
05447 "Replacing position of ref. wavelengths with ones based on "
05448 "current optical model."
05449 );
05450
05451 dummy = giraffe_imagestack_get(lines_data, LF_I_XCCD);
05452 cpl_image_delete(dummy); dummy = NULL;
05453
05454 dummy = cpl_image_duplicate(giraffe_image_get(x_ref_wlens));
05455 cpl_image_flip_local(dummy,1);
05456
05457 giraffe_imagestack_set(
05458 lines_data,
05459 LF_I_XCCD,
05460 dummy
05461 );
05462
05463
05464
05465
05466
05467 xws_sigma_clip.sigma = config->xws_clip_level;
05468 xws_sigma_clip.mfrac = config->xws_clip_mfrac;
05469 xws_sigma_clip.niter = config->xws_clip_niter;
05470
05471 xws_poly_deg.xdeg = config->xws_poly_x_deg;
05472 xws_poly_deg.ydeg = config->xws_poly_y_deg;
05473 xws_poly_deg.ncoeffs = (xws_poly_deg.xdeg+1) * (xws_poly_deg.ydeg+1);
05474
05475 x_opt_mod_resids = giraffe_image_new(CPL_TYPE_DOUBLE);
05476
05477
05478
05479
05480
05481
05482
05483 x_opt_mod_resids_table = result;
05484
05485 status =
05486 giraffe_fit_x_optm_residuals_wrapper(
05487 _locy,
05488 _locw,
05489 lines_data,
05490 subslitfibers,
05491 xws_sigma_clip,
05492 xws_poly_deg,
05493 wavcoeff,
05494 x_opt_mod_resids,
05495 x_opt_mod_resids_table,
05496 config,
05497 grating_data,
05498 line_width
05499 );
05500
05501 if (status!=0) {
05502 cpl_msg_error(fctid, "Unable to fit coefficients of the "
05503 "wavelength solution, aborting...");
05504 cpl_image_delete(fitted_status);
05505 giraffe_image_delete(x_opt_mod_resids);
05506 cpl_image_delete(fitted_x_wlen);
05507 giraffe_image_delete(x_ref_wlens);
05508 cpl_matrix_delete(fit_opt_mod);
05509 giraffe_imagestack_delete(lines_data);
05510 cpl_matrix_delete(lines_params);
05511 giraffe_table_delete(wavelengths_copy);
05512 giraffe_grating_delete(grating_data);
05513 giraffe_slitgeometry_delete(subslitfibers);
05514 cpl_matrix_delete(opt_mod_params);
05515 return 12;
05516 }
05517
05518
05519
05520
05521
05522 if (last_refit==TRUE) {
05523
05524
05525
05526
05527
05528
05529
05530 wavcoeff->subslitfit = config->fit_subslits;
05531 wavcoeff->opt_mod = config->opt_model;
05532 wavcoeff->opt_mod_params = NULL;
05533
05534 if (wavcoeff->opt_mod==LMRQ_XOPTMOD) {
05535
05536 wavcoeff->opt_mod_params = cpl_matrix_new(4,1);
05537 cpl_matrix_set(wavcoeff->opt_mod_params, 0, 0,
05538 config->opt_direction);
05539 cpl_matrix_set(wavcoeff->opt_mod_params, 1, 0,
05540 grating_data->fcoll);
05541 cpl_matrix_set(wavcoeff->opt_mod_params, 2, 0,
05542 grating_data->gcam);
05543 cpl_matrix_set(wavcoeff->opt_mod_params, 3, 0,
05544 grating_data->theta);
05545
05546
05547 } else if (wavcoeff->opt_mod==LMRQ_XOPTMOD2) {
05548
05549 wavcoeff->opt_mod_params = cpl_matrix_new(7,1);
05550 cpl_matrix_set(wavcoeff->opt_mod_params, 0, 0,
05551 config->opt_direction);
05552 cpl_matrix_set(wavcoeff->opt_mod_params, 1, 0,
05553 grating_data->fcoll);
05554 cpl_matrix_set(wavcoeff->opt_mod_params, 2, 0,
05555 grating_data->gcam);
05556 cpl_matrix_set(wavcoeff->opt_mod_params, 3, 0,
05557 grating_data->theta);
05558 cpl_matrix_set(wavcoeff->opt_mod_params, 4, 0,
05559 grating_data->sdx);
05560 cpl_matrix_set(wavcoeff->opt_mod_params, 5, 0,
05561 grating_data->sdy);
05562 cpl_matrix_set(wavcoeff->opt_mod_params, 6, 0,
05563 grating_data->sphi);
05564
05565 }
05566
05567 }
05568
05569
05570
05571
05572
05573
05574 if (last_refit==TRUE) {
05575 giraffe_calculate_statistics_entire_fit(
05576 x_opt_mod_resids,
05577 x_ref_wlens,
05578 fitted_status,
05579 lines_data,
05580 fitted_x_wlen
05581 );
05582 }
05583
05584 cpl_image_delete(fitted_status);
05585 giraffe_image_delete(x_opt_mod_resids);
05586 cpl_image_delete(fitted_x_wlen);
05587 cpl_image_delete(x_wlen);
05588 cpl_matrix_delete(fit_opt_mod);
05589 giraffe_imagestack_delete(lines_data);
05590 cpl_matrix_delete(lines_params);
05591 giraffe_table_delete(wavelengths_copy);
05592 giraffe_image_delete(x_ref_wlens);
05593
05594 }
05595
05596
05597
05598
05599
05600
05601 properties = giraffe_table_get_properties(result);
05602
05603 cpl_plist_erase(properties, "NAXIS1");
05604 cpl_plist_erase(properties, "NAXIS2");
05605
05606
05607
05608
05609
05610
05611 cpl_matrix_delete(wlen_offset);
05612 giraffe_grating_delete(grating_data);
05613 giraffe_slitgeometry_delete(subslitfibers);
05614 cpl_matrix_delete(opt_mod_params);
05615
05616 return 0;
05617
05618 }
05619
05620
05633 void
05634 giraffe_wavecalibration_config_add(cpl_parlist *list)
05635 {
05636
05637 cpl_parameter *p;
05638
05639 if (!list) {
05640 return;
05641 }
05642
05643
05644 p = cpl_parameter_value_new("giraffe.wcal.linewidth",
05645 CPL_TYPE_STRING,
05646 "Line widths for Line Detection Fit and "
05647 "Search Window, multiple widths allowed e.g. "
05648 "'60.0,40.0,15.0'",
05649 "giraffe.wcal",
05650 "15.0");
05651 cpl_parameter_set_alias(p, "wcal-lnwidth", NULL, NULL);
05652 cpl_parlist_append(list, p);
05653
05654
05655 p = cpl_parameter_value_new("giraffe.wcal.linefluxrate",
05656 CPL_TYPE_DOUBLE,
05657 "Only lines with neighbours having "
05658 "relative intensity < 1.0 / linefluxrate are "
05659 "accepted",
05660 "giraffe.wcal",
05661 50.0);
05662
05663 cpl_parameter_set_alias(p, "wcal-lnflux", NULL, NULL);
05664 cpl_parlist_append(list, p);
05665
05666
05667 p = cpl_parameter_value_new("giraffe.wcal.linebright",
05668 CPL_TYPE_STRING,
05669 "Line brightness criterium: if integer "
05670 "select N brightest lines, if float select "
05671 "lines with nominal intensity > N",
05672 "giraffe.wcal",
05673 "80");
05674
05675 cpl_parameter_set_alias(p, "wcal-lnbright", NULL, NULL);
05676 cpl_parlist_append(list, p);
05677
05678
05679 p = cpl_parameter_value_new("giraffe.wcal.linethresh",
05680 CPL_TYPE_DOUBLE,
05681 "Line detection threshold during the "
05682 "line fitting (multiple of bias sigma)",
05683 "giraffe.wcal",
05684 1.0);
05685
05686 cpl_parameter_set_alias(p, "wcal-lnthresh", NULL, NULL);
05687 cpl_parlist_append(list, p);
05688
05689
05690 p = cpl_parameter_value_new("giraffe.wcal.lineoffset",
05691 CPL_TYPE_DOUBLE,
05692 "Accepted difference: position of "
05693 "(raw maximum - fit)",
05694 "giraffe.wcal",
05695 10.0);
05696
05697 cpl_parameter_set_alias(p, "wcal-lnoffset", NULL, NULL);
05698 cpl_parlist_append(list, p);
05699
05700
05701 p = cpl_parameter_value_new("giraffe.wcal.lineniter",
05702 CPL_TYPE_INT,
05703 "Line Detection Fit: Maximum number of "
05704 "iterations",
05705 "giraffe.wcal",
05706 50);
05707
05708 cpl_parameter_set_alias(p, "wcal-lnniter", NULL, NULL);
05709 cpl_parlist_append(list, p);
05710
05711
05712 p = cpl_parameter_value_new("giraffe.wcal.linentest",
05713 CPL_TYPE_INT,
05714 "Line Detection Fit: Maximum number of "
05715 "tests",
05716 "giraffe.wcal",
05717 7);
05718
05719 cpl_parameter_set_alias(p, "wcal-lnntest", NULL, NULL);
05720 cpl_parlist_append(list, p);
05721
05722
05723 p = cpl_parameter_value_new("giraffe.wcal.linedchisq",
05724 CPL_TYPE_DOUBLE,
05725 "Line Detection Fit: Maximum chisq "
05726 "difference for test",
05727 "giraffe.wcal",
05728 0.0001);
05729
05730 cpl_parameter_set_alias(p, "wcal-lndchisq", NULL, NULL);
05731 cpl_parlist_append(list, p);
05732
05733
05734 p = cpl_parameter_enum_new("giraffe.wcal.linemodel",
05735 CPL_TYPE_STRING,
05736 "Line Detection Fit: Line profile model",
05737 "giraffe.wcal",
05738 "psfexp", 3, "psfexp", "psfexp2", "gausssum");
05739
05740 cpl_parameter_set_alias(p, "wcal-lnmodel", NULL, NULL);
05741 cpl_parlist_append(list, p);
05742
05743
05744 p = cpl_parameter_value_new("giraffe.wcal.linereswid",
05745 CPL_TYPE_DOUBLE,
05746 "Line Detection Fit: Line Width to Resolution "
05747 "Width Conversion factor",
05748 "giraffe.wcal",
05749 0.5);
05750
05751 cpl_parameter_set_alias(p, "wcal-lnreswid", NULL, NULL);
05752 cpl_parlist_append(list, p);
05753
05754
05755 p = cpl_parameter_value_new("giraffe.wcal.lineexpwid",
05756 CPL_TYPE_DOUBLE,
05757 "Line Detection Fit: Exponential line "
05758 "profile exponent",
05759 "giraffe.wcal",
05760 3.0);
05761
05762 cpl_parameter_set_alias(p, "wcal-lnexpwid", NULL, NULL);
05763 cpl_parlist_append(list, p);
05764
05765
05766 p = cpl_parameter_value_new("giraffe.wcal.optsol",
05767 CPL_TYPE_BOOL,
05768 "Optical Model Fit: Fit optical model "
05769 "parameters",
05770 "giraffe.wcal",
05771 TRUE);
05772
05773 cpl_parameter_set_alias(p, "wcal-optsol", NULL, NULL);
05774 cpl_parlist_append(list, p);
05775
05776
05777 p = cpl_parameter_value_new("giraffe.wcal.optdir",
05778 CPL_TYPE_INT,
05779 "Optical Model Fit: Dispersion direction",
05780 "giraffe.wcal",
05781 1);
05782
05783 cpl_parameter_set_alias(p, "wcal-optdir", NULL, NULL);
05784 cpl_parlist_append(list, p);
05785
05786
05787 p = cpl_parameter_enum_new("giraffe.wcal.optmodel",
05788 CPL_TYPE_STRING,
05789 "Optical Model Fit: Optical model",
05790 "giraffe.wcal",
05791 "xoptmod2", 2, "xoptmod", "xoptmod2");
05792
05793 cpl_parameter_set_alias(p, "wcal-optmodel", NULL, NULL);
05794 cpl_parlist_append(list, p);
05795
05796
05797 p = cpl_parameter_value_new("giraffe.wcal.optniter",
05798 CPL_TYPE_INT,
05799 "Optical Model Fit: Maximum number of "
05800 "iterations",
05801 "giraffe.wcal",
05802 50);
05803
05804 cpl_parameter_set_alias(p, "wcal-optniter", NULL, NULL);
05805 cpl_parlist_append(list, p);
05806
05807
05808 p = cpl_parameter_value_new("giraffe.wcal.optntest",
05809 CPL_TYPE_INT,
05810 "Optical Model Fit: Maximum number of "
05811 "tests",
05812 "giraffe.wcal",
05813 7);
05814
05815 cpl_parameter_set_alias(p, "wcal-optntest", NULL, NULL);
05816 cpl_parlist_append(list, p);
05817
05818
05819 p = cpl_parameter_value_new("giraffe.wcal.optdchisq",
05820 CPL_TYPE_DOUBLE,
05821 "Optical Model Fit: Maximum number of chisq "
05822 "difference tests",
05823 "giraffe.wcal",
05824 0.0001);
05825
05826 cpl_parameter_set_alias(p, "wcal-optdchisq", NULL, NULL);
05827 cpl_parlist_append(list, p);
05828
05829
05830 p = cpl_parameter_value_new("giraffe.wcal.subslfit",
05831 CPL_TYPE_BOOL,
05832 "Optical Model Fit: Use subslit geometry "
05833 "'true' or whole slit 'false'",
05834 "giraffe.wcal",
05835 FALSE);
05836
05837 cpl_parameter_set_alias(p, "wcal-ssfit", NULL, NULL);
05838 cpl_parlist_append(list, p);
05839
05840
05841 p = cpl_parameter_value_new("giraffe.wcal.xwsigma",
05842 CPL_TYPE_DOUBLE,
05843 "PSF Width Fitting: Sigma Clipping: Maximum "
05844 "multiple of sigma",
05845 "giraffe.wcal",
05846 2.5);
05847
05848 cpl_parameter_set_alias(p, "wcal-xwsigma", NULL, NULL);
05849 cpl_parlist_append(list, p);
05850
05851
05852 p = cpl_parameter_value_new("giraffe.wcal.xwniter",
05853 CPL_TYPE_INT,
05854 "PSF Width Fitting: Sigma Clipping: Maximum "
05855 "number of iterations",
05856 "giraffe.wcal",
05857 10);
05858
05859 cpl_parameter_set_alias(p, "wcal-xwniter", NULL, NULL);
05860 cpl_parlist_append(list, p);
05861
05862
05863 p = cpl_parameter_value_new("giraffe.wcal.xwmfrac",
05864 CPL_TYPE_DOUBLE,
05865 "PSF Width Fitting: Sigma Clipping: Minimum "
05866 "fraction of points accepted/total "
05867 "[0.0...1.0]",
05868 "giraffe.wcal",
05869 0.9);
05870
05871 cpl_parameter_set_alias(p, "wcal-xwmfrac", NULL, NULL);
05872 cpl_parlist_append(list, p);
05873
05874
05875 p = cpl_parameter_value_new("giraffe.wcal.xworder",
05876 CPL_TYPE_STRING,
05877 "PSF Width Fitting: X and Y polynomial order "
05878 "for x-width chebyshev fit",
05879 "giraffe.wcal",
05880 "2,2");
05881
05882 cpl_parameter_set_alias(p, "wcal-xworder", NULL, NULL);
05883 cpl_parlist_append(list, p);
05884
05885
05886 p = cpl_parameter_value_new("giraffe.wcal.wssigma",
05887 CPL_TYPE_DOUBLE,
05888 "Chebyshev Correction Fit: Sigma Clipping: "
05889 "Maximum multiple of sigma",
05890 "giraffe.wcal",
05891 200.0);
05892
05893 cpl_parameter_set_alias(p, "wcal-wssigma", NULL, NULL);
05894 cpl_parlist_append(list, p);
05895
05896
05897 p = cpl_parameter_value_new("giraffe.wcal.wsniter",
05898 CPL_TYPE_INT,
05899 "Chebyshev Correction Fit: Sigma Clipping: "
05900 "Maximum number of iterations",
05901 "giraffe.wcal",
05902 10);
05903
05904 cpl_parameter_set_alias(p, "wcal-wsniter", NULL, NULL);
05905 cpl_parlist_append(list, p);
05906
05907
05908 p = cpl_parameter_value_new("giraffe.wcal.wsmfrac",
05909 CPL_TYPE_DOUBLE,
05910 "Chebyshev Correction Fit: Sigma Clipping: "
05911 "Minimum fraction of points accepted/total "
05912 "[0.0...1.0]",
05913 "giraffe.wcal",
05914 0.9);
05915
05916 cpl_parameter_set_alias(p, "wcal-wsmfrac", NULL, NULL);
05917 cpl_parlist_append(list, p);
05918
05919
05920 p = cpl_parameter_value_new("giraffe.wcal.wsorder",
05921 CPL_TYPE_STRING,
05922 "Chebyshev Correction Fit: X and Y polynomial "
05923 "order wavelength chebyshev correction",
05924 "giraffe.wcal",
05925 "6,4");
05926
05927 cpl_parameter_set_alias(p, "wcal-wsorder", NULL, NULL);
05928 cpl_parlist_append(list, p);
05929
05930
05931 p = cpl_parameter_value_new("giraffe.wcal.lwlen",
05932 CPL_TYPE_STRING,
05933 "Line Detection Fit: (minimum,maximum) "
05934 "wavelength to use during fit [nm]",
05935 "giraffe.wcal",
05936 "0.0,0.0");
05937
05938 cpl_parameter_set_alias(p, "wcal-wlrange", NULL, NULL);
05939 cpl_parlist_append(list, p);
05940
05941 return;
05942
05943 }
05944
05958 GiWcalConfig*
05959 giraffe_wavecalibration_config_create(cpl_parlist *list)
05960 {
05961
05962 const cxchar *fctid = "giraffe_wcal_config_create";
05963
05964 const cxchar *delim1 = ",";
05965
05966 cxchar *tmp_ref_value = NULL;
05967 cxchar **widths = NULL;
05968
05969 cxint i;
05970 cxint scanlen;
05971 cxint count = 0;
05972
05973 cxbool f_error = FALSE;
05974 cxbool f_params_invalid = FALSE;
05975 cxbool f_dot_found = FALSE;
05976
05977
05978 cpl_parameter *p = NULL;
05979
05980 GiWcalConfig *config = NULL;
05981
05982
05983 if (!list) {
05984 return NULL;
05985 }
05986
05987 config = cx_calloc(1, sizeof *config);
05988
05989
05990
05991
05992
05993
05994 config->line_widths = NULL;
05995 config->flux_ratio = 0.0;
05996 config->bright_threshold = CX_MAXDOUBLE;
05997 config->bright_count = CX_MAXINT;
05998 config->line_threshold = 0.0;
05999 config->line_offset = 0.0;
06000 config->line_niter = 0;
06001 config->line_ntest = 0;
06002 config->line_model = LMRQ_UNDEFINED;
06003 config->line_dchsq = 0.0;
06004 config->line_reswidratio = 0.0;
06005 config->line_widexpo = 0.0;
06006 config->opt_solution = TRUE;
06007 config->opt_direction = 0;
06008 config->opt_model = LMRQ_UNDEFINED;
06009 config->fit_subslits = FALSE;
06010 config->opt_mod_niter = 0;
06011 config->opt_mod_ntest = 0;
06012 config->opt_mod_dchsq = 0.0;
06013 config->xws_clip_level = 0.0;
06014 config->xws_clip_niter = 0;
06015 config->xws_clip_mfrac = 0.0;
06016 config->pxw_clip_level = 0.0;
06017 config->pxw_clip_niter = 0;
06018 config->pxw_clip_mfrac = 0.0;
06019 config->pxw_poly_x_deg = 0;
06020 config->pxw_poly_y_deg = 0;
06021 config->xws_poly_x_deg = 0;
06022 config->xws_poly_y_deg = 0;
06023 config->range_wlen_min = 0.0;
06024 config->range_wlen_max = 0.0;
06025
06026
06027
06028
06029
06030 p = cpl_parlist_find(list, "giraffe.wcal.linewidth");
06031 tmp_ref_value = cpl_parameter_get_string(p);
06032
06033 if (tmp_ref_value) {
06034
06035 cxint count = 0;
06036 cxint scanlen = 0;
06037 cxint i;
06038 cxdouble tmp_width;
06039
06040 widths = cx_strsplit(tmp_ref_value, ",", 255);
06041
06042 while (widths[count]!=NULL && count<255) {
06043 count++;
06044 }
06045
06046 config->line_widths = cpl_matrix_new(1, count);
06047
06048 for (i=0; i<count; i++) {
06049 scanlen = sscanf(widths[i], " %le ", &(tmp_width));
06050 cpl_matrix_set(config->line_widths, 0, i, tmp_width);
06051 if (scanlen!=1)
06052 f_error = TRUE;
06053 }
06054
06055 if (f_error==TRUE) {
06056 cpl_matrix_delete(config->line_widths); config->line_widths = NULL;
06057 }
06058
06059 cx_strfreev(widths); widths = NULL;
06060
06061 }
06062
06063 p = cpl_parlist_find(list, "giraffe.wcal.linefluxrate");
06064 config->flux_ratio = cpl_parameter_get_double(p);
06065
06066 p = cpl_parlist_find(list, "giraffe.wcal.linebright");
06067 tmp_ref_value = cpl_parameter_get_string(p);
06068
06069 for (i=0; i<(cxint)strlen(tmp_ref_value); i++) {
06070 if (tmp_ref_value[i]=='.')
06071 f_dot_found = TRUE;
06072 }
06073
06074 if (f_dot_found==TRUE) {
06075 scanlen = sscanf(tmp_ref_value, " %le ", &config->bright_threshold);
06076 } else {
06077 scanlen = sscanf(tmp_ref_value, " %d ", &config->bright_count);
06078 }
06079
06080 p = cpl_parlist_find(list, "giraffe.wcal.linethresh");
06081 config->line_threshold = cpl_parameter_get_double(p);
06082
06083 p = cpl_parlist_find(list, "giraffe.wcal.lineoffset");
06084 config->line_offset = cpl_parameter_get_double(p);
06085
06086 p = cpl_parlist_find(list, "giraffe.wcal.lineniter");
06087 config->line_niter = cpl_parameter_get_int(p);
06088
06089 p = cpl_parlist_find(list, "giraffe.wcal.linentest");
06090 config->line_ntest = cpl_parameter_get_int(p);
06091
06092 p = cpl_parlist_find(list, "giraffe.wcal.linemodel");
06093 tmp_ref_value = cpl_parameter_get_string(p);
06094
06095 if (strcmp(tmp_ref_value, "psfexp")==0) {
06096 config->line_model = LMRQ_PSFEXP;
06097 }
06098 if (strcmp(tmp_ref_value, "psfexp2")==0) {
06099 config->line_model = LMRQ_PSFEXP2;
06100 }
06101 if (strcmp(tmp_ref_value, "gausssum")==0) {
06102 config->line_model = LMRQ_GAUSSUM;
06103 }
06104
06105 p = cpl_parlist_find(list, "giraffe.wcal.linedchisq");
06106 config->line_dchsq = cpl_parameter_get_double(p);
06107
06108 p = cpl_parlist_find(list, "giraffe.wcal.linereswid");
06109 config->line_reswidratio = cpl_parameter_get_double(p);
06110
06111 p = cpl_parlist_find(list, "giraffe.wcal.lineexpwid");
06112 config->line_widexpo = cpl_parameter_get_double(p);
06113
06114 p = cpl_parlist_find(list, "giraffe.wcal.optsol");
06115 config->opt_solution = cpl_parameter_get_bool(p);
06116
06117 p = cpl_parlist_find(list, "giraffe.wcal.optdir");
06118 config->opt_direction = cpl_parameter_get_int(p);
06119
06120 p = cpl_parlist_find(list, "giraffe.wcal.optmodel");
06121 tmp_ref_value = cpl_parameter_get_string(p);
06122
06123 if (strcmp(tmp_ref_value, "xoptmod")==0) {
06124 config->opt_model = LMRQ_XOPTMOD;
06125 }
06126 if (strcmp(tmp_ref_value, "xoptmod2")==0) {
06127 config->opt_model = LMRQ_XOPTMOD2;
06128 }
06129
06130 p = cpl_parlist_find(list, "giraffe.wcal.subslfit");
06131 config->fit_subslits = cpl_parameter_get_bool(p);
06132
06133 p = cpl_parlist_find(list, "giraffe.wcal.optniter");
06134 config->opt_mod_niter = cpl_parameter_get_int(p);
06135
06136 p = cpl_parlist_find(list, "giraffe.wcal.optntest");
06137 config->opt_mod_ntest = cpl_parameter_get_int(p);
06138
06139 p = cpl_parlist_find(list, "giraffe.wcal.optdchisq");
06140 config->opt_mod_dchsq = cpl_parameter_get_double(p);
06141
06142 p = cpl_parlist_find(list, "giraffe.wcal.wssigma");
06143 config->xws_clip_level = cpl_parameter_get_double(p);
06144
06145 p = cpl_parlist_find(list, "giraffe.wcal.wsniter");
06146 config->xws_clip_niter = cpl_parameter_get_int(p);
06147
06148 p = cpl_parlist_find(list, "giraffe.wcal.wsmfrac");
06149 config->xws_clip_mfrac = cpl_parameter_get_double(p);
06150
06151 p = cpl_parlist_find(list, "giraffe.wcal.xwsigma");
06152 config->pxw_clip_level = cpl_parameter_get_double(p);
06153
06154 p = cpl_parlist_find(list, "giraffe.wcal.xwniter");
06155 config->pxw_clip_niter = cpl_parameter_get_int(p);
06156
06157 p = cpl_parlist_find(list, "giraffe.wcal.xwmfrac");
06158 config->pxw_clip_mfrac = cpl_parameter_get_double(p);
06159
06160 p = cpl_parlist_find(list, "giraffe.wcal.xworder");
06161 tmp_ref_value = cpl_parameter_get_string(p);
06162
06163 count = 0;
06164 scanlen = 0;
06165 widths = cx_strsplit(tmp_ref_value, delim1, 255);
06166
06167 while (widths[count]!=NULL && count<255) {
06168 count++;
06169 }
06170
06171 if (count==2) {
06172 scanlen = sscanf(widths[0], " %d ", &(config->pxw_poly_x_deg));
06173 scanlen = sscanf(widths[1], " %d ", &(config->pxw_poly_y_deg));
06174 }
06175
06176 cx_strfreev(widths); widths = NULL;
06177
06178 p = cpl_parlist_find(list, "giraffe.wcal.wsorder");
06179 tmp_ref_value = cpl_parameter_get_string(p);
06180
06181 count = 0;
06182 scanlen = 0;
06183 widths = cx_strsplit(tmp_ref_value, delim1, 255);
06184
06185 while (widths[count]!=NULL && count<255) {
06186 count++;
06187 }
06188
06189 if (count==2) {
06190 scanlen = sscanf(widths[0], " %d ", &(config->xws_poly_x_deg));
06191 scanlen = sscanf(widths[1], " %d ", &(config->xws_poly_y_deg));
06192 }
06193
06194 cx_strfreev(widths); widths = NULL;
06195
06196 p = cpl_parlist_find(list, "giraffe.wcal.lwlen");
06197 tmp_ref_value = cpl_parameter_get_string(p);
06198
06199 count = 0;
06200 scanlen = 0;
06201 widths = cx_strsplit(tmp_ref_value, delim1, 255);
06202
06203 while (widths[count]!=NULL && count<255) {
06204 count++;
06205 }
06206
06207 if (count==2) {
06208 scanlen = sscanf(widths[0], " %le ", &(config->range_wlen_min));
06209 scanlen = sscanf(widths[1], " %le ", &(config->range_wlen_max));
06210 }
06211
06212 cx_strfreev(widths); widths = NULL;
06213
06214
06215
06216
06217
06218 if (cpl_matrix_get_ncol(config->line_widths)==0) {
06219 cpl_msg_error(fctid, "Invalid line widths set..." );
06220 f_params_invalid = TRUE;
06221 }
06222
06223 if ( (config->bright_threshold>=(CX_MAXDOUBLE/2.0)) &&
06224 (config->bright_count>=(CX_MAXINT/2) ) ) {
06225 cpl_msg_error(fctid, "Invalid line threshold..." );
06226 f_params_invalid = TRUE;
06227 }
06228
06229 if (config->line_model==LMRQ_UNDEFINED) {
06230 cpl_msg_error(fctid, "Invalid Levenberg Marquardt Model..." );
06231 f_params_invalid = TRUE;
06232 }
06233
06234 if ((config->opt_direction!=1)&&(config->opt_direction!=-1)) {
06235 cpl_msg_error(fctid, "Invalid Optical Model direction..." );
06236 f_params_invalid = TRUE;
06237 }
06238
06239 if (config->opt_model==LMRQ_UNDEFINED) {
06240 cpl_msg_error(fctid, "Invalid Optical Model..." );
06241 f_params_invalid = TRUE;
06242 }
06243
06244 if (f_params_invalid==TRUE) {
06245 giraffe_wavecalibration_config_destroy(config);
06246 config = NULL;
06247 }
06248
06249 return config;
06250
06251 }
06252
06267 void
06268 giraffe_wavecalibration_config_destroy(GiWcalConfig *config)
06269 {
06270
06271 if (config) {
06272
06273 if (config->line_widths)
06274 cpl_matrix_delete(config->line_widths);
06275
06276 cx_free(config);
06277 config = NULL;
06278
06279 }
06280
06281 return;
06282 }