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