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 <cxmemory.h>
00037
00038 #include <cpl_parameter.h>
00039 #include <cpl_parameterlist.h>
00040 #include <cpl_image.h>
00041 #include <cpl_msg.h>
00042
00043 #include "gimacros.h"
00044 #include "gidebug.h"
00045 #include "gierror.h"
00046 #include "gialias.h"
00047 #include "gimatrix.h"
00048 #include "gimessages.h"
00049 #include "gimath.h"
00050 #include "gimath_lm.h"
00051 #include "gifiberutils.h"
00052 #include "giutils.h"
00053 #include "girebinning.h"
00054
00055
00064 #define GIFITS_KEYWORD_MISSING_MSG "FITS KEYWORD [%s] not found!! Aborting..."
00065 #define GIWAVECAL_GRATING_WAVELENGTH_EPSILON 0.0001
00066
00067
00068 enum GiLocDataType {
00069 GILOCDATATYPE_UNDEFINED,
00070 GILOCDATATYPE_FITTED_DATA,
00071 GILOCDATATYPE_FIT_COEFFS
00072 };
00073
00074 typedef enum GiLocDataType GiLocDataType;
00075
00076
00077 struct GiGrat {
00078 cx_string *name;
00079 cx_string *filter_name;
00080 cx_string *setup_name;
00081 cx_string *slit_name;
00082 cxint order;
00083 cxdouble wlen0;
00084 cxdouble wlenmin;
00085 cxdouble wlenmax;
00086 cxdouble band;
00087 cxdouble resol;
00088 cxdouble space;
00089 cxdouble theta;
00090 cxdouble fcoll;
00091 cxdouble gcam;
00092 cxdouble slitdx;
00093 cxdouble slitdy;
00094 cxdouble slitphi;
00095 };
00096
00097 typedef struct GiGrat GiGrat;
00098
00099
00100 struct GiFiberPosition {
00101 cpl_matrix *x_fiber;
00102 cpl_matrix *y_fiber;
00103 };
00104
00105 typedef struct GiFiberPosition GiFiberPosition;
00106
00107
00108 struct GiLocPosition {
00109 cxint ydeg;
00110 cxint wdeg;
00111 GiLocDataType type;
00112 cpl_image *centroids;
00113 cpl_image *widths;
00114 };
00115
00116 typedef struct GiLocPosition GiLocPosition;
00117
00118
00119 struct GiBinnParams {
00120 cxint xdeg;
00121 cxint ydeg;
00122 };
00123
00124 typedef struct GiBinnParams GiBinnParams;
00125
00126
00127 struct GiSlitGeo {
00128 cxint nsubslits;
00129 cpl_matrix **subslits;
00130 };
00131
00132 typedef struct GiSlitGeo GiSlitGeo;
00133
00134 struct GiWcalSolution {
00135 cxbool subslitfit;
00136 lmrq_model_id opt_mod;
00137 cpl_matrix *opt_mod_params;
00138 GiSlitGeo *wav_coeffs;
00139 GiSlitGeo *wav_limits;
00140 };
00141
00142 typedef struct GiWcalSolution GiWcalSolution;
00143
00144
00145 struct GiRebinInfo {
00146 const cxchar* method;
00147 const cxchar* scale;
00148 const cxchar* range;
00149 const cxchar* units;
00150
00151 cxdouble wmin;
00152 cxdouble wcenter;
00153 cxdouble wmax;
00154 cxdouble wstep;
00155
00156 cxint offset;
00157
00158 };
00159
00160 typedef struct GiRebinInfo GiRebinInfo;
00161
00162
00163
00164
00165
00166
00167 static cxdouble ddb, dde;
00168
00169
00170 inline static cxint
00171 _giraffe_resample_update_properties(GiImage* spectra, GiRebinInfo* info)
00172 {
00173
00174 cpl_image* image = giraffe_image_get(spectra);
00175
00176 cpl_propertylist* properties = giraffe_image_get_properties(spectra);
00177
00178
00179 giraffe_error_push();
00180
00181 cpl_propertylist_update_double(properties, GIALIAS_DATAMIN,
00182 cpl_image_get_min(image));
00183 cpl_propertylist_update_double(properties, GIALIAS_DATAMAX,
00184 cpl_image_get_max(image));
00185
00186 cpl_propertylist_update_string(properties, GIALIAS_GIRFTYPE,
00187 "BINSP");
00188
00189 cpl_propertylist_update_int(properties, GIALIAS_BINWNX,
00190 cpl_image_get_size_y(image));
00191 cpl_propertylist_update_int(properties, GIALIAS_BINWNS,
00192 cpl_image_get_size_x(image));
00193
00194 cpl_propertylist_update_string(properties, GIALIAS_BUNIT,
00195 "adu");
00196
00197 cpl_propertylist_update_string(properties, GIALIAS_CTYPE1,
00198 "INDEX");
00199 cpl_propertylist_update_string(properties, GIALIAS_CUNIT1,
00200 "");
00201 cpl_propertylist_update_double(properties, GIALIAS_CRPIX1,
00202 1.);
00203 cpl_propertylist_update_double(properties, GIALIAS_CRVAL1,
00204 1.);
00205 cpl_propertylist_update_double(properties, GIALIAS_CDELT1,
00206 1.);
00207
00208 cpl_propertylist_update_string(properties, GIALIAS_CTYPE2,
00209 "AWAV");
00210 cpl_propertylist_update_string(properties, GIALIAS_CUNIT2,
00211 info->units);
00212 cpl_propertylist_update_double(properties, GIALIAS_CRPIX2,
00213 info->offset + 1);
00214 cpl_propertylist_update_double(properties, GIALIAS_CRVAL2,
00215 info->wmin);
00216 cpl_propertylist_update_double(properties, GIALIAS_CDELT2,
00217 info->wstep);
00218
00219 cpl_propertylist_update_double(properties, GIALIAS_BINWLMIN,
00220 info->wmin);
00221 cpl_propertylist_update_double(properties, GIALIAS_BINWL0,
00222 info->wcenter);
00223 cpl_propertylist_update_double(properties, GIALIAS_BINWLMAX,
00224 info->wmax);
00225 cpl_propertylist_update_double(properties, GIALIAS_BINSTEP,
00226 info->wstep);
00227 cpl_propertylist_update_string(properties, GIALIAS_BINMETHOD,
00228 info->method);
00229 cpl_propertylist_update_string(properties, GIALIAS_BINSCALE,
00230 info->scale);
00231 cpl_propertylist_update_string(properties, GIALIAS_BINRANGE,
00232 info->range);
00233
00234 if (cpl_error_get_code() != CPL_ERROR_NONE) {
00235 return 1;
00236 }
00237
00238 giraffe_error_pop();
00239
00240 return 0;
00241
00242 }
00243
00244
00245 static GiGrat*
00246 _giraffe_grating_new(void)
00247 {
00248
00249 GiGrat *grating = NULL;
00250
00251 grating = (GiGrat*) cx_calloc(1, (cxsize)sizeof(GiGrat));
00252
00253 grating->name = cx_string_create("UNKNOWN");
00254 grating->filter_name = cx_string_create("UNKNOWN");
00255 grating->setup_name = cx_string_create("UNKNOWN");
00256 grating->slit_name = cx_string_create("UNKNOWN");
00257
00258 return grating;
00259
00260 }
00261
00262
00263 static void
00264 _giraffe_grating_delete(GiGrat *grating)
00265 {
00266
00267 if (grating==NULL) { return; }
00268
00269 if (grating->name!=NULL) {
00270 cx_string_delete(grating->name);
00271 }
00272 if (grating->filter_name!=NULL) {
00273 cx_string_delete(grating->filter_name);
00274 }
00275 if (grating->setup_name!=NULL) {
00276 cx_string_delete(grating->setup_name);
00277 }
00278 if (grating->slit_name!=NULL) {
00279 cx_string_delete(grating->slit_name);
00280 }
00281 cx_free(grating);
00282
00283 }
00284
00285
00286 static cxint
00287 _giraffe_grating_setup(const GiTable *grating_table,
00288 const GiImage *grating_ass_img, GiGrat *grating_setup)
00289 {
00290
00291
00292
00293
00294
00295 const cxchar *fctid = "_giraffe_grating_setup";
00296
00297 cxdouble wlen_match = 0.0,
00298 wlen = 0.0,
00299 tmp_gratgrv = 0.0;
00300
00301 cxint32 row_match = 0,
00302 row_nulls,
00303 i = 0;
00304
00305 const cxchar *c_name_setup = "SETUP";
00306 const cxchar *c_name_order = "ORDER";
00307 const cxchar *c_name_wl0 = "WLEN0";
00308 const cxchar *c_name_wlmin = "WLMIN";
00309 const cxchar *c_name_wlmax = "WLMAX";
00310 const cxchar *c_name_band = "BAND";
00311 const cxchar *c_name_theta = "THETA";
00312 const cxchar *c_name_fcoll = "FCOLL";
00313 const cxchar *c_name_gcam = "GCAM";
00314 const cxchar *c_name_sdx = "SDX";
00315 const cxchar *c_name_sdy = "SDY";
00316 const cxchar *c_name_sdphi = "SPHI";
00317 const cxchar *c_name_rmed = "RMED";
00318 const cxchar *c_name_rifa = "RIFA";
00319
00320 cpl_propertylist *ref_plimg = NULL;
00321 cpl_table *ref_gtable = NULL;
00322 cx_string *slit_name = NULL;
00323
00324 GiInstrumentMode instrument_mode;
00325
00326
00327
00328
00329
00330
00331 if (grating_table ==NULL) { return 1; }
00332 if (grating_ass_img==NULL) { return 1; }
00333 if (grating_setup ==NULL) { return 1; }
00334
00335 if ((ref_plimg=giraffe_image_get_properties(grating_ass_img))==NULL) {
00336 return 128;
00337 }
00338
00339 if ((ref_gtable = giraffe_table_get(grating_table))==NULL) {
00340 return 128;
00341 }
00342
00343 slit_name = cx_string_new();
00344
00345
00346
00347
00348
00349
00350
00351
00352
00353 if (!cpl_propertylist_has(ref_plimg, GIALIAS_GRATWLEN)) {
00354 cpl_msg_error(fctid, GIFITS_KEYWORD_MISSING_MSG, GIALIAS_GRATWLEN);
00355 cx_string_delete(slit_name);
00356 return 2;
00357 }
00358 else {
00359 grating_setup->wlen0 = cpl_propertylist_get_double(ref_plimg,
00360 GIALIAS_GRATWLEN);
00361 }
00362
00363 if (!cpl_propertylist_has(ref_plimg, GIALIAS_GRATORDER)) {
00364 cpl_msg_error(fctid, GIFITS_KEYWORD_MISSING_MSG, GIALIAS_GRATORDER);
00365 cx_string_delete(slit_name);
00366 return 2;
00367 }
00368 else {
00369 grating_setup->order = cpl_propertylist_get_int(ref_plimg, GIALIAS_GRATORDER);
00370 }
00371
00372 if (!cpl_propertylist_has(ref_plimg, GIALIAS_SLITNAME)) {
00373
00374 cpl_msg_error(fctid, GIFITS_KEYWORD_MISSING_MSG, GIALIAS_SLITNAME);
00375 cx_string_delete(slit_name);
00376 return 2;
00377 } else {
00378 cx_string_set(slit_name,
00379 cpl_propertylist_get_string(ref_plimg, GIALIAS_SLITNAME));
00380 }
00381
00382 if (!cpl_propertylist_has(ref_plimg, GIALIAS_GRATGRV)) {
00383
00384 cpl_msg_error(fctid, GIFITS_KEYWORD_MISSING_MSG, GIALIAS_GRATGRV);
00385 cx_string_delete(slit_name);
00386 return 2;
00387 } else {
00388 tmp_gratgrv = cpl_propertylist_get_double(ref_plimg, GIALIAS_GRATGRV );
00389 }
00390
00391 if (!cpl_propertylist_has(ref_plimg, GIALIAS_GRATNAME)) {
00392 cpl_msg_error(fctid, GIFITS_KEYWORD_MISSING_MSG, GIALIAS_GRATNAME);
00393 cx_string_delete(slit_name);
00394 return 2;
00395 } else {
00396 cx_string_set(grating_setup->name,
00397 cpl_propertylist_get_string(ref_plimg, GIALIAS_GRATNAME));
00398 }
00399
00400 if (!cpl_propertylist_has(ref_plimg, GIALIAS_FILTNAME)) {
00401 cpl_msg_error(fctid, GIFITS_KEYWORD_MISSING_MSG, GIALIAS_FILTNAME);
00402 cx_string_delete(slit_name);
00403 return 2;
00404 }
00405 else {
00406 cx_string_set(grating_setup->filter_name,
00407 cpl_propertylist_get_string(ref_plimg, GIALIAS_FILTNAME));
00408 }
00409
00410
00411
00412
00413
00414
00415 for (i = 0; i < cpl_table_get_nrow(ref_gtable); i++) {
00416
00417 cxint _order = cpl_table_get_int(ref_gtable, c_name_order, i, NULL);
00418
00419 if (_order == grating_setup->order) {
00420
00421 wlen = cpl_table_get(ref_gtable, c_name_wl0, i, &row_nulls);
00422
00423 if (fabs(wlen - grating_setup->wlen0) <
00424 fabs(wlen_match - grating_setup->wlen0)) {
00425 wlen_match = wlen;
00426 row_match = i;
00427 }
00428
00429 }
00430 }
00431
00432
00433
00434
00435
00436
00437 if (fabs(wlen_match - grating_setup->wlen0) >
00438 GIWAVECAL_GRATING_WAVELENGTH_EPSILON) {
00439
00440 cpl_msg_error(fctid, "Grating setup (wavelength %.2f nm, order %d) "
00441 "not found in grating table!", grating_setup->wlen0,
00442 grating_setup->order);
00443 cx_string_delete(slit_name);
00444 return 3;
00445 }
00446 else {
00447 cpl_msg_debug(fctid, "Found wlen0 in grating table at position %d",
00448 row_match);
00449 }
00450
00451
00452
00453
00454
00455
00456 cx_string_set(grating_setup->setup_name,
00457 (cxchar*) cpl_table_get_string(ref_gtable, c_name_setup,
00458 row_match));
00459
00460 cx_string_set(grating_setup->slit_name, cx_string_get(slit_name));
00461
00462 grating_setup->wlenmin = cpl_table_get(ref_gtable, c_name_wlmin,
00463 row_match, &row_nulls);
00464
00465 grating_setup->wlenmax = cpl_table_get(ref_gtable, c_name_wlmax,
00466 row_match, &row_nulls);
00467
00468 grating_setup->band = cpl_table_get(ref_gtable, c_name_band,
00469 row_match, &row_nulls);
00470
00471 grating_setup->theta = cpl_table_get(ref_gtable, c_name_theta,
00472 row_match, &row_nulls);
00473
00474 grating_setup->space = 1.0 / fabs(GI_MM_TO_NM * tmp_gratgrv);
00475
00476
00477 instrument_mode = giraffe_get_mode(ref_plimg);
00478
00479 switch (instrument_mode) {
00480 case GIMODE_MEDUSA:
00481 grating_setup->resol = cpl_table_get(ref_gtable, c_name_rmed,
00482 row_match, &row_nulls);
00483 break;
00484
00485 case GIMODE_IFU:
00486 grating_setup->resol = cpl_table_get(ref_gtable, c_name_rifa,
00487 row_match, &row_nulls);
00488 break;
00489
00490 case GIMODE_ARGUS:
00491 grating_setup->resol = cpl_table_get(ref_gtable, c_name_rifa,
00492 row_match, &row_nulls);
00493 break;
00494
00495 default:
00496 grating_setup->resol = -1.0;
00497 break;
00498 }
00499
00500 grating_setup->fcoll =
00501 cpl_table_get(ref_gtable, c_name_fcoll, row_match, &row_nulls);
00502
00503 grating_setup->gcam =
00504 cpl_table_get(ref_gtable, c_name_gcam, row_match, &row_nulls);
00505
00506 grating_setup->slitdx =
00507 cpl_table_get(ref_gtable, c_name_sdx, row_match, &row_nulls);
00508
00509 grating_setup->slitdy =
00510 cpl_table_get(ref_gtable, c_name_sdy, row_match, &row_nulls);
00511
00512 grating_setup->slitphi =
00513 cpl_table_get(ref_gtable, c_name_sdphi, row_match, &row_nulls);
00514
00515 cx_string_delete(slit_name);
00516
00517 return 0;
00518
00519 }
00520
00521
00522 static GiFiberPosition*
00523 _giraffe_fiberposition_new(void)
00524 {
00525
00526 GiFiberPosition* tmp = NULL;
00527
00528 tmp = (GiFiberPosition*) cx_calloc(1, sizeof(GiFiberPosition));
00529
00530 tmp->x_fiber = NULL;
00531 tmp->y_fiber = NULL;
00532
00533 return tmp;
00534 }
00535
00536
00537 static void
00538 _giraffe_fiberposition_delete(GiFiberPosition *fp)
00539 {
00540
00541 if (fp != NULL) {
00542
00543 if (fp->x_fiber) {
00544 cpl_matrix_delete(fp->x_fiber);
00545 }
00546
00547 if (fp->y_fiber) {
00548 cpl_matrix_delete(fp->y_fiber);
00549 }
00550
00551 cx_free(fp);
00552
00553 }
00554
00555 return;
00556
00557 }
00558
00559
00560 static GiSlitGeo*
00561 _giraffe_slitgeo_new(void)
00562 {
00563
00564 GiSlitGeo *sgeometry = NULL;
00565
00566 sgeometry = cx_malloc(sizeof(GiSlitGeo));
00567
00568 sgeometry->subslits = NULL;
00569 sgeometry->nsubslits = 0;
00570
00571 return sgeometry;
00572
00573 }
00574
00575
00576 static void
00577 _giraffe_slitgeo_delete(GiSlitGeo *sgeometry)
00578 {
00579
00580 if (sgeometry != NULL) {
00581
00582 if (sgeometry->subslits != NULL) {
00583
00584 cxint i;
00585
00586 for (i = 0; i < sgeometry->nsubslits; i++) {
00587 cpl_matrix_delete(sgeometry->subslits[i]);
00588 }
00589
00590 cx_free(sgeometry->subslits);
00591 }
00592
00593 cx_free(sgeometry);
00594
00595 }
00596
00597 return;
00598
00599 }
00600
00601
00602 static cxint
00603 _giraffe_slitgeo_size(GiSlitGeo *sgeometry)
00604 {
00605
00606 if (sgeometry == NULL) {
00607 return -1;
00608 }
00609
00610 if (sgeometry->subslits != NULL) {
00611 return sgeometry->nsubslits;
00612 }
00613
00614 return -1;
00615
00616 }
00617
00618
00619 static void
00620 _giraffe_slitgeo_resize(GiSlitGeo *sgeometry, cxint size)
00621 {
00622
00623 if (sgeometry == NULL) {
00624 return;
00625 }
00626
00627 if (size == sgeometry->nsubslits) {
00628 return;
00629 }
00630
00631 if (sgeometry->subslits != NULL) {
00632
00633 cxint i;
00634
00635 for (i = 0; i < sgeometry->nsubslits; i++) {
00636 cpl_matrix_delete(sgeometry->subslits[i]);
00637 }
00638 }
00639
00640 cx_free(sgeometry->subslits);
00641
00642 sgeometry->nsubslits = size;
00643 sgeometry->subslits = cx_calloc(sgeometry->nsubslits, sizeof(cpl_matrix*));
00644
00645 return;
00646
00647 }
00648
00649
00650 static void
00651 _giraffe_slitgeo_create(GiSlitGeo *sgeometry, cxint idx, cxint nrow,
00652 cxint ncol)
00653 {
00654
00655 if (sgeometry == NULL) {
00656 return;
00657 }
00658
00659 if (sgeometry->subslits == NULL) {
00660 return;
00661 }
00662
00663 if ((idx < 0) || (idx > sgeometry->nsubslits)) {
00664 return;
00665 }
00666
00667 if (sgeometry->subslits[idx] != NULL) {
00668 cpl_matrix_delete(sgeometry->subslits[idx]);
00669 }
00670
00671 sgeometry->subslits[idx] = cpl_matrix_new(nrow, ncol);
00672
00673 return;
00674
00675 }
00676
00677
00678 static void
00679 _giraffe_slitgeo_set(GiSlitGeo *sgeometry, cxint idx, cpl_matrix *nm)
00680 {
00681
00682 if (sgeometry == NULL) {
00683 return;
00684 }
00685
00686 if (sgeometry->subslits == NULL) {
00687 return;
00688 }
00689
00690 if ((idx < 0) || (idx > sgeometry->nsubslits)) {
00691 return;
00692 }
00693
00694 if (sgeometry->subslits[idx] != NULL) {
00695 cpl_matrix_delete(sgeometry->subslits[idx]);
00696 }
00697
00698 if (nm) {
00699 sgeometry->subslits[idx] = cpl_matrix_duplicate(nm);
00700 }
00701 else {
00702 sgeometry->subslits[idx] = NULL;
00703 }
00704
00705 }
00706
00707
00708 static cpl_matrix*
00709 _giraffe_slitgeo_get(GiSlitGeo *sgeometry, cxint idx)
00710 {
00711
00712 if (sgeometry == NULL) {
00713 return NULL;
00714 }
00715
00716 if (sgeometry->subslits == NULL) {
00717 return NULL;
00718 }
00719
00720 if ((idx < 0)||(idx > sgeometry->nsubslits)) {
00721 return NULL;
00722 }
00723
00724 return (sgeometry->subslits[idx]);
00725
00726 }
00727
00728
00729 static cxint
00730 _giraffe_slitgeo_setup(const GiTable *slitgeo,
00731 GiFiberPosition *fiber_slit_position,
00732 GiSlitGeo *subslits, cxbool fitsubslit)
00733 {
00734
00735 const cxchar *const fctid = "_giraffe_slitgeo_setup";
00736
00737
00738 const cxchar *c_name_xf = "XF";
00739 const cxchar *c_name_yf = "YF";
00740 const cxchar *c_name_nspec = "FPS";
00741 const cxchar *c_name_ssn = "SSN";
00742
00743
00744 cpl_matrix *nspec = NULL;
00745 cpl_matrix *nsubslits = NULL;
00746
00747 cxint nr_slitgeo = 0,
00748 max_nsubslits = 0,
00749 i = 0,
00750 j = 0,
00751 row_null = 0,
00752 count = 0,
00753 column_index = 0,
00754 tmp_nspec = 0,
00755 tmp_nsubslits = 0;
00756
00757 cxdouble tmp_xf,
00758 tmp_yf;
00759
00760 cpl_table *ref_slitgeo = NULL;
00761
00762 cpl_error_code ce_code;
00763
00764
00765
00766
00767
00768
00769 if (slitgeo ==NULL) { return 1; }
00770 if (fiber_slit_position==NULL) { return 1; }
00771 if (subslits ==NULL) { return 1; }
00772
00773
00774
00775
00776
00777 ref_slitgeo = giraffe_table_get(slitgeo);
00778 nr_slitgeo = cpl_table_get_nrow(ref_slitgeo);
00779
00780 fiber_slit_position->x_fiber = cpl_matrix_new(nr_slitgeo, 1);
00781 fiber_slit_position->y_fiber = cpl_matrix_new(nr_slitgeo, 1);
00782
00783 nspec = cpl_matrix_new(nr_slitgeo, 1);
00784 nsubslits = cpl_matrix_new(nr_slitgeo, 1);
00785
00786
00787
00788
00789
00790 max_nsubslits = 0;
00791
00792 for (i = 0; i < nr_slitgeo; i++) {
00793
00794 tmp_xf = cpl_table_get(ref_slitgeo, c_name_xf, i, &row_null);
00795 tmp_yf = cpl_table_get(ref_slitgeo, c_name_yf, i, &row_null);
00796
00797 tmp_nspec = cpl_table_get_int(ref_slitgeo, c_name_nspec, i,
00798 &row_null) - 1;
00799
00800 tmp_nsubslits = cpl_table_get_int(ref_slitgeo, c_name_ssn, i,
00801 &row_null);
00802
00803 if (tmp_nsubslits>max_nsubslits) {
00804 max_nsubslits = tmp_nsubslits;
00805 }
00806
00807 ce_code = cpl_matrix_set(fiber_slit_position->x_fiber, i, 0, tmp_xf);
00808 ce_code = cpl_matrix_set(fiber_slit_position->y_fiber, i, 0, tmp_yf);
00809
00810 ce_code = cpl_matrix_set(nspec, i, 0, (cxdouble)tmp_nspec);
00811 ce_code = cpl_matrix_set(nsubslits, i, 0, (cxdouble)tmp_nsubslits);
00812
00813 }
00814
00815
00816
00817
00818
00819 if (fitsubslit) {
00820
00821
00822
00823 _giraffe_slitgeo_resize(subslits, max_nsubslits);
00824
00825 for (i = 1; i <= max_nsubslits; i++) {
00826
00827 cpl_matrix *ref_matrix = NULL;
00828 cxint curr_ssn;
00829
00830 count = 0;
00831 for (j=0; j<nr_slitgeo; j++) {
00832 curr_ssn = (cxint) cpl_matrix_get(nsubslits, j, 0);
00833 if (i==curr_ssn) {
00834 ++count;
00835 }
00836 }
00837
00838 _giraffe_slitgeo_create(subslits, i-1, count, 1);
00839
00840 ref_matrix = _giraffe_slitgeo_get(subslits, i-1);
00841
00842 column_index = 0;
00843 for (j = 0; j < nr_slitgeo; j++) {
00844
00845 curr_ssn = (cxint) cpl_matrix_get(nsubslits, j, 0);
00846
00847 if (i == curr_ssn) {
00848 ce_code = cpl_matrix_set(ref_matrix, column_index, 0,
00849 (cxdouble)j);
00850 column_index++;
00851 }
00852
00853 }
00854 }
00855
00856 cpl_msg_debug(fctid, "Using multiple slits for Slit Geometry");
00857
00858 }
00859 else {
00860
00861 const cxchar *idx = giraffe_fiberlist_query_index(ref_slitgeo);
00862
00863
00864
00865
00866
00867
00868 cpl_matrix *ref_matrix = NULL;
00869
00870 _giraffe_slitgeo_resize(subslits, 1);
00871 _giraffe_slitgeo_create(subslits, 0, nr_slitgeo, 1);
00872
00873 ref_matrix = _giraffe_slitgeo_get(subslits, 0);
00874
00875 for (j = 0; j < nr_slitgeo; j++) {
00876
00877 cxint cs = cpl_table_get_int(ref_slitgeo, idx, j, NULL) - 1;
00878 ce_code = cpl_matrix_set(ref_matrix, j, 0, cs);
00879
00880
00881 }
00882
00883 cpl_msg_debug(fctid, "Using single slit for Slit Geometry");
00884
00885 }
00886
00887 cpl_matrix_delete(nspec);
00888 nspec = NULL;
00889
00890 cpl_matrix_delete(nsubslits);
00891 nsubslits = NULL;
00892
00893 return 0;
00894
00895 }
00896
00897
00898 static GiWcalSolution*
00899 _giraffe_wcalsolution_new(void)
00900 {
00901
00902 GiWcalSolution* tmp = NULL;
00903
00904 tmp = (GiWcalSolution*) cx_calloc(1, sizeof(GiWcalSolution));
00905
00906 tmp->subslitfit = FALSE;
00907 tmp->opt_mod = LMRQ_UNDEFINED;
00908 tmp->opt_mod_params = NULL;
00909 tmp->wav_coeffs = NULL;
00910 tmp->wav_limits = NULL;
00911
00912 return tmp;
00913 }
00914
00915
00916 static void
00917 _giraffe_wcalsolution_delete(GiWcalSolution *ws)
00918 {
00919
00920 if (ws != NULL) {
00921
00922 if (ws->opt_mod_params!=NULL) {
00923 cpl_matrix_delete(ws->opt_mod_params);
00924 }
00925
00926 if (ws->wav_coeffs!=NULL) {
00927 _giraffe_slitgeo_delete(ws->wav_coeffs);
00928 }
00929
00930 if (ws->wav_limits!=NULL) {
00931 _giraffe_slitgeo_delete(ws->wav_limits);
00932 }
00933
00934 cx_free(ws);
00935
00936 }
00937
00938 return;
00939
00940 }
00941
00942
00943 static GiWcalSolution*
00944 _giraffe_wcalsolution_create(const GiTable *wavesolution)
00945 {
00946
00947 cxchar buffer[68];
00948
00949 cxint i = 0;
00950 cxint poly_x_deg = 0;
00951 cxint poly_y_deg = 0;
00952 cxint ncoefficients = 0;
00953
00954 cxdouble* pd_coefficients = NULL;
00955
00956 cpl_matrix* coefficients = NULL;
00957 cpl_matrix* limits = NULL;
00958
00959 cpl_propertylist* _properties = NULL;
00960
00961 cpl_table* _table = NULL;
00962
00963 GiWcalSolution* wavcoeff = NULL;
00964
00965
00966
00967 if (wavesolution == NULL) {
00968 return NULL;
00969 }
00970
00971 wavcoeff = _giraffe_wcalsolution_new();
00972
00973 _properties = giraffe_table_get_properties(wavesolution);
00974
00975
00976
00977
00978
00979
00980 if (cpl_propertylist_has(_properties, GIALIAS_OPT_MOD) == TRUE) {
00981
00982 const cxchar* optmod = cpl_propertylist_get_string(_properties,
00983 GIALIAS_OPT_MOD);
00984
00985 if (strncmp(optmod, "xoptmod2", 8) == 0) {
00986 wavcoeff->opt_mod = LMRQ_XOPTMOD2;
00987 }
00988 else if (strncmp(optmod, "xoptmod", 7) == 0) {
00989 wavcoeff->opt_mod = LMRQ_XOPTMOD;
00990 }
00991 else {
00992 wavcoeff->opt_mod = LMRQ_UNDEFINED;
00993 }
00994 }
00995
00996 if (wavcoeff->opt_mod == LMRQ_XOPTMOD2) {
00997
00998 wavcoeff->opt_mod_params = cpl_matrix_new(7,1);
00999
01000 if (cpl_propertylist_has(_properties, GIALIAS_OPTMDIR)) {
01001 cpl_matrix_set(
01002 wavcoeff->opt_mod_params,
01003 0,
01004 0,
01005 cpl_propertylist_get_int(_properties, GIALIAS_OPTMDIR)
01006 );
01007 } else {
01008 _giraffe_wcalsolution_delete(wavcoeff);
01009 return NULL;
01010 }
01011
01012 if (cpl_propertylist_has(_properties, GIALIAS_WSOL_OPTMFCOLL)) {
01013 cpl_matrix_set(
01014 wavcoeff->opt_mod_params,
01015 1,
01016 0,
01017 cpl_propertylist_get_double(_properties, GIALIAS_WSOL_OPTMFCOLL)
01018 );
01019 } else {
01020 _giraffe_wcalsolution_delete(wavcoeff);
01021 return NULL;
01022 }
01023
01024 if (cpl_propertylist_has(_properties, GIALIAS_WSOL_OPTMGCAM)) {
01025 cpl_matrix_set(
01026 wavcoeff->opt_mod_params,
01027 2,
01028 0,
01029 cpl_propertylist_get_double(_properties, GIALIAS_WSOL_OPTMGCAM)
01030 );
01031 } else {
01032 _giraffe_wcalsolution_delete(wavcoeff);
01033 return NULL;
01034 }
01035
01036 if (cpl_propertylist_has(_properties, GIALIAS_WSOL_OPTMTHETA)) {
01037 cpl_matrix_set(
01038 wavcoeff->opt_mod_params,
01039 3,
01040 0,
01041 cpl_propertylist_get_double(_properties, GIALIAS_WSOL_OPTMTHETA)
01042 );
01043 } else {
01044 _giraffe_wcalsolution_delete(wavcoeff);
01045 return NULL;
01046 }
01047
01048 if (cpl_propertylist_has(_properties, GIALIAS_WSOL_OPTMSDX)) {
01049 cpl_matrix_set(
01050 wavcoeff->opt_mod_params,
01051 4,
01052 0,
01053 cpl_propertylist_get_double(_properties, GIALIAS_WSOL_OPTMSDX)
01054 );
01055 } else {
01056 _giraffe_wcalsolution_delete(wavcoeff);
01057 return NULL;
01058 }
01059
01060 if (cpl_propertylist_has(_properties, GIALIAS_WSOL_OPTMSDY)) {
01061
01062
01063
01064 cpl_matrix_set(
01065 wavcoeff->opt_mod_params,
01066 5,
01067 0,
01068 cpl_propertylist_get_double(_properties, GIALIAS_WSOL_OPTMSDY)
01069 );
01070
01071 } else {
01072 _giraffe_wcalsolution_delete(wavcoeff);
01073 return NULL;
01074 }
01075
01076 if (cpl_propertylist_has(_properties, GIALIAS_WSOL_OPTMSPHI)) {
01077 cpl_matrix_set(
01078 wavcoeff->opt_mod_params,
01079 6,
01080 0,
01081 cpl_propertylist_get_double(_properties, GIALIAS_WSOL_OPTMSPHI)
01082 );
01083
01084 } else {
01085 _giraffe_wcalsolution_delete(wavcoeff);
01086 return NULL;
01087 }
01088
01089 } else if (wavcoeff->opt_mod==LMRQ_XOPTMOD) {
01090
01091 wavcoeff->opt_mod_params = cpl_matrix_new(4,1);
01092
01093 if (cpl_propertylist_has(_properties, GIALIAS_OPTMDIR)) {
01094 cpl_matrix_set(
01095 wavcoeff->opt_mod_params,
01096 0,
01097 0,
01098 cpl_propertylist_get_int(_properties, GIALIAS_OPTMDIR)
01099 );
01100 } else {
01101 _giraffe_wcalsolution_delete(wavcoeff);
01102 return NULL;
01103 }
01104
01105 if (cpl_propertylist_has(_properties, GIALIAS_WSOL_OPTMFCOLL)) {
01106 cpl_matrix_set(
01107 wavcoeff->opt_mod_params,
01108 1,
01109 0,
01110 cpl_propertylist_get_double(_properties, GIALIAS_WSOL_OPTMFCOLL)
01111 );
01112 } else {
01113 _giraffe_wcalsolution_delete(wavcoeff);
01114 return NULL;
01115 }
01116
01117 if (cpl_propertylist_has(_properties, GIALIAS_WSOL_OPTMGCAM)) {
01118 cpl_matrix_set(
01119 wavcoeff->opt_mod_params,
01120 2,
01121 0,
01122 cpl_propertylist_get_double(_properties, GIALIAS_WSOL_OPTMGCAM)
01123 );
01124 } else {
01125 _giraffe_wcalsolution_delete(wavcoeff);
01126 return NULL;
01127 }
01128
01129 if (cpl_propertylist_has(_properties, GIALIAS_WSOL_OPTMTHETA)) {
01130 cpl_matrix_set(
01131 wavcoeff->opt_mod_params,
01132 3,
01133 0,
01134 cpl_propertylist_get_double(_properties, GIALIAS_WSOL_OPTMTHETA)
01135 );
01136 } else {
01137 _giraffe_wcalsolution_delete(wavcoeff);
01138 return NULL;
01139 }
01140
01141
01142 } else {
01143
01144 _giraffe_wcalsolution_delete(wavcoeff);
01145 return NULL;
01146
01147 }
01148
01149
01150
01151
01152
01153
01154 _table = giraffe_table_get(wavesolution);
01155
01156 if (_table != NULL) {
01157
01158
01159 if (cpl_propertylist_has(_properties, GIALIAS_SSF)) {
01160
01161 if (cpl_propertylist_get_bool(_properties, GIALIAS_SSF) == 0) {
01162 wavcoeff->subslitfit = FALSE;
01163 }
01164 else {
01165 wavcoeff->subslitfit = TRUE;
01166 }
01167
01168 }
01169 else {
01170
01171 _giraffe_wcalsolution_delete(wavcoeff);
01172 return NULL;
01173
01174 }
01175
01176 wavcoeff->wav_limits = _giraffe_slitgeo_new();
01177 _giraffe_slitgeo_resize(wavcoeff->wav_limits, 1);
01178
01179 limits = cpl_matrix_new(1, 4);
01180 cpl_matrix_fill(limits, -1.);
01181
01182 if (cpl_table_has_column(_table, "XMIN") &&
01183 cpl_table_has_column(_table, "XMAX")) {
01184 cpl_matrix_set(limits, 0, 0,
01185 cpl_table_get_double(_table, "XMIN", 0, NULL));
01186 cpl_matrix_set(limits, 0, 1,
01187 cpl_table_get_double(_table, "XMAX", 0, NULL));
01188 }
01189
01190 if (cpl_table_has_column(_table, "YMIN") &&
01191 cpl_table_has_column(_table, "YMAX")) {
01192 cpl_matrix_set(limits, 0, 2,
01193 cpl_table_get_double(_table, "YMIN", 0, NULL));
01194 cpl_matrix_set(limits, 0, 3,
01195 cpl_table_get_double(_table, "YMAX", 0, NULL));
01196 }
01197
01198 _giraffe_slitgeo_set(wavcoeff->wav_limits, 0, limits);
01199
01200 cpl_matrix_delete(limits);
01201 limits = NULL;
01202
01203 wavcoeff->wav_coeffs = _giraffe_slitgeo_new();
01204 _giraffe_slitgeo_resize(wavcoeff->wav_coeffs, 1);
01205
01206 if (cpl_propertylist_has(_properties, GIALIAS_XRES_PDEG)) {
01207
01208 cxchar *l, *r, *tmpstr;
01209
01210 tmpstr = (cxchar*) cpl_propertylist_get_string(_properties,
01211 GIALIAS_XRES_PDEG);
01212
01213 l = &(tmpstr[0]);
01214 r = &(tmpstr[2]);
01215
01216 poly_x_deg = atoi(l) + 1;
01217 poly_y_deg = atoi(r) + 1;
01218
01219 }
01220 else {
01221
01222 _giraffe_wcalsolution_delete(wavcoeff);
01223 return NULL;
01224
01225 }
01226
01227 ncoefficients = poly_x_deg * poly_y_deg;
01228
01229 coefficients = cpl_matrix_new(poly_x_deg,poly_y_deg);
01230 pd_coefficients = cpl_matrix_get_data(coefficients);
01231
01232 for (i=0; i<ncoefficients; i++) {
01233
01234 snprintf(buffer, sizeof buffer, "XC%-d", i);
01235
01236 pd_coefficients[i] =
01237 cpl_table_get_double(_table, buffer, 0, NULL);
01238
01239 }
01240
01241 _giraffe_slitgeo_set(wavcoeff->wav_coeffs, 0, coefficients);
01242
01243 cpl_matrix_delete(coefficients);
01244 coefficients = NULL;
01245
01246 }
01247
01248 return wavcoeff;
01249
01250 }
01251
01252
01253 static cpl_image*
01254 _giraffe_compute_pixel_abscissa(cpl_matrix* m_wavelengths,
01255 cpl_matrix* m_wloffset,
01256 GiFiberPosition* fiber_slit_position,
01257 cpl_matrix* m_opt_mod_params,
01258 lmrq_model lmrq_opt_mod_x)
01259 {
01260
01261
01262
01263
01264
01265 const cxchar *fctid = "_giraffe_compute_pixel_abscissa";
01266
01267 register cxint n;
01268 register cxint line;
01269 register cxint nwlen;
01270 register cxint ns;
01271
01272 cxint nr_m_opt_mod_params = 0;
01273
01274 cxdouble xccd = 0.;
01275 cxdouble* pd_xref = NULL;
01276 cxdouble* pd_m_inputs = NULL;
01277 cxdouble* pd_m_yfibre = NULL;
01278 cxdouble* pd_m_xfibre = NULL;
01279 cxdouble* pd_m_wavelengths = NULL;
01280 cxdouble* pd_m_opt_mod_params = NULL;
01281
01282 cpl_image* xref = NULL;
01283
01284 cpl_matrix* m_inputs = NULL;
01285
01286
01287
01288
01289
01290
01291 if (m_wavelengths == NULL) {
01292 return NULL;
01293 }
01294
01295 if ((fiber_slit_position == NULL) ||
01296 (fiber_slit_position->x_fiber == NULL) ||
01297 (fiber_slit_position->y_fiber == NULL)) {
01298 return NULL;
01299 }
01300
01301 if (m_opt_mod_params == NULL) {
01302 return NULL;
01303 }
01304
01305
01306 nwlen = cpl_matrix_get_nrow(m_wavelengths);
01307 ns = cpl_matrix_get_nrow(fiber_slit_position->y_fiber);
01308
01309 if ((m_wloffset != NULL) && (cpl_matrix_get_nrow(m_wloffset) != ns)) {
01310 return NULL;
01311 }
01312
01313
01314
01315
01316
01317
01318 xref = cpl_image_new(ns, nwlen, CPL_TYPE_DOUBLE);
01319 pd_xref = cpl_image_get_data_double(xref);
01320
01321 m_inputs = cpl_matrix_new(lmrq_opt_mod_x.ninputs, 1);
01322 pd_m_inputs = cpl_matrix_get_data(m_inputs);
01323
01324 pd_m_yfibre = cpl_matrix_get_data(fiber_slit_position->y_fiber);
01325 pd_m_xfibre = cpl_matrix_get_data(fiber_slit_position->x_fiber);
01326 pd_m_wavelengths = cpl_matrix_get_data(m_wavelengths);
01327
01328 pd_m_opt_mod_params = cpl_matrix_get_data(m_opt_mod_params);
01329 nr_m_opt_mod_params = cpl_matrix_get_nrow(m_opt_mod_params);
01330
01331
01332
01333
01334
01335
01336 if (m_wloffset != NULL) {
01337
01338 cxdouble* pd_m_wloffset = cpl_matrix_get_data(m_wloffset);
01339
01340 for (n = 0; n < ns; n++) {
01341
01342 pd_m_inputs[2] = pd_m_yfibre[n];
01343 pd_m_inputs[1] = pd_m_xfibre[n];
01344
01345 for (line = 0; line < nwlen; line++) {
01346
01347 pd_m_inputs[0] = pd_m_wavelengths[line] + pd_m_wloffset[n];
01348
01349 lmrq_opt_mod_x.cfunc(pd_m_inputs, pd_m_opt_mod_params,
01350 NULL, &xccd, NULL, nr_m_opt_mod_params);
01351
01352 pd_xref[line * ns + n] = xccd;
01353
01354 }
01355
01356 }
01357
01358 }
01359 else {
01360
01361 for (n = 0; n < ns; n++) {
01362
01363 pd_m_inputs[2] = pd_m_yfibre[n];
01364 pd_m_inputs[1] = pd_m_xfibre[n];
01365
01366 for (line = 0; line < nwlen; line++) {
01367
01368 pd_m_inputs[0] = pd_m_wavelengths[line];
01369
01370 lmrq_opt_mod_x.cfunc(pd_m_inputs, pd_m_opt_mod_params,
01371 NULL, &xccd, NULL, nr_m_opt_mod_params);
01372
01373 pd_xref[line * ns + n] = xccd;
01374
01375 }
01376
01377 }
01378
01379 }
01380
01381 cpl_matrix_delete(m_inputs);
01382
01383 cpl_msg_debug(fctid, "Processing completed: Returning image [x,y] ="
01384 " [%" CPL_SIZE_FORMAT ",%" CPL_SIZE_FORMAT "]",
01385 cpl_image_get_size_x(xref), cpl_image_get_size_y(xref));
01386
01387 return xref;
01388
01389 }
01390
01391
01392 inline static cpl_matrix *
01393 _giraffe_rebin_setup_model(GiImage *extspectra, GiWcalSolution *wcal)
01394 {
01395
01396 cxint npixel;
01397
01398 cxdouble pixelsize;
01399
01400 cpl_propertylist *properties = NULL;
01401
01402 cpl_matrix *model = NULL;
01403
01404
01405 if (extspectra == NULL) {
01406 return NULL;
01407 }
01408
01409 if (wcal == NULL) {
01410 return NULL;
01411 }
01412
01413 properties = giraffe_image_get_properties(extspectra);
01414
01415 if (properties == NULL) {
01416 return NULL;
01417 }
01418
01419
01420
01421
01422
01423
01424 if (!cpl_propertylist_has(properties, GIALIAS_EXT_NX)) {
01425 return NULL;
01426 }
01427
01428 npixel = cpl_propertylist_get_int(properties, GIALIAS_EXT_NX);
01429
01430
01431
01432
01433
01434
01435 if (!cpl_propertylist_has(properties, GIALIAS_PIXSIZX)) {
01436 return NULL;
01437 }
01438
01439 pixelsize = cpl_propertylist_get_double(properties, GIALIAS_PIXSIZX);
01440 pixelsize /= 1000.;
01441
01442
01443
01444
01445
01446
01447 switch (wcal->opt_mod) {
01448 case LMRQ_XOPTMOD:
01449 if (cpl_matrix_get_nrow(wcal->opt_mod_params) != 4) {
01450 return NULL;
01451 }
01452 else {
01453
01454 cxdouble direction = cpl_matrix_get(wcal->opt_mod_params, 0, 0);
01455 cxdouble fcoll = cpl_matrix_get(wcal->opt_mod_params, 1, 0);
01456 cxdouble cfact = cpl_matrix_get(wcal->opt_mod_params, 2, 0);
01457
01458 model = cpl_matrix_new(4, 1);
01459
01460 cpl_matrix_set(model, 0, 0, npixel * direction);
01461 cpl_matrix_set(model, 1, 0, pixelsize);
01462 cpl_matrix_set(model, 2, 0, fcoll);
01463 cpl_matrix_set(model, 3, 0, cfact);
01464 }
01465 break;
01466
01467 case LMRQ_XOPTMOD2:
01468 if (cpl_matrix_get_nrow(wcal->opt_mod_params) != 7) {
01469 return NULL;
01470 }
01471 else {
01472
01473 cxdouble direction = cpl_matrix_get(wcal->opt_mod_params, 0, 0);
01474 cxdouble fcoll = cpl_matrix_get(wcal->opt_mod_params, 1, 0);
01475 cxdouble cfact = cpl_matrix_get(wcal->opt_mod_params, 2, 0);
01476 cxdouble sdx = cpl_matrix_get(wcal->opt_mod_params, 4, 0);
01477 cxdouble sdy = cpl_matrix_get(wcal->opt_mod_params, 5, 0);
01478 cxdouble sphi = cpl_matrix_get(wcal->opt_mod_params, 6, 0);
01479
01480 model = cpl_matrix_new(7, 1);
01481
01482 cpl_matrix_set(model, 0, 0, npixel * direction);
01483 cpl_matrix_set(model, 1, 0, pixelsize);
01484 cpl_matrix_set(model, 2, 0, fcoll);
01485 cpl_matrix_set(model, 3, 0, cfact);
01486 cpl_matrix_set(model, 4, 0, sdx);
01487 cpl_matrix_set(model, 5, 0, sdy);
01488 cpl_matrix_set(model, 6, 0, sphi);
01489 }
01490 break;
01491
01492 default:
01493 return NULL;
01494 break;
01495 }
01496
01497 cx_assert(model != NULL);
01498
01499 return model;
01500
01501 }
01502
01503
01504 inline static cpl_matrix *
01505 _giraffe_rebin_setup_grating(GiImage *extspectra, GiTable *grating,
01506 GiTable *wlsolution)
01507 {
01508
01509 cxint status = 0;
01510
01511 cpl_propertylist *properties = NULL;
01512
01513 cpl_matrix *setup = NULL;
01514
01515 GiGrat *grating_data = _giraffe_grating_new();
01516
01517
01518 status = _giraffe_grating_setup(grating, extspectra, grating_data);
01519
01520 if (status != 0) {
01521 _giraffe_grating_delete(grating_data);
01522 return NULL;
01523 }
01524
01525
01526 properties = giraffe_table_get_properties(wlsolution);
01527
01528 if (cpl_propertylist_has(properties, GIALIAS_WSOL_OMFCOLL)) {
01529 grating_data->fcoll = cpl_propertylist_get_double(properties,
01530 GIALIAS_WSOL_OMFCOLL);
01531 }
01532
01533 if (cpl_propertylist_has(properties, GIALIAS_WSOL_OMGCAM)) {
01534 grating_data->gcam = cpl_propertylist_get_double(properties,
01535 GIALIAS_WSOL_OMGCAM);
01536 }
01537
01538 if (cpl_propertylist_has(properties, GIALIAS_WSOL_OMGTHETA)) {
01539 grating_data->theta = cpl_propertylist_get_double(properties,
01540 GIALIAS_WSOL_OMGTHETA);
01541 }
01542
01543 if (cpl_propertylist_has(properties, GIALIAS_WSOL_OMSDX)) {
01544 grating_data->slitdx = cpl_propertylist_get_double(properties,
01545 GIALIAS_WSOL_OMSDX);
01546 }
01547
01548 if (cpl_propertylist_has(properties, GIALIAS_WSOL_OMSDY)) {
01549 grating_data->slitdy = cpl_propertylist_get_double(properties,
01550 GIALIAS_WSOL_OMSDY);
01551 }
01552
01553 if (cpl_propertylist_has(properties, GIALIAS_WSOL_OMSPHI)) {
01554 grating_data->slitphi = cpl_propertylist_get_double(properties,
01555 GIALIAS_WSOL_OMSPHI);
01556 }
01557
01558
01559 setup = cpl_matrix_new(7, 1);
01560
01561 cpl_matrix_set(setup, 0, 0, grating_data->theta);
01562 cpl_matrix_set(setup, 1, 0, grating_data->order);
01563 cpl_matrix_set(setup, 2, 0, grating_data->wlenmin / GI_MM_TO_NM);
01564 cpl_matrix_set(setup, 3, 0, grating_data->wlen0 / GI_MM_TO_NM);
01565 cpl_matrix_set(setup, 4, 0, grating_data->wlenmax / GI_MM_TO_NM);
01566 cpl_matrix_set(setup, 5, 0, grating_data->resol);
01567 cpl_matrix_set(setup, 6, 0, grating_data->space);
01568
01569 _giraffe_grating_delete(grating_data);
01570 grating_data = NULL;
01571
01572 return setup;
01573
01574 }
01575
01576
01589 inline static cxint
01590 _giraffe_spline_calc_circe(cxdouble x, register cxdouble* t, cxint n)
01591 {
01592
01593 register cxint lo = 0;
01594 register cxint hi = n - 1;
01595
01596
01597 if (x >= t[0] && x <= t[n - 1]) {
01598
01599 while (hi - lo > 1) {
01600
01601 register cxint mid = (lo + hi) / 2.;
01602
01603 cxdouble tm = 0.;
01604
01605 tm = t[mid];
01606
01607 if (x < tm) {
01608 hi = mid;
01609 }
01610 else {
01611 lo = mid;
01612 }
01613 }
01614
01615 return hi;
01616
01617 }
01618
01619 return -1;
01620
01621 }
01622
01642 inline static void
01643 _giraffe_spline_calc_tridi(register cxdouble* a, register cxdouble* b,
01644 register cxdouble* c, register cxdouble* f,
01645 register cxdouble* x, cxint n)
01646 {
01647
01648 register cxint i = 0;
01649
01650 c[0] /= a[0];
01651
01652 for (i = 1; i < n; i++) {
01653 c[i] /= (a[i] - b[i] * c[i - 1]);
01654 }
01655
01656 f[0] /= a[0];
01657
01658 for (i = 1; i < n; i++) {
01659 f[i] = (f[i] - b[i] * f[i - 1]) / (a[i] - b[i] * c[i - 1]);
01660 }
01661
01662 x[n - 1] = f[n - 1];
01663
01664 for (i = n - 2; i >= 0; i--) {
01665 x[i] = f[i] - c[i] * x[i + 1];
01666 }
01667
01668 return;
01669 }
01670
01690 inline static cxint
01691 _giraffe_spline_calc_interpolate(cxdouble z, cxdouble* val,
01692 register cxdouble* x, register cxdouble* y,
01693 register cxdouble* k, cxint n)
01694 {
01695
01696 cxint m = 0;
01697
01698 cxdouble h = 0.;
01699 cxdouble t = 0.;
01700 cxdouble d = 0.;
01701 cxdouble a = 0.;
01702 cxdouble b = 0.;
01703 cxdouble dx = 0.;
01704
01705
01706 m = _giraffe_spline_calc_circe(z, x, n);
01707
01708 if (m < 0) {
01709
01710
01711 if (z < x[0]) {
01712 dx = z - x[0];
01713 *val = y[0] + dx * (k[0] + 0.5 * dx * ddb);
01714 } else {
01715 dx = z - x[n - 1];
01716 *val = y[n - 1] + dx * (k[n - 1] + 0.5 * dx * dde);
01717 }
01718
01719 return 1;
01720
01721 }
01722
01723 dx = z - x[m - 1];
01724 h = x[m] - x[m - 1];
01725 d = (y[m] - y[m - 1]) / h;
01726 t = dx / h;
01727 a = (k[m - 1] - d) * (1 - t);
01728 b = (k[m] - d) * t;
01729 *val = t * y[m] + (1 - t) * y[m - 1] + h * t * (1 - t) * (a - b);
01730
01731 return 0;
01732
01733 }
01734
01755 inline static cxint
01756 _giraffe_spline_calc_initalize(cxdouble* x, cxdouble* y, cxdouble* k,
01757 cxint n, cxdouble q2b, cxdouble q2e)
01758 {
01759
01760 register cxint i = 0;
01761 register cxint ip = 0;
01762
01763 register cxdouble* a;
01764 register cxdouble* b;
01765 register cxdouble* c;
01766 register cxdouble* f;
01767
01768 cxdouble hio = 0.;
01769 cxdouble hip = 0.;
01770 cxdouble dio = 0.;
01771 cxdouble dip = 0.;
01772
01773
01774
01775 ddb = q2b;
01776 dde = q2e;
01777
01778 a = (cxdouble*) cx_malloc(4 * n * sizeof(cxdouble));
01779
01780 b = a + n;
01781 c = b + n;
01782 f = c + n;
01783
01784 for (i = 0; i < n; i++) {
01785
01786 hip = ((ip = i + 1) < n ? x[ip] - x[i] : 0.0);
01787 dip = (ip < n ? (y[ip] - y[i]) / hip : 0.0);
01788 b[i] = (ip < n ? hip : hio);
01789 a[i] = 2.0 * (hip + hio);
01790 c[i] = (i > 0 ? hio : hip);
01791 f[i] = 3.0 * (hip * dio + hio * dip);
01792
01793 if (i == 0) {
01794 f[0] = 3.0 * hip * dip - hip * hip * q2b * 0.5;
01795 }
01796 else if (i == n - 1) {
01797 f[n - 1] = 3.0 * hio * dio + hio * hio * q2e * 0.5;
01798 }
01799
01800 dio = dip;
01801 hio = hip;
01802 }
01803
01804 _giraffe_spline_calc_tridi(a, b, c, f, k, n);
01805
01806 cx_free(a);
01807
01808 return 0;
01809
01810 }
01811
01830 inline static cxint
01831 _giraffe_rebin_interpolate_spline(cpl_matrix* x_1, cpl_matrix* y_1,
01832 cpl_matrix* x_2, cpl_matrix* y_2)
01833 {
01834
01835 cxint i = 0;
01836 cxint res = 0;
01837 cxint nr_x1 = 0;
01838 cxint nr_x2 = 0;
01839
01840 cxdouble* k = NULL;
01841 cxdouble* pd_x1 = NULL;
01842 cxdouble* pd_y1 = NULL;
01843 cxdouble* pd_x2 = NULL;
01844 cxdouble* pd_y2 = NULL;
01845
01846
01847
01848 if (x_1 == NULL || y_1 == NULL || x_2 == NULL || y_2 == NULL) {
01849 return 1;
01850 }
01851
01852 nr_x1 = cpl_matrix_get_nrow(x_1);
01853 nr_x2 = cpl_matrix_get_nrow(x_2);
01854
01855 pd_x1 = cpl_matrix_get_data(x_1);
01856 pd_y1 = cpl_matrix_get_data(y_1);
01857 pd_y2 = cpl_matrix_get_data(y_2);
01858 pd_x2 = cpl_matrix_get_data(x_2);
01859
01860
01861
01862
01863
01864
01865 k = (cxdouble*) cx_malloc(nr_x1 * sizeof(cxdouble));
01866
01867
01868
01869
01870
01871
01872 res = _giraffe_spline_calc_initalize(pd_x1, pd_y1, k, nr_x1, 0.0, 0.0);
01873
01874 if (res < 0) {
01875 cx_free(k);
01876 return res;
01877 }
01878
01879
01880
01881
01882
01883 for (i = 0; i < nr_x2; i++) {
01884 res = _giraffe_spline_calc_interpolate(pd_x2[i], &(pd_y2[i]), pd_x1,
01885 pd_y1, k, nr_x1);
01886 }
01887
01888 cx_free(k);
01889
01890 return 0;
01891
01892 }
01893
01915 inline static cxint
01916 _giraffe_rebin_interpolate_linear(
01917 cpl_matrix *x_1,
01918 cpl_matrix *y_1,
01919 cpl_matrix *x_2,
01920 cpl_matrix *y_2
01921 )
01922 {
01923
01924
01925
01926
01927
01928 register cxdouble a, b ;
01929 register cxint i, j, j_1, found, n1;
01930
01931 cxint nr_x1 = 0,
01932 nr_x2 = 0;
01933 cxdouble *pd_x1 = NULL,
01934 *pd_x2 = NULL,
01935 *pd_y2 = NULL,
01936 *pd_y1 = NULL;
01937
01938
01939
01940
01941
01942 if (x_1 == NULL) { return 1; }
01943 if (y_1 == NULL) { return 1; }
01944 if (x_2 == NULL) { return 1; }
01945 if (y_2 == NULL) { return 1; }
01946
01947 nr_x1 = cpl_matrix_get_nrow(x_1);
01948 nr_x2 = cpl_matrix_get_nrow(x_2);
01949 pd_x1 = cpl_matrix_get_data(x_1);
01950 pd_x2 = cpl_matrix_get_data(x_2);
01951 pd_y1 = cpl_matrix_get_data(y_1);
01952 pd_y2 = cpl_matrix_get_data(y_2);
01953
01954
01955
01956
01957
01958 n1 = nr_x1 - 1;
01959
01960 for (i = 0; i < nr_x2; i++) {
01961
01962 found = 0;
01963 for (j = 0; j < n1; j++) {
01964 if ((pd_x2[i] >= pd_x1[j]) && (pd_x2[i] <= pd_x1[j+1])) {
01965 found++ ;
01966 break ;
01967 }
01968 }
01969
01970 if (!found) {
01971 pd_y2[i] = 0.0;
01972 } else {
01973 j_1 = j + 1;
01974 a = (pd_y1[j_1] - pd_y1[j]) / (pd_x1[j_1] - pd_x1[j]);
01975 b = pd_y1[j] - a * pd_x1[j];
01976 pd_y2[i] = (a * pd_x2[i] + b);
01977
01978 }
01979 }
01980
01981 return 0;
01982
01983 }
01984
02010 inline static cxint
02011 _giraffe_rebin_interpolate_linear_error(
02012 cpl_matrix *x_1,
02013 cpl_matrix *y_1,
02014 cpl_matrix *y_1err,
02015 cpl_matrix *x_2,
02016 cpl_matrix *y_2,
02017 cpl_matrix *y_2err
02018 ) {
02019
02020
02021
02022
02023
02024 register double a, b ,dx;
02025 register int i, j, j_1, found, n1 ;
02026
02027 cxint nr_x1 = 0,
02028 nr_x2 = 0;
02029 cxdouble *pd_x1 = NULL,
02030 *pd_y1 = NULL,
02031 *pd_y1err = NULL,
02032 *pd_x2 = NULL,
02033 *pd_y2 = NULL,
02034 *pd_y2err = NULL;
02035
02036
02037
02038
02039
02040 if (x_1 == NULL) { return 1; }
02041 if (y_1 == NULL) { return 1; }
02042 if (y_1err == NULL) { return 1; }
02043 if (x_2 == NULL) { return 1; }
02044 if (y_2 == NULL) { return 1; }
02045 if (y_2err == NULL) { return 1; }
02046
02047 nr_x1 = cpl_matrix_get_nrow(x_1);
02048 nr_x2 = cpl_matrix_get_nrow(x_2);
02049 pd_x1 = cpl_matrix_get_data(x_1);
02050 pd_y1 = cpl_matrix_get_data(y_1);
02051 pd_y1err = cpl_matrix_get_data(y_1err);
02052 pd_x2 = cpl_matrix_get_data(x_2);
02053 pd_y2 = cpl_matrix_get_data(y_2);
02054 pd_y2err = cpl_matrix_get_data(y_2err);
02055
02056
02057
02058
02059
02060 n1 = nr_x1 - 1;
02061
02062 for (i = 0; i < nr_x2; i++) {
02063
02064 found = 0;
02065 for (j = 0; j < n1; j++) {
02066 if ((pd_x2[i] >= pd_x1[j]) && (pd_x2[i] <= pd_x1[j+1])) {
02067 found++ ;
02068 break ;
02069 }
02070 }
02071
02072 if (!found) {
02073 pd_y2[i] = 0.0;
02074 pd_y2err[i] = 0.0;
02075 } else {
02076
02077 j_1 = j + 1;
02078 dx = (pd_x1[j_1] - pd_x1[j]);
02079 a = (pd_y1[j_1] - pd_y1[j]) / dx;
02080 b = pd_y1[j] - a * pd_x1[j] ;
02081 pd_y2[i] = (a * pd_x2[i] + b) ;
02082 a = (pd_y1err[j_1] - pd_y1err[j]) / dx;
02083 b = pd_y1err[j] - a * pd_x1[j] ;
02084 pd_y2err[i] = (a * pd_x2[i] + b) ;
02085
02086 }
02087 }
02088
02089 return 0;
02090
02091 }
02092
02112 inline static cxint
02113 _giraffe_resample_linear(cpl_image* rbspectra, cpl_image* rberrors,
02114 cpl_image* abscissa, cpl_image* exspectra,
02115 cpl_image* exerrors, cxint opt_direction)
02116 {
02117
02118 const cxchar* const fctid = "_giraffe_resample_linear";
02119
02120 register cxlong n = 0;
02121
02122 cxint status = 0;
02123 cxint nx = 0;
02124 cxint ns = 0;
02125 cxint nwl = 0;
02126
02127 cxdouble nx1 = 0.;
02128 cxdouble* _mabscissa = NULL;
02129 cxdouble* _mexspectra = NULL;
02130 cxdouble* _mexerrors = NULL;
02131 cxdouble* _mwavelength = NULL;
02132 cxdouble* _mrbspectra = NULL;
02133 cxdouble* _mrberrors = NULL;
02134 cxdouble* _abscissa = NULL;
02135 cxdouble* _exspectra = NULL;
02136 cxdouble* _exerrors = NULL;
02137 cxdouble* _rbspectra = NULL;
02138 cxdouble* _rberrors = NULL;
02139
02140 cpl_matrix* mabscissa = NULL;
02141 cpl_matrix* mwavelength = NULL;
02142 cpl_matrix* mexspectra = NULL;
02143 cpl_matrix* mexerrors = NULL;
02144 cpl_matrix* mrbspectra = NULL;
02145 cpl_matrix* mrberrors = NULL;
02146
02147
02148
02149 if ((abscissa == NULL) || (exspectra == NULL) || (rbspectra == NULL)) {
02150 return 1;
02151 }
02152
02153 if ((exerrors != NULL) && (rberrors == NULL)) {
02154 return 1;
02155 }
02156
02157
02158 nx = cpl_image_get_size_y(exspectra);
02159 ns = cpl_image_get_size_x(exspectra);
02160 nwl = cpl_image_get_size_y(abscissa);
02161
02162 if ((exerrors != NULL) &&
02163 ((nx != cpl_image_get_size_y(exerrors)) ||
02164 (ns != cpl_image_get_size_x(exerrors)))) {
02165 return 1;
02166 }
02167
02168 nx1 = nx - 0.5;
02169
02170 mabscissa = cpl_matrix_new(nx, 1);
02171 mexspectra = cpl_matrix_new(nx, 1);
02172
02173 mwavelength = cpl_matrix_new(nwl, 1);
02174 mrbspectra = cpl_matrix_new(nwl, 1);
02175
02176 _mabscissa = cpl_matrix_get_data(mabscissa);
02177 _mexspectra = cpl_matrix_get_data(mexspectra);
02178 _mwavelength = cpl_matrix_get_data(mwavelength);
02179 _mrbspectra = cpl_matrix_get_data(mrbspectra);
02180
02181 _abscissa = cpl_image_get_data_double(abscissa);
02182 _exspectra = cpl_image_get_data_double(exspectra);
02183 _rbspectra = cpl_image_get_data_double(rbspectra);
02184
02185 if (exerrors != NULL) {
02186 mexerrors = cpl_matrix_new(nx, 1);
02187 mrberrors = cpl_matrix_new(nwl, 1);
02188
02189 _mexerrors = cpl_matrix_get_data(mexerrors);
02190 _mrberrors = cpl_matrix_get_data(mrberrors);
02191
02192 _exerrors = cpl_image_get_data_double(exerrors);
02193 _rberrors = cpl_image_get_data_double(rberrors);
02194 }
02195
02196
02197
02198
02199
02200
02201
02202
02203 cpl_msg_debug(fctid, "Rebinning %d spectra, using dispersion direction "
02204 "%d and linear interpolation", ns, opt_direction);
02205
02206 for (n = 0; n < ns; n++) {
02207
02208 register cxlong x = 0;
02209
02210
02211 for (x = 0; x < nwl; x++) {
02212 register cxlong j = x * ns + n;
02213 _mwavelength[x] = _abscissa[j];
02214 }
02215
02216 if (exerrors == NULL) {
02217
02218 if (opt_direction < 0) {
02219
02220 for (x = 0; x < nx; x++) {
02221
02222 register cxlong j = x * ns + n;
02223 register cxlong k = nx - x - 1;
02224
02225 _mabscissa[x] = (cxdouble) x;
02226 _mexspectra[k] = _exspectra[j];
02227 }
02228
02229 }
02230 else {
02231
02232 for (x = 0; x < nx; x++) {
02233
02234 register cxlong j = x * ns + n;
02235
02236 _mabscissa[x] = (cxdouble) x;
02237 _mexspectra[x] = _exspectra[j];
02238
02239 }
02240
02241 }
02242
02243
02244
02245
02246
02247
02248 status = _giraffe_rebin_interpolate_linear(mabscissa,
02249 mexspectra,
02250 mwavelength,
02251 mrbspectra);
02252
02253 for (x = 0; x < nwl; x++) {
02254
02255 register cxlong j = x * ns + n;
02256
02257 if ((-0.5 > _mwavelength[x]) || (_mwavelength[x] > nx1)) {
02258 _rbspectra[j] = 0.;
02259 }
02260 else {
02261 _rbspectra[j] = _mrbspectra[x];
02262 }
02263
02264 }
02265
02266 }
02267 else {
02268
02269 if (opt_direction < 0) {
02270
02271 for (x = 0; x < nx; x++) {
02272
02273 register cxlong j = x * ns + n;
02274 register cxlong k = nx - x - 1;
02275
02276 _mabscissa[x] = (cxdouble) x;
02277 _mexspectra[k] = _exspectra[j];
02278 _mexerrors[k] = _exerrors[j];
02279 }
02280
02281 }
02282 else {
02283
02284 for (x = 0; x < nx; x++) {
02285
02286 register cxlong j = x * ns + n;
02287
02288 _mabscissa[x] = (cxdouble) x;
02289 _mexspectra[x] = _exspectra[j];
02290 _mexerrors[x] = _exerrors[j];
02291
02292 }
02293
02294 }
02295
02296
02297
02298
02299
02300
02301 status =
02302 _giraffe_rebin_interpolate_linear_error(mabscissa,
02303 mexspectra,
02304 mexerrors,
02305 mwavelength,
02306 mrbspectra,
02307 mrberrors);
02308
02309 for (x = 0; x < nwl; x++) {
02310
02311 register cxlong j = x * ns + n;
02312
02313 if ((-0.5 > _mwavelength[x]) || (_mwavelength[x] > nx1)) {
02314 _rbspectra[j] = 0.;
02315 _rberrors[j] = 0.;
02316 }
02317 else {
02318 _rbspectra[j] = _mrbspectra[x];
02319 _rberrors[j] = _mrberrors[x];
02320 }
02321
02322 }
02323
02324 }
02325
02326 }
02327
02328
02329 cpl_matrix_delete(mrbspectra);
02330 mrbspectra = NULL;
02331
02332 cpl_matrix_delete(mwavelength);
02333 mwavelength = NULL;
02334
02335 cpl_matrix_delete(mexspectra);
02336 mexspectra = NULL;
02337
02338 cpl_matrix_delete(mabscissa);
02339 mabscissa = NULL;
02340
02341 if (exerrors != NULL) {
02342 cpl_matrix_delete(mrberrors);
02343 mrberrors = NULL;
02344
02345 cpl_matrix_delete(mexerrors);
02346 mexerrors = NULL;
02347 }
02348
02349 cpl_msg_debug(fctid, "Rebinned %d spectra", ns);
02350
02351 return 0;
02352
02353 }
02354
02355
02375 inline static cxint
02376 _giraffe_resample_spline(cpl_image* rbspectra, cpl_image* rberrors,
02377 cpl_image* abscissa, cpl_image* exspectra,
02378 cpl_image* exerrors, cxint opt_direction)
02379 {
02380
02381 const cxchar* const fctid = "_giraffe_resample_spline";
02382
02383 register cxlong n = 0;
02384
02385 cxint status = 0;
02386 cxint nx = 0;
02387 cxint ns = 0;
02388 cxint nwl = 0;
02389
02390 cxdouble nx1 = 0.;
02391 cxdouble* _mabscissa = NULL;
02392 cxdouble* _mexspectra = NULL;
02393 cxdouble* _mexerrors = NULL;
02394 cxdouble* _mwavelength = NULL;
02395 cxdouble* _mrbspectra = NULL;
02396 cxdouble* _mrberrors = NULL;
02397 cxdouble* _abscissa = NULL;
02398 cxdouble* _exspectra = NULL;
02399 cxdouble* _exerrors = NULL;
02400 cxdouble* _rbspectra = NULL;
02401 cxdouble* _rberrors = NULL;
02402
02403 cpl_matrix* mabscissa = NULL;
02404 cpl_matrix* mwavelength = NULL;
02405 cpl_matrix* mexspectra = NULL;
02406 cpl_matrix* mexerrors = NULL;
02407 cpl_matrix* mrbspectra = NULL;
02408 cpl_matrix* mrberrors = NULL;
02409
02410
02411
02412 if ((abscissa == NULL) || (exspectra == NULL) || (rbspectra == NULL)) {
02413 return 1;
02414 }
02415
02416 if ((exerrors != NULL) && (rberrors == NULL)) {
02417 return 1;
02418 }
02419
02420
02421 nx = cpl_image_get_size_y(exspectra);
02422 ns = cpl_image_get_size_x(exspectra);
02423 nwl = cpl_image_get_size_y(abscissa);
02424
02425 if ((exerrors != NULL) &&
02426 ((nx != cpl_image_get_size_y(exerrors)) ||
02427 (ns != cpl_image_get_size_x(exerrors)))) {
02428 return 1;
02429 }
02430
02431 nx1 = nx - 0.5;
02432
02433 mabscissa = cpl_matrix_new(nx, 1);
02434 mexspectra = cpl_matrix_new(nx, 1);
02435
02436 mwavelength = cpl_matrix_new(nwl, 1);
02437 mrbspectra = cpl_matrix_new(nwl, 1);
02438
02439 _mabscissa = cpl_matrix_get_data(mabscissa);
02440 _mexspectra = cpl_matrix_get_data(mexspectra);
02441 _mwavelength = cpl_matrix_get_data(mwavelength);
02442 _mrbspectra = cpl_matrix_get_data(mrbspectra);
02443
02444 _abscissa = cpl_image_get_data_double(abscissa);
02445 _exspectra = cpl_image_get_data_double(exspectra);
02446 _rbspectra = cpl_image_get_data_double(rbspectra);
02447
02448 if (exerrors != NULL) {
02449 mexerrors = cpl_matrix_new(nx, 1);
02450 mrberrors = cpl_matrix_new(nwl, 1);
02451
02452 _mexerrors = cpl_matrix_get_data(mexerrors);
02453 _mrberrors = cpl_matrix_get_data(mrberrors);
02454
02455 _exerrors = cpl_image_get_data_double(exerrors);
02456 _rberrors = cpl_image_get_data_double(rberrors);
02457 }
02458
02459
02460
02461
02462
02463
02464
02465
02466 cpl_msg_debug(fctid, "Rebinning %d spectra, using dispersion direction "
02467 "%d and linear interpolation", ns, opt_direction);
02468
02469 for (n = 0; n < ns; n++) {
02470
02471 register cxlong x = 0;
02472
02473
02474 for (x = 0; x < nwl; x++) {
02475 register cxlong j = x * ns + n;
02476 _mwavelength[x] = _abscissa[j];
02477 }
02478
02479 if (exerrors == NULL) {
02480
02481 if (opt_direction < 0) {
02482
02483 for (x = 0; x < nx; x++) {
02484
02485 register cxlong j = x * ns + n;
02486 register cxlong k = nx - x - 1;
02487
02488 _mabscissa[x] = (cxdouble) x;
02489 _mexspectra[k] = _exspectra[j];
02490 }
02491
02492 }
02493 else {
02494
02495 for (x = 0; x < nx; x++) {
02496
02497 register cxlong j = x * ns + n;
02498
02499 _mabscissa[x] = (cxdouble) x;
02500 _mexspectra[x] = _exspectra[j];
02501
02502 }
02503
02504 }
02505
02506
02507
02508
02509
02510
02511 status = _giraffe_rebin_interpolate_spline(mabscissa,
02512 mexspectra,
02513 mwavelength,
02514 mrbspectra);
02515
02516 for (x = 0; x < nwl; x++) {
02517
02518 register cxlong j = x * ns + n;
02519
02520 if ((-0.5 > _mwavelength[x]) || (_mwavelength[x] > nx1)) {
02521 _rbspectra[j] = 0.;
02522 }
02523 else {
02524 _rbspectra[j] = _mrbspectra[x];
02525 }
02526
02527 }
02528
02529 }
02530 else {
02531
02532 if (opt_direction < 0) {
02533
02534 for (x = 0; x < nx; x++) {
02535
02536 register cxlong j = x * ns + n;
02537 register cxlong k = nx - x - 1;
02538
02539 _mabscissa[x] = (cxdouble) x;
02540 _mexspectra[k] = _exspectra[j];
02541 _mexerrors[k] = _exerrors[j];
02542 }
02543
02544 }
02545 else {
02546
02547 for (x = 0; x < nx; x++) {
02548
02549 register cxlong j = x * ns + n;
02550
02551 _mabscissa[x] = (cxdouble) x;
02552 _mexspectra[x] = _exspectra[j];
02553 _mexerrors[x] = _exerrors[j];
02554
02555 }
02556
02557 }
02558
02559
02560
02561
02562
02563
02564
02565 status = _giraffe_rebin_interpolate_spline(mabscissa,
02566 mexspectra,
02567 mwavelength,
02568 mrbspectra);
02569
02570 status = _giraffe_rebin_interpolate_linear(mabscissa,
02571 mexerrors,
02572 mwavelength,
02573 mrberrors);
02574
02575 for (x = 0; x < nwl; x++) {
02576
02577 register cxlong j = x * ns + n;
02578
02579 if ((-0.5 > _mwavelength[x]) || (_mwavelength[x] > nx1)) {
02580 _rbspectra[j] = 0.;
02581 _rberrors[j] = 0.;
02582 }
02583 else {
02584 _rbspectra[j] = _mrbspectra[x];
02585 _rberrors[j] = _mrberrors[x];
02586 }
02587
02588 }
02589
02590 }
02591
02592 }
02593
02594
02595 cpl_matrix_delete(mrbspectra);
02596 mrbspectra = NULL;
02597
02598 cpl_matrix_delete(mwavelength);
02599 mwavelength = NULL;
02600
02601 cpl_matrix_delete(mexspectra);
02602 mexspectra = NULL;
02603
02604 cpl_matrix_delete(mabscissa);
02605 mabscissa = NULL;
02606
02607 if (exerrors != NULL) {
02608 cpl_matrix_delete(mrberrors);
02609 mrberrors = NULL;
02610
02611 cpl_matrix_delete(mexerrors);
02612 mexerrors = NULL;
02613 }
02614
02615 cpl_msg_debug(fctid, "Rebinned %d spectra", ns);
02616
02617 return 0;
02618
02619 }
02620
02621
02695 static cxdouble
02696 giraffe_rebin_compute_opt_mod3(cxdouble xccd, cxdouble xfibre,
02697 cxdouble yfibre, cxdouble nx,
02698 cxdouble pixsize, cxdouble fcoll,
02699 cxdouble cfact, cxdouble gtheta,
02700 cxdouble gorder, cxdouble gspace,
02701 cxdouble slitdx, cxdouble slitdy,
02702 cxdouble slitphi)
02703 {
02704
02705
02706
02707
02708
02709 cxdouble xf, yf, d, t1, t12, t13, t18, t19, t2, t23, t28,
02710 t3, t31, t32, t36, t37, t39, t4, t40, t5, t62, t8, t9;
02711
02712
02713
02714
02715
02716
02717
02718 xf = xfibre * (1.0 + slitphi * yfibre) + slitdx;
02719 yf = yfibre * sqrt(1.0 - slitphi * slitphi) + slitdy;
02720 d = sqrt(xf * xf + yf * yf + fcoll * fcoll);
02721 t1 = cos(gtheta);
02722 t2 = xf*t1;
02723 t3 = xccd*xccd;
02724 t4 = pixsize*pixsize;
02725 t5 = t3*t4;
02726 t8 = sin(gtheta);
02727 t9 = fcoll*t8;
02728 t12 = cfact*cfact;
02729 t13 = fcoll*fcoll;
02730 t18 = nx*nx;
02731 t19 = t18*t4;
02732 t23 = xccd*t4*nx;
02733 t28 = t12*t13;
02734 t31 = yf*yf;
02735 t32 = d*d;
02736 t36 = 4.0*t28;
02737 t37 = t19+4.0*t5-4.0*t23+t36;
02738 t39 = t1*t1;
02739 t40 = t39*t4;
02740 t62 = sqrt((-t31+t32)*t37*(4.0*t40*t3-4.0*xccd*nx*t40 +
02741 8.0*xccd*t1*cfact*t9*pixsize+t19*t39 -
02742 4.0*cfact*fcoll*t8*nx*t1*pixsize+t36 -
02743 4.0*t28*t39));
02744
02745 return((4.0*t2*t5 + 4.0*t9*t5 + 4.0*t12*t13*fcoll*t8+t2*t19+t9*t19 -
02746 4.0*t9*t23 - 4.0*t2*t23 + 4.0*t28*t2+t62)*gspace/t37/gorder/d);
02747
02748 }
02749
02774 static cxdouble
02775 giraffe_rebin_compute_log_opt_mod3(cxdouble xccd, cxdouble xfibre,
02776 cxdouble yfibre, cxdouble nx,
02777 cxdouble pixsize, cxdouble fcoll,
02778 cxdouble cfact, cxdouble gtheta,
02779 cxdouble gorder, cxdouble gspace,
02780 cxdouble slitdx, cxdouble slitdy,
02781 cxdouble slitphi)
02782 {
02783
02784 return log(giraffe_rebin_compute_opt_mod3(xccd, xfibre, yfibre, nx,
02785 pixsize, fcoll, cfact, gtheta,
02786 gorder, gspace, slitdx, slitdy,
02787 slitphi));
02788
02789 }
02790
02837 static cxint
02838 giraffe_rebin_compute_lambda_range(GiFiberPosition *fiber_slit_position,
02839 cpl_matrix *opt_mod_params,
02840 cpl_matrix *grat_params,
02841 cxbool lambda_logarithmic,
02842 cxbool wlen_range_common,
02843 cxdouble *lambda_min, cxdouble *lambda_max)
02844 {
02845
02846
02847
02848
02849
02850 const cxchar *fctid = "giraffe_rebin_compute_lambda_range";
02851
02852 register cxlong n, ns;
02853 register cxdouble dx2, dnx, wl1, wl2;
02854
02855 double (*computeWl) (double, double, double, double, double, double,
02856 double, double, double, double, double, double,
02857 double);
02858
02859 cxdouble *pd_opt_mod_params = NULL,
02860 *pd_xfiber = NULL,
02861 *pd_yfiber = NULL,
02862 *pd_grat_params = NULL;
02863
02864 cxint nr_xfiber;
02865
02866
02867
02868
02869
02870 if (fiber_slit_position ==NULL) { return 1; }
02871 if (fiber_slit_position->x_fiber==NULL) { return 1; }
02872 if (fiber_slit_position->y_fiber==NULL) { return 1; }
02873 if (opt_mod_params ==NULL) { return 1; }
02874 if (grat_params ==NULL) { return 1; }
02875 if (lambda_min ==NULL) { return 1; }
02876 if (lambda_max ==NULL) { return 1; }
02877
02878 pd_opt_mod_params = cpl_matrix_get_data(opt_mod_params);
02879
02880 pd_xfiber = cpl_matrix_get_data(fiber_slit_position->x_fiber);
02881 nr_xfiber = cpl_matrix_get_nrow(fiber_slit_position->x_fiber);
02882
02883
02884
02885
02886
02887 if (lambda_logarithmic==TRUE) {
02888 computeWl = giraffe_rebin_compute_log_opt_mod3;
02889 } else {
02890 computeWl = giraffe_rebin_compute_opt_mod3;
02891 }
02892
02893 dnx = abs(pd_opt_mod_params[O_NX]);
02894 dx2 = dnx - 1.0;
02895 ns = nr_xfiber;
02896
02897 if (wlen_range_common==TRUE) {
02898 *lambda_min = 0.0;
02899 *lambda_max = CX_MAXDOUBLE;
02900 } else {
02901 *lambda_min = CX_MAXDOUBLE;
02902 *lambda_max = 0.0;
02903 }
02904
02905 pd_yfiber = cpl_matrix_get_data(fiber_slit_position->y_fiber);
02906 pd_grat_params = cpl_matrix_get_data(grat_params);
02907
02908 for (n = 0; n < ns; n++) {
02909
02910
02911 wl1 =
02912 computeWl(
02913 0.0,
02914 pd_xfiber[n],
02915 pd_yfiber[n],
02916 dnx,
02917 pd_opt_mod_params[O_PXSIZ],
02918 pd_opt_mod_params[O_FCOLL],
02919 pd_opt_mod_params[O_CFACT],
02920 pd_grat_params[G_THETA],
02921 pd_grat_params[G_ORDER],
02922 pd_grat_params[G_SPACE],
02923 pd_opt_mod_params[O_SOFFX],
02924 pd_opt_mod_params[O_SOFFY],
02925 pd_opt_mod_params[O_SPHI]
02926 );
02927
02928
02929 wl2 =
02930 computeWl(
02931 dx2,
02932 pd_xfiber[n],
02933 pd_yfiber[n],
02934 dnx,
02935 pd_opt_mod_params[O_PXSIZ],
02936 pd_opt_mod_params[O_FCOLL],
02937 pd_opt_mod_params[O_CFACT],
02938 pd_grat_params[G_THETA],
02939 pd_grat_params[G_ORDER],
02940 pd_grat_params[G_SPACE],
02941 pd_opt_mod_params[O_SOFFX],
02942 pd_opt_mod_params[O_SOFFY],
02943 pd_opt_mod_params[O_SPHI]
02944 );
02945
02946 if (wlen_range_common==TRUE) {
02947
02948
02949
02950 if (pd_opt_mod_params[O_NX] < 0) {
02951 *lambda_max = CX_MIN(*lambda_max, wl1);
02952 *lambda_min = CX_MAX(*lambda_min, wl2);
02953 } else {
02954 *lambda_max = CX_MIN(*lambda_max, wl2);
02955 *lambda_min = CX_MAX(*lambda_min, wl1);
02956 }
02957
02958 } else {
02959
02960
02961
02962 if (pd_opt_mod_params[O_NX] < 0) {
02963 *lambda_max = CX_MAX(*lambda_max, wl1);
02964 *lambda_min = CX_MIN(*lambda_min, wl2);
02965 } else {
02966 *lambda_max = CX_MAX(*lambda_max, wl2);
02967 *lambda_min = CX_MIN(*lambda_min, wl1);
02968 }
02969
02970 }
02971
02972 }
02973
02974 if (wlen_range_common==TRUE) {
02975
02976 *lambda_max = floor((*lambda_max) * GI_MM_TO_NM) / GI_MM_TO_NM;
02977 *lambda_min = ceil( (*lambda_min) * GI_MM_TO_NM) / GI_MM_TO_NM;
02978 } else {
02979
02980 *lambda_max = ceil( (*lambda_max) * GI_MM_TO_NM) / GI_MM_TO_NM;
02981 *lambda_min = floor((*lambda_min) * GI_MM_TO_NM) / GI_MM_TO_NM;
02982 }
02983
02984 cpl_msg_debug(fctid, "Rebinning lambda range now: [%12.6f,%12.6f]",
02985 *lambda_min, *lambda_max);
02986
02987 return 0;
02988
02989 }
02990
03013 static cpl_image*
03014 giraffe_rebin_compute_pixel_x_residuals(
03015 GiLocPosition *locPos,
03016 cpl_image *abcissa,
03017 GiSlitGeo *slitGeo,
03018 GiSlitGeo *xresiduals_limits,
03019 GiSlitGeo *xresiduals_coeff
03020 ) {
03021
03022
03023
03024
03025
03026 const cxchar *fctid = "giraffe_rebin_compute_pixel_x_residuals";
03027
03028 cxdouble xmin, xmax, ymin, ymax, yup, ylo, yccd, ywid;
03029 cxint n, m, x, xx, x0, i, j, k, l, xxp, x0p;
03030
03031 cxint subslit,
03032 nfibers,
03033 nmin,
03034 nmax,
03035 nlen,
03036 nx,
03037 ns,
03038 nwl,
03039 nf,
03040 nstart,
03041 ndata,
03042 nr_fit,
03043 nc_fit;
03044
03045 cpl_matrix *xss = NULL,
03046 *yss = NULL,
03047 *fit = NULL,
03048 *curr_xres_limits = NULL,
03049 *curr_xres_coeff = NULL;
03050
03051 cpl_image *x_residuals_img = NULL;
03052
03053 cpl_matrix *curr_subslit = NULL;
03054
03055 cxdouble *pd_curr_subslit = NULL,
03056 *pd_abcissa = NULL,
03057 *pd_xss = NULL,
03058 *pd_yss = NULL;
03059
03060 cxdouble *pd_locy = NULL,
03061 *pd_locw = NULL,
03062 *buffer = NULL,
03063 *pd_fit = NULL,
03064 *pd_x_residuals_img = NULL;
03065
03066
03067
03068
03069
03070
03071 if (locPos ==NULL) { return NULL; }
03072 if (locPos->centroids ==NULL) { return NULL; }
03073 if (locPos->widths ==NULL) { return NULL; }
03074 if (abcissa ==NULL) { return NULL; }
03075 if (slitGeo ==NULL) { return NULL; }
03076 if (xresiduals_limits ==NULL) { return NULL; }
03077 if (xresiduals_coeff ==NULL) { return NULL; }
03078
03079 nx = cpl_image_get_size_y(locPos->centroids);
03080 ns = cpl_image_get_size_x(locPos->centroids);
03081 nf = cpl_image_get_size_x(abcissa);
03082 nwl = cpl_image_get_size_y(abcissa);
03083
03084 cpl_msg_debug(
03085 fctid,
03086 "Computing pixel x residuals, using nr spec/nr lines/orig abcissa "
03087 "size: %d/%d/%d",
03088 ns,
03089 nwl,
03090 nx
03091 );
03092
03093
03094
03095
03096
03097 x_residuals_img = cpl_image_new(nf, nwl, CPL_TYPE_DOUBLE);
03098 pd_x_residuals_img = cpl_image_get_data_double(x_residuals_img);
03099 pd_abcissa = cpl_image_get_data_double(abcissa);
03100
03101 nstart = 0;
03102
03103 for (subslit = 0; subslit<_giraffe_slitgeo_size(slitGeo); subslit++) {
03104
03105 curr_subslit = _giraffe_slitgeo_get(slitGeo, subslit);
03106 pd_curr_subslit = cpl_matrix_get_data(curr_subslit);
03107
03108 giraffe_matrix_sort(curr_subslit);
03109
03110 curr_xres_limits =
03111 cpl_matrix_duplicate(
03112 _giraffe_slitgeo_get(xresiduals_limits, subslit)
03113 );
03114
03115 curr_xres_coeff =
03116 cpl_matrix_duplicate(
03117 _giraffe_slitgeo_get(xresiduals_coeff, subslit)
03118 );
03119
03120
03121 nfibers = cpl_matrix_get_nrow(curr_subslit);
03122
03123 nmin = (cxint) pd_curr_subslit[0];
03124 nmax = (cxint) pd_curr_subslit[nfibers - 1];
03125 nlen = nmax - nmin + 1;
03126 ndata = nwl * nfibers;
03127
03128 ymax = 0.0;
03129 ymin = CX_MAXDOUBLE;
03130
03131 xss = cpl_matrix_new(ndata, 1);
03132 yss = cpl_matrix_new(ndata, 1);
03133
03134 pd_xss = cpl_matrix_get_data(xss);
03135 pd_yss = cpl_matrix_get_data(yss);
03136
03137 pd_locy = cpl_image_get_data_double(locPos->centroids);
03138 pd_locw = cpl_image_get_data_double(locPos->widths);
03139
03140
03141 k = 0;
03142
03143 for (m = 0, n = 0; n < nfibers; n++, m++) {
03144
03145 i = 0;
03146
03147 for (x = 0; x < nwl; x++) {
03148
03149 j = x * nf + (nstart + n);
03150 x0 = (cxint) floor(pd_abcissa[j]);
03151 xx = (cxint) ceil(pd_abcissa[j]);
03152
03153 x0 = CX_MAX(CX_MIN(x0, nx - 1), 0);
03154 xx = CX_MAX(CX_MIN(xx, nx - 1), 0);
03155
03156 l = i * nfibers + m;
03157 xxp = xx * ns + cpl_matrix_get(curr_subslit, n, 0);
03158 x0p = x0 * ns + cpl_matrix_get(curr_subslit, n, 0);
03159
03160 pd_xss[l] = pd_abcissa[j];
03161
03162
03163
03164
03165
03166
03167 yccd = pd_locy[x0p];
03168 pd_yss[l] = yccd + ((pd_locy[xxp] - yccd) * (pd_xss[l] - x0));
03169
03170 ywid = pd_locw[x0p];
03171 ywid = ywid + ((pd_locw[xxp] - ywid) * (pd_xss[l] - x0));
03172
03173
03174 yup = yccd + ywid;
03175 ylo = yccd - ywid;
03176
03177
03178 if (ymax < yup) {
03179 ymax = yup;
03180 }
03181
03182 if (ymin > ylo) {
03183 ymin = ylo;
03184 }
03185
03186 ++i;
03187 ++k;
03188
03189 }
03190 }
03191
03192
03193 cpl_matrix_set_size(xss, k, 1);
03194 cpl_matrix_set_size(yss, k, 1);
03195 pd_xss = cpl_matrix_get_data(xss);
03196 pd_yss = cpl_matrix_get_data(yss);
03197
03198 xmin = cpl_matrix_get(curr_xres_limits, 0, 0);
03199 xmax = cpl_matrix_get(curr_xres_limits, 0, 1);
03200 ymin = cpl_matrix_get(curr_xres_limits, 0, 2);
03201 ymax = cpl_matrix_get(curr_xres_limits, 0, 3);
03202
03203 xmin = xmin < 0. ? 0. : xmin;
03204 xmax = xmax < 0. ? (cxdouble)nx : xmax;
03205
03206 ymin = ymin < 0. ? 0. : ymin;
03207 ymax = ymax < 0. ? 2048. : ymax;
03208
03209
03210 fit =
03211 giraffe_chebyshev_fit2d(
03212 xmin, ymin,
03213 (xmax - xmin),
03214 (ymax - ymin + 1.0),
03215 curr_xres_coeff,
03216 xss,
03217 yss
03218 );
03219
03220 cpl_matrix_delete(yss);
03221 cpl_matrix_delete(xss);
03222 cpl_matrix_delete(curr_xres_coeff);
03223 cpl_matrix_delete(curr_xres_limits);
03224
03225
03226 buffer = cpl_matrix_get_data(fit);
03227 cpl_matrix_unwrap(fit);
03228 fit = NULL;
03229
03230 fit = cpl_matrix_wrap(nwl, nfibers, buffer);
03231 pd_fit = cpl_matrix_get_data(fit);
03232 nr_fit = cpl_matrix_get_nrow(fit);
03233 nc_fit = cpl_matrix_get_ncol(fit);
03234
03235
03236 for (x = 0; x < nr_fit; x++) {
03237 for (k = nstart, n = 0; n < nc_fit; n++, k++) {
03238 pd_x_residuals_img[x * nf + k] = pd_fit[x * nc_fit + n];
03239 }
03240 }
03241
03242 cpl_matrix_delete(fit);
03243 fit = NULL;
03244
03245 nstart += nfibers;
03246
03247 }
03248
03249 cpl_msg_debug(
03250 fctid,
03251 "Computed pixel x residuals, returning image [%d,%d]",
03252 ns,
03253 nwl
03254 );
03255
03256 return x_residuals_img;
03257
03258 }
03259
03260
03293 static cpl_image*
03294 giraffe_rebin_compute_rebin_abcissa(GiFiberPosition* fiber_slit_position,
03295 GiLocPosition* locPos,
03296 GiSlitGeo* slitGeo,
03297 GiSlitGeo* xresiduals_limits,
03298 GiSlitGeo* xresiduals_coeff,
03299 cpl_matrix* grat_params,
03300 cpl_matrix* opt_mod_params,
03301 cpl_matrix* wloffsets,
03302 lmrq_model lmrq_opt_mod_x,
03303 GiRebinParams binPrms)
03304 {
03305
03306
03307
03308
03309
03310 const cxchar* const fctid = "giraffe_rebin_compute_rebin_abcissa";
03311
03312 cpl_matrix* wlengths = NULL;
03313 cpl_matrix* temp_params = NULL;
03314
03315 cpl_image* abcissa = NULL;
03316 cpl_image* x_residuals_img = NULL;
03317
03318 cxdouble* pd_wlengths = NULL;
03319 cxdouble* pd_temp_params = NULL;
03320 cxdouble* pd_opt_mod_params = NULL;
03321 cxdouble* pd_grat_params = NULL;
03322
03323
03324
03325
03326
03327 if (fiber_slit_position == NULL) {
03328 return NULL;
03329 }
03330
03331 if (locPos == NULL) {
03332 return NULL;
03333 }
03334
03335 if (slitGeo == NULL) {
03336 return NULL;
03337 }
03338
03339 if (grat_params == NULL) {
03340 return NULL;
03341 }
03342
03343 if (opt_mod_params == NULL) {
03344 return NULL;
03345 }
03346
03347 wlengths = cpl_matrix_new(binPrms.size, 1);
03348 pd_wlengths = cpl_matrix_get_data(wlengths);
03349
03350 temp_params = cpl_matrix_new(lmrq_opt_mod_x.nparams, 1);
03351
03352 pd_temp_params = cpl_matrix_get_data(temp_params);
03353 pd_opt_mod_params = cpl_matrix_get_data(opt_mod_params);
03354 pd_grat_params = cpl_matrix_get_data(grat_params);
03355
03356 pd_temp_params[OG_NX] = pd_opt_mod_params[O_NX];
03357 pd_temp_params[OG_PXSIZ] = pd_opt_mod_params[O_PXSIZ];
03358 pd_temp_params[OG_FCOLL] = pd_opt_mod_params[O_FCOLL];
03359 pd_temp_params[OG_CFACT] = pd_opt_mod_params[O_CFACT];
03360 pd_temp_params[OG_THETA] = pd_grat_params[G_THETA];
03361 pd_temp_params[OG_ORDER] = pd_grat_params[G_ORDER];
03362 pd_temp_params[OG_SPACE] = pd_grat_params[G_SPACE];
03363
03364 if (lmrq_opt_mod_x.nparams > OG_SOFFX) {
03365 pd_temp_params[OG_SOFFX] = pd_opt_mod_params[O_SOFFX];
03366 pd_temp_params[OG_SOFFY] = pd_opt_mod_params[O_SOFFY];
03367 pd_temp_params[OG_SPHI] = pd_opt_mod_params[O_SPHI];
03368 }
03369
03370
03371
03372
03373
03374
03375
03376
03377
03378 if (binPrms.log==TRUE) {
03379
03380 cxint i;
03381 for (i = 0; i < binPrms.size; i++) {
03382 pd_wlengths[i] = exp(binPrms.min + (cxdouble) i * binPrms.step);
03383 }
03384 } else {
03385 cxint i;
03386 for (i = 0; i < binPrms.size; i++) {
03387 pd_wlengths[i] = binPrms.min + (cxdouble) i * binPrms.step;
03388 }
03389 }
03390
03391 abcissa = _giraffe_compute_pixel_abscissa(wlengths, wloffsets,
03392 fiber_slit_position,
03393 temp_params, lmrq_opt_mod_x);
03394
03395
03396
03397
03398
03399
03400
03401 if ((binPrms.xres==TRUE) && (xresiduals_coeff!=NULL)) {
03402
03403 x_residuals_img =
03404 giraffe_rebin_compute_pixel_x_residuals(
03405 locPos,
03406 abcissa,
03407 slitGeo,
03408 xresiduals_limits,
03409 xresiduals_coeff
03410 );
03411
03412 cpl_image_subtract(abcissa, x_residuals_img);
03413 cpl_image_delete(x_residuals_img);
03414
03415 }
03416
03417 cpl_matrix_delete(wlengths);
03418 cpl_matrix_delete(temp_params);
03419
03420 cpl_msg_debug(fctid, "Processing complete : returning image "
03421 "[%" CPL_SIZE_FORMAT ", %" CPL_SIZE_FORMAT "]",
03422 cpl_image_get_size_x(abcissa), cpl_image_get_size_y(abcissa));
03423
03424 return abcissa;
03425
03426 }
03427
03455 inline static cxint
03456 _giraffe_resample_spectra(GiRebinning* result,
03457 const GiExtraction* extraction,
03458 const GiLocalization* localization,
03459 GiFiberPosition* fiber_position,
03460 GiSlitGeo* subslits,
03461 GiSlitGeo* xres_limits,
03462 GiSlitGeo* xres_coeff,
03463 GiBinnParams* xres_order,
03464 cpl_matrix* grating_data,
03465 cpl_matrix* optical_model,
03466 cpl_matrix* wlen_offsets,
03467 cxdouble rbstep,
03468 GiRebinMethod method,
03469 GiRebinRange range,
03470 GiRebinScale scale)
03471 {
03472
03473 const cxchar* const fctid = "_giraffe_resample_spectra";
03474
03475
03476 cxbool log_scale = FALSE;
03477
03478 cxint i = 0;
03479 cxint status = 0;
03480 cxint om_sign = 0;
03481 cxint rbsize = 0;
03482 cxint nspectra = 0;
03483
03484 cxdouble wlmin = 0.;
03485 cxdouble wlmax = 0.;
03486 cxdouble* _optical_model = NULL;
03487
03488 cpl_matrix* wavelengths = NULL;
03489
03490 cpl_image* _exspectra = NULL;
03491 cpl_image* _exerrors = NULL;
03492 cpl_image* _rbspectra = NULL;
03493 cpl_image* _rberrors = NULL;
03494 cpl_image* abscissa = NULL;
03495
03496 cpl_propertylist* properties = NULL;
03497
03498 GiImage* rbspectra = NULL;
03499 GiImage* rberrors = NULL;
03500
03501 GiLocPosition locPos;
03502
03503 GiRebinParams binPrms;
03504
03505 GiRebinInfo setup;
03506
03507
03508
03509
03510
03511
03512
03513 lmrq_model_id opt_mod_id = LMRQ_XOPTMOD2;
03514
03515
03516 if (result == NULL || extraction == NULL || localization == NULL) {
03517 return 1;
03518 }
03519
03520 if (result->spectra != NULL || result->errors != NULL) {
03521 return 1;
03522 }
03523
03524 if (extraction->spectra == NULL) {
03525 return 1;
03526 }
03527
03528 if (localization->locy == NULL || localization->locw == NULL) {
03529 return 1;
03530 }
03531
03532 if (fiber_position == NULL) {
03533 return 1;
03534 }
03535
03536 if (subslits == NULL) {
03537 return 1;
03538 }
03539
03540 if (grating_data == NULL) {
03541 return 1;
03542 }
03543
03544 if (optical_model == NULL) {
03545 return 1;
03546 }
03547
03548
03549 if (xres_coeff != NULL) {
03550 if (xres_limits == NULL || xres_order == NULL) {
03551 return 1;
03552 }
03553 }
03554
03555
03556
03557
03558
03559
03560
03561 _exspectra = giraffe_image_get(extraction->spectra);
03562
03563 if (extraction->error != NULL) {
03564 _exerrors = giraffe_image_get(extraction->error);
03565 }
03566
03567 _optical_model = cpl_matrix_get_data(optical_model);
03568
03569 nspectra = cpl_image_get_size_x(_exspectra);
03570
03571 om_sign = (_optical_model[O_NX] >= 0) ? 1 : -1;
03572
03573 if (scale == GIREBIN_SCALE_LOG) {
03574 log_scale = TRUE;
03575 }
03576
03577
03578
03579
03580
03581
03582 if (range == GIREBIN_RANGE_SETUP) {
03583
03584
03585
03586
03587
03588 wlmin = cpl_matrix_get(grating_data, 2, 0);
03589 wlmax = cpl_matrix_get(grating_data, 4, 0);
03590
03591 if (log_scale == TRUE) {
03592 wlmin = log(wlmin);
03593 wlmax = log(wlmax);
03594 }
03595
03596 }
03597 else {
03598
03599
03600
03601
03602
03603 status = giraffe_rebin_compute_lambda_range(fiber_position,
03604 optical_model,
03605 grating_data, log_scale,
03606 TRUE, &wlmin, &wlmax);
03607
03608 }
03609
03610 rbsize = 1 + (cxint) ((wlmax - wlmin) / rbstep);
03611
03612 if (rbsize < 0) {
03613
03614 cpl_msg_debug(fctid, "Invalid dispersion direction [%d], changing "
03615 "optical model orientation", om_sign);
03616
03617 om_sign = -om_sign;
03618 _optical_model[O_NX] = -_optical_model[O_NX];
03619
03620 status = giraffe_rebin_compute_lambda_range(fiber_position,
03621 optical_model,
03622 grating_data, log_scale,
03623 TRUE, &wlmin, &wlmax);
03624
03625 rbsize = 1 + (cxint) ((wlmax - wlmin) / rbstep);
03626
03627 }
03628
03629 if (rbsize < 1) {
03630 cpl_msg_error(fctid, "Invalid size %d of rebinned spectra, "
03631 "aborting...", rbsize);
03632 return 2;
03633 }
03634
03635
03636
03637
03638
03639
03640 locPos.type = GILOCDATATYPE_FITTED_DATA;
03641 locPos.centroids = giraffe_image_get(localization->locy);
03642 locPos.widths = giraffe_image_get(localization->locw);
03643
03644 binPrms.min = wlmin;
03645 binPrms.step = rbstep;
03646 binPrms.size = rbsize;
03647 binPrms.log = log_scale;
03648
03649 if (xres_coeff == NULL || (xres_order->xdeg == 0 &&
03650 xres_order->ydeg == 0)) {
03651 binPrms.xres = FALSE;
03652 }
03653 else {
03654 binPrms.xres = TRUE;
03655 }
03656
03657 abscissa = giraffe_rebin_compute_rebin_abcissa(fiber_position, &locPos,
03658 subslits, xres_limits,
03659 xres_coeff, grating_data,
03660 optical_model, wlen_offsets,
03661 lmrq_models[opt_mod_id],
03662 binPrms);
03663
03664
03665
03666
03667
03668
03669 wavelengths = cpl_matrix_new(rbsize, 1);
03670
03671 for (i = 0; i < rbsize; i++) {
03672 cpl_matrix_set(wavelengths, i, 0, wlmin + (cxdouble) i * rbstep);
03673 }
03674
03675 rbspectra = giraffe_image_create(CPL_TYPE_DOUBLE, nspectra, rbsize);
03676 _rbspectra = giraffe_image_get(rbspectra);
03677
03678 if (_exerrors != NULL) {
03679 rberrors = giraffe_image_create(CPL_TYPE_DOUBLE, nspectra, rbsize);
03680 _rberrors = giraffe_image_get(rberrors);
03681 }
03682
03683 switch (method) {
03684 case GIREBIN_METHOD_LINEAR:
03685 status = _giraffe_resample_linear(_rbspectra, _rberrors, abscissa,
03686 _exspectra, _exerrors, om_sign);
03687 break;
03688
03689 case GIREBIN_METHOD_SPLINE:
03690 status = _giraffe_resample_spline(_rbspectra, _rberrors, abscissa,
03691 _exspectra, _exerrors, om_sign);
03692 break;
03693
03694 default:
03695
03696
03697
03698 gi_error("Invalid rebinning method!");
03699 break;
03700 }
03701
03702 cpl_image_delete(abscissa);
03703 abscissa = NULL;
03704
03705 if (status != 0) {
03706 cpl_msg_error(fctid, "Error during rebinning, aborting...");
03707
03708 cpl_matrix_delete(wavelengths);
03709 wavelengths = NULL;
03710
03711 giraffe_image_delete(rbspectra);
03712 rbspectra = NULL;
03713
03714 if (rberrors != NULL) {
03715 giraffe_image_delete(rberrors);
03716 rberrors = NULL;
03717 }
03718
03719 return 3;
03720 }
03721
03722
03723
03724
03725
03726
03727
03728 switch (scale) {
03729 case GIREBIN_SCALE_LOG:
03730 {
03731 cxsize nw = cpl_matrix_get_nrow(wavelengths);
03732
03733 cxdouble mm2nm = log(GI_MM_TO_NM);
03734
03735 setup.wmin = mm2nm + cpl_matrix_get(wavelengths, 0, 0);
03736 setup.wcenter = mm2nm + cpl_matrix_get(wavelengths, nw / 2, 0);
03737 setup.wmax = mm2nm + cpl_matrix_get(wavelengths, nw - 1, 0);
03738 setup.wstep = rbstep;
03739
03740 setup.units = "log(nm)";
03741 setup.offset = 0;
03742 }
03743 break;
03744
03745 case GIREBIN_SCALE_LINEAR:
03746 {
03747 cxsize nw = cpl_matrix_get_nrow(wavelengths);
03748
03749 setup.wmin = GI_MM_TO_NM * cpl_matrix_get(wavelengths, 0, 0);
03750 setup.wcenter = GI_MM_TO_NM * cpl_matrix_get(wavelengths,
03751 nw / 2, 0);
03752 setup.wmax = GI_MM_TO_NM * cpl_matrix_get(wavelengths,
03753 nw - 1, 0);
03754 setup.wstep = GI_MM_TO_NM * rbstep;
03755
03756 setup.units = "nm";
03757 setup.offset = 0;
03758 }
03759 break;
03760
03761 default:
03762
03763
03764
03765 gi_error("Invalid scaling option!");
03766 break;
03767 }
03768
03769 cpl_matrix_delete(wavelengths);
03770 wavelengths = NULL;
03771
03772
03773 switch (method) {
03774 case GIREBIN_METHOD_LINEAR:
03775 setup.method = "linear";
03776 break;
03777
03778 case GIREBIN_METHOD_SPLINE:
03779 setup.method = "spline";
03780 break;
03781
03782 default:
03783
03784
03785
03786 gi_error("Invalid rebinning method!");
03787 break;
03788 }
03789
03790
03791 switch (scale) {
03792 case GIREBIN_SCALE_LINEAR:
03793 setup.scale = "linear";
03794 break;
03795
03796 case GIREBIN_SCALE_LOG:
03797 setup.scale = "logarithmic";
03798 break;
03799
03800 default:
03801
03802
03803
03804 gi_error("Invalid scaling option!");
03805 break;
03806 }
03807
03808 switch (range) {
03809 case GIREBIN_RANGE_SETUP:
03810 setup.range = "setup";
03811 break;
03812
03813 case GIREBIN_RANGE_COMMON:
03814 setup.range = "common";
03815 break;
03816
03817 default:
03818
03819
03820
03821 gi_error("Invalid range option!");
03822 break;
03823 }
03824
03825
03826
03827
03828
03829
03830 giraffe_error_push();
03831
03832 properties = giraffe_image_get_properties(extraction->spectra);
03833 giraffe_image_set_properties(rbspectra, properties);
03834
03835 if (cpl_error_get_code() != CPL_ERROR_NONE) {
03836 giraffe_image_delete(rbspectra);
03837 rbspectra = NULL;
03838
03839 if (rberrors != NULL) {
03840 giraffe_image_delete(rberrors);
03841 rberrors = NULL;
03842 }
03843
03844 return 4;
03845 }
03846
03847 giraffe_error_pop();
03848
03849 status = _giraffe_resample_update_properties(rbspectra, &setup);
03850
03851 if (status != 0) {
03852 giraffe_image_delete(rbspectra);
03853 rbspectra = NULL;
03854
03855 if (rberrors != NULL) {
03856 giraffe_image_delete(rberrors);
03857 rberrors = NULL;
03858 }
03859
03860 return 4;
03861 }
03862
03863
03864
03865
03866
03867
03868 if (_rberrors != NULL) {
03869
03870 giraffe_error_push();
03871
03872 properties = giraffe_image_get_properties(extraction->error);
03873 giraffe_image_set_properties(rberrors, properties);
03874
03875 if (cpl_error_get_code() != CPL_ERROR_NONE) {
03876 giraffe_image_delete(rbspectra);
03877 rbspectra = NULL;
03878
03879 if (rberrors != NULL) {
03880 giraffe_image_delete(rberrors);
03881 rberrors = NULL;
03882 }
03883
03884 return 5;
03885 }
03886
03887 giraffe_error_pop();
03888
03889 status = _giraffe_resample_update_properties(rberrors, &setup);
03890
03891 if (status != 0) {
03892 giraffe_image_delete(rbspectra);
03893 rbspectra = NULL;
03894
03895 if (rberrors != NULL) {
03896 giraffe_image_delete(rberrors);
03897 rberrors = NULL;
03898 }
03899
03900 return 5;
03901 }
03902
03903 }
03904
03905 result->spectra = rbspectra;
03906 result->errors = rberrors;
03907
03908 return 0;
03909
03910 }
03911
03912
03920 GiRange *
03921 giraffe_rebin_get_wavelength_range(GiImage *spectra, GiTable *wlsolution,
03922 GiTable *grating, GiTable *slitgeometry,
03923 cxbool common)
03924 {
03925
03926 cxint status = 0;
03927
03928 cxdouble min = 0.;
03929 cxdouble max = 0.;
03930
03931 cpl_matrix *optical_model = NULL;
03932 cpl_matrix *grating_data = NULL;
03933
03934 GiFiberPosition *positions = NULL;
03935 GiSlitGeo *subslits = NULL;
03936
03937 GiWcalSolution *wcal = NULL;
03938
03939 GiRange *range = NULL;
03940
03941
03942 if (spectra == NULL) {
03943 return NULL;
03944 }
03945
03946 if (grating == NULL) {
03947 return NULL;
03948 }
03949
03950 if (slitgeometry == NULL) {
03951 return NULL;
03952 }
03953
03954
03955 wcal = _giraffe_wcalsolution_create(wlsolution);
03956
03957 if (wcal == NULL) {
03958 return NULL;
03959 }
03960
03961 optical_model = _giraffe_rebin_setup_model(spectra, wcal);
03962
03963 if (optical_model == NULL) {
03964 _giraffe_wcalsolution_delete(wcal);
03965 return NULL;
03966 }
03967
03968 _giraffe_wcalsolution_delete(wcal);
03969
03970 grating_data = _giraffe_rebin_setup_grating(spectra, grating,
03971 wlsolution);
03972
03973 if (grating_data == NULL) {
03974
03975 cpl_matrix_delete(grating_data);
03976 cpl_matrix_delete(optical_model);
03977
03978 return NULL;
03979
03980 }
03981
03982 positions = _giraffe_fiberposition_new();
03983 subslits = _giraffe_slitgeo_new();
03984
03985 status = _giraffe_slitgeo_setup(slitgeometry, positions, subslits,
03986 FALSE);
03987
03988 if (status != 0) {
03989
03990 _giraffe_slitgeo_delete(subslits);
03991 _giraffe_fiberposition_delete(positions);
03992
03993 cpl_matrix_delete(grating_data);
03994 cpl_matrix_delete(optical_model);
03995
03996 return NULL;
03997
03998 }
03999
04000 status = giraffe_rebin_compute_lambda_range(positions, optical_model,
04001 grating_data,
04002 GIREBIN_SCALE_LINEAR,
04003 common, &min, &max);
04004
04005
04006
04007
04008
04009 min *= GI_MM_TO_NM;
04010 max *= GI_MM_TO_NM;
04011
04012 _giraffe_slitgeo_delete(subslits);
04013 _giraffe_fiberposition_delete(positions);
04014
04015 cpl_matrix_delete(grating_data);
04016 cpl_matrix_delete(optical_model);
04017
04018 range = giraffe_range_create(min, max);
04019
04020 return range;
04021
04022 }
04023
04024
04058 cxint
04059 giraffe_rebin_spectra(GiRebinning *rebinning,
04060 const GiExtraction *extraction,
04061 const GiTable *fibers,
04062 const GiLocalization *localization,
04063 const GiTable *grating,
04064 const GiTable *slitgeo,
04065 const GiTable *solution,
04066 const GiRebinConfig *config)
04067 {
04068
04069 const cxchar* const fctid = "giraffe_rebin_spectra";
04070
04071
04072 cxint status = 0;
04073 cxint ex_sp_extr_pixels = 0;
04074 cxint calc_rebinned_size = 0;
04075 cxint default_rebinned_size = GIREBIN_SIZE_Y_DEFAULT;
04076
04077 cxdouble rbin_multiplier = 0.;
04078 cxdouble ex_sp_pixsize_x = 0.;
04079 cxdouble rbin_stepsize = 0.;
04080
04081 cpl_matrix* grat_params = NULL;
04082 cpl_matrix* opt_mod_params = NULL;
04083 cpl_matrix* wloffsets = NULL;
04084
04085 cpl_table* _fibers = NULL;
04086
04087 cpl_propertylist* _pl_ext_sp = NULL;
04088 cpl_propertylist* _pl_wsol = NULL;
04089
04090 GiImage* ex_sp_frame = NULL;
04091 GiImage* ex_sp_err_frame = NULL;
04092 GiImage* loc_y_frame = NULL;
04093 GiImage* loc_w_frame = NULL;
04094
04095 GiSlitGeo* subslit_fibers = NULL;
04096 GiSlitGeo* wav_coeffs = NULL;
04097 GiSlitGeo* wav_limits = NULL;
04098
04099 GiGrat* grating_data = NULL;
04100
04101 GiFiberPosition* fiber_slit_position = NULL;
04102
04103 GiWcalSolution* wcalib_solution = NULL;
04104
04105 GiBinnParams xres_polynom_deg = {0, 0};
04106
04107
04108
04109
04110
04111
04112
04113 if (extraction == NULL) {
04114 cpl_msg_error(fctid, "No extracted data, aborting...");
04115 return 1;
04116 }
04117
04118 if (extraction->spectra == NULL) {
04119 cpl_msg_error(fctid, "No extracted spectra, aborting...");
04120 return 1;
04121 }
04122
04123 if (fibers == NULL) {
04124 cpl_msg_error(fctid, "No fiber table, aborting ...");
04125 return 1;
04126 }
04127
04128 if (localization == NULL) {
04129 cpl_msg_error(fctid, "No localization data, aborting...");
04130 return 1;
04131 }
04132
04133 if (localization->locy == NULL) {
04134 cpl_msg_error(fctid, "No localization centroids, aborting...");
04135 return 1;
04136 }
04137
04138 if (localization->locw == NULL) {
04139 cpl_msg_error(fctid, "No localization widths, aborting...");
04140 return 1;
04141 }
04142
04143 if (grating == NULL) {
04144 cpl_msg_error(fctid, "No grating data, aborting...");
04145 return 1;
04146 }
04147
04148 if (rebinning == NULL) {
04149 cpl_msg_error(fctid, "No rebinning results container, aborting...");
04150 return 1;
04151 }
04152
04153 if (config == NULL) {
04154 cpl_msg_error(fctid, "No rebinning configuration data, aborting...");
04155 return 1;
04156 }
04157
04158 if (solution == NULL) {
04159 cpl_msg_error(fctid, "No wavecalibration solution, aborting...");
04160 return 1;
04161 }
04162
04163 ex_sp_frame = extraction->spectra;
04164 ex_sp_err_frame = extraction->error;
04165 loc_y_frame = localization->locy;
04166 loc_w_frame = localization->locw;
04167
04168 _pl_ext_sp = giraffe_image_get_properties(ex_sp_frame);
04169 _pl_wsol = giraffe_table_get_properties(solution);
04170
04171
04172 _fibers = giraffe_table_get(fibers);
04173 cx_assert(_fibers != NULL);
04174
04175
04176
04177
04178
04179
04180
04181
04182
04183
04184
04185 if (cpl_propertylist_has(_pl_ext_sp, GIALIAS_PIXSIZX) == TRUE) {
04186 ex_sp_pixsize_x = cpl_propertylist_get_double(_pl_ext_sp,
04187 GIALIAS_PIXSIZX);
04188
04189 }
04190 else {
04191 cpl_msg_error(fctid, "%s Keyword missing in Extracted Spectra "
04192 "Frame, aborting ...", GIALIAS_PIXSIZX);
04193 return 2;
04194 }
04195
04196
04197
04198
04199
04200
04201 if (ex_sp_pixsize_x > 1.) {
04202 ex_sp_pixsize_x /= 1000.;
04203 }
04204
04205
04206
04207
04208
04209
04210 if (cpl_propertylist_has(_pl_ext_sp, GIALIAS_GRATNAME) == TRUE) {
04211
04212 const cxchar* _string = NULL;
04213
04214 _string = cpl_propertylist_get_string(_pl_ext_sp, GIALIAS_GRATNAME);
04215
04216 if (strncmp(_string, "LR", 2) == 0) {
04217 rbin_multiplier = 4.;
04218 }
04219 else if (strncmp(_string, "HR", 2) == 0) {
04220 rbin_multiplier = 1.;
04221 }
04222 else {
04223 rbin_multiplier = 1.;
04224 }
04225
04226 }
04227 else {
04228 cpl_msg_error(fctid, "%s Keyword missing in Extracted Spectra Frame, "
04229 "aborting ...", GIALIAS_GRATNAME);
04230 return 2;
04231 }
04232
04233
04234
04235
04236
04237
04238 if (cpl_propertylist_has(_pl_ext_sp, GIALIAS_EXT_NX) == TRUE) {
04239 ex_sp_extr_pixels = cpl_propertylist_get_int(_pl_ext_sp,
04240 GIALIAS_EXT_NX);
04241
04242 }
04243 else {
04244 cpl_msg_error(fctid, "%s Keyword missing in Extracted Spectra Frame, "
04245 "aborting ...", GIALIAS_EXT_NX);
04246 return 2;
04247 }
04248
04249
04250
04251
04252
04253
04254 grating_data = _giraffe_grating_new();
04255
04256 status = _giraffe_grating_setup(grating, ex_sp_frame, grating_data);
04257
04258 if (status != 0) {
04259 cpl_msg_error(fctid, "Unable to retrieve grating information, "
04260 "aborting...");
04261 _giraffe_grating_delete(grating_data);
04262 return 3;
04263 }
04264
04265
04266
04267
04268
04269 fiber_slit_position = _giraffe_fiberposition_new();
04270 subslit_fibers = _giraffe_slitgeo_new();
04271
04272 status = _giraffe_slitgeo_setup(slitgeo, fiber_slit_position,
04273 subslit_fibers, FALSE);
04274
04275 if (status != 0) {
04276 cpl_msg_error(fctid, "Unable to retrieve slit geometry information, "
04277 "aborting...");
04278 _giraffe_grating_delete(grating_data);
04279 _giraffe_fiberposition_delete(fiber_slit_position);
04280 _giraffe_slitgeo_delete(subslit_fibers);
04281 return 7;
04282 }
04283
04284
04285 wcalib_solution = _giraffe_wcalsolution_create(solution);
04286
04287 if (wcalib_solution == NULL) {
04288 cpl_msg_error(fctid, "Cannot create wavelength solution, "
04289 "aborting ...");
04290 _giraffe_grating_delete(grating_data);
04291 _giraffe_fiberposition_delete(fiber_slit_position);
04292 _giraffe_slitgeo_delete(subslit_fibers);
04293 return 4;
04294 }
04295
04296 if (cpl_propertylist_has(_pl_wsol, GIALIAS_WSOL_OMFCOLL) == TRUE) {
04297 grating_data->fcoll =
04298 cpl_propertylist_get_double(_pl_wsol, GIALIAS_WSOL_OMFCOLL);
04299 }
04300
04301 if (cpl_propertylist_has(_pl_wsol, GIALIAS_WSOL_OMGCAM) == TRUE) {
04302 grating_data->gcam =
04303 cpl_propertylist_get_double(_pl_wsol, GIALIAS_WSOL_OMGCAM);
04304 }
04305
04306 if (cpl_propertylist_has(_pl_wsol, GIALIAS_WSOL_OMGTHETA) == TRUE) {
04307 grating_data->theta =
04308 cpl_propertylist_get_double(_pl_wsol, GIALIAS_WSOL_OMGTHETA);
04309 }
04310
04311 if (cpl_propertylist_has(_pl_wsol, GIALIAS_WSOL_OMSDX) == TRUE) {
04312 grating_data->slitdx =
04313 cpl_propertylist_get_double(_pl_wsol, GIALIAS_WSOL_OMSDX);
04314 }
04315
04316 if (cpl_propertylist_has(_pl_wsol, GIALIAS_WSOL_OMSDY) == TRUE) {
04317 grating_data->slitdy =
04318 cpl_propertylist_get_double(_pl_wsol, GIALIAS_WSOL_OMSDY);
04319 }
04320
04321 if (cpl_propertylist_has(_pl_wsol, GIALIAS_WSOL_OMSPHI) == TRUE) {
04322 grating_data->slitphi =
04323 cpl_propertylist_get_double(_pl_wsol, GIALIAS_WSOL_OMSPHI);
04324 }
04325
04326
04327
04328
04329
04330
04331
04332
04333 if (cpl_table_has_column(_fibers, "WLRES") != 0) {
04334
04335 cxint fiber = 0;
04336 cxint nfibers = cpl_table_get_nrow(_fibers);
04337
04338
04339 wloffsets = cpl_matrix_new(nfibers, 1);
04340
04341 for (fiber = 0; fiber < nfibers; ++fiber) {
04342
04343 cxdouble wloffset = cpl_table_get_double(_fibers, "WLRES",
04344 fiber, NULL);
04345
04346
04347 wloffset *= -GI_NM_TO_MM;
04348 cpl_matrix_set(wloffsets, fiber, 0, wloffset);
04349
04350 }
04351
04352 cpl_msg_info(fctid, "Applying SIMCAL wavelength corrections ...");
04353
04354 }
04355
04356
04357
04358
04359
04360
04361
04362
04363
04364
04365
04366
04367 if (config->scmethod == GIREBIN_SCALE_LOG) {
04368
04369 cxint rebin_size;
04370
04371 cxdouble wlenmax;
04372 cxdouble wlenmin;
04373
04374 rebin_size = default_rebinned_size;
04375
04376 wlenmin = log(grating_data->wlenmin / GI_MM_TO_NM);
04377 wlenmax = log(grating_data->wlenmax / GI_MM_TO_NM);
04378
04379 if ((config->size != rebin_size) && (config->size != 0)) {
04380 rebin_size = config->size;
04381 }
04382
04383 rbin_stepsize = (wlenmax - wlenmin) / rebin_size;
04384
04385 calc_rebinned_size = 1 + (cxint) ((wlenmax-wlenmin)/ rbin_stepsize);
04386
04387 }
04388 else {
04389
04390 cxint rebin_size;
04391
04392 cxdouble wlenmax;
04393 cxdouble wlenmin;
04394
04395 wlenmin = grating_data->wlenmin / GI_MM_TO_NM;
04396 wlenmax = grating_data->wlenmax / GI_MM_TO_NM;
04397
04398 rbin_stepsize = (config->lstep / GI_MM_TO_NM) * rbin_multiplier;
04399 rebin_size = (wlenmax - wlenmin) / rbin_stepsize;
04400
04401 if ((config->size != rebin_size) && (config->size != 0)) {
04402 rebin_size = config->size;
04403 rbin_stepsize = (wlenmax - wlenmin) / rebin_size;
04404 }
04405
04406 calc_rebinned_size = 1 + (cxint) ((wlenmax-wlenmin) / rbin_stepsize);
04407
04408 }
04409
04410
04411
04412
04413
04414 if (wcalib_solution!=NULL) {
04415
04416 if (wcalib_solution->opt_mod==LMRQ_XOPTMOD) {
04417
04418 cxint nrow;
04419 cxdouble opt_direction, fcoll, cfact;
04420
04421 nrow = cpl_matrix_get_nrow(wcalib_solution->opt_mod_params);
04422 if (nrow==4) {
04423 opt_direction =
04424 cpl_matrix_get(wcalib_solution->opt_mod_params, 0, 0);
04425 fcoll =
04426 cpl_matrix_get(wcalib_solution->opt_mod_params, 1, 0);
04427 cfact =
04428 cpl_matrix_get(wcalib_solution->opt_mod_params, 2, 0);
04429
04430 opt_mod_params = cpl_matrix_new(4,1);
04431 cpl_matrix_set(opt_mod_params, 0, 0,
04432 ex_sp_extr_pixels * opt_direction);
04433 cpl_matrix_set(opt_mod_params, 1, 0, ex_sp_pixsize_x);
04434 cpl_matrix_set(opt_mod_params, 2, 0, fcoll);
04435 cpl_matrix_set(opt_mod_params, 3, 0, cfact);
04436 }
04437 else {
04438 cpl_msg_error(fctid, "Invalid number of physical optical "
04439 "parameters, aborting...");
04440
04441 if (wloffsets != NULL) {
04442 cpl_matrix_delete(wloffsets);
04443 }
04444
04445 _giraffe_wcalsolution_delete(wcalib_solution);
04446 _giraffe_grating_delete(grating_data);
04447 _giraffe_fiberposition_delete(fiber_slit_position);
04448 _giraffe_slitgeo_delete(subslit_fibers);
04449 return 6;
04450 }
04451
04452 }
04453 else if (wcalib_solution->opt_mod==LMRQ_XOPTMOD2) {
04454
04455 cxint nrow;
04456 cxdouble opt_direction, fcoll, cfact, gtheta, slitdx,
04457 slitdy, slitphi;
04458
04459 nrow = cpl_matrix_get_nrow(wcalib_solution->opt_mod_params);
04460 if (nrow==7) {
04461 opt_direction =
04462 cpl_matrix_get(wcalib_solution->opt_mod_params, 0, 0);
04463 fcoll =
04464 cpl_matrix_get(wcalib_solution->opt_mod_params, 1, 0);
04465 cfact =
04466 cpl_matrix_get(wcalib_solution->opt_mod_params, 2, 0);
04467 gtheta =
04468 cpl_matrix_get(wcalib_solution->opt_mod_params, 3, 0);
04469 slitdx =
04470 cpl_matrix_get(wcalib_solution->opt_mod_params, 4, 0);
04471 slitdy =
04472 cpl_matrix_get(wcalib_solution->opt_mod_params, 5, 0);
04473 slitphi =
04474 cpl_matrix_get(wcalib_solution->opt_mod_params, 6, 0);
04475
04476 opt_mod_params = cpl_matrix_new(7,1);
04477 cpl_matrix_set(opt_mod_params, 0, 0,
04478 ex_sp_extr_pixels * opt_direction);
04479 cpl_matrix_set(opt_mod_params, 1, 0, ex_sp_pixsize_x);
04480 cpl_matrix_set(opt_mod_params, 2, 0, fcoll);
04481 cpl_matrix_set(opt_mod_params, 3, 0, cfact);
04482 cpl_matrix_set(opt_mod_params, 4, 0, slitdx);
04483 cpl_matrix_set(opt_mod_params, 5, 0, slitdy);
04484 cpl_matrix_set(opt_mod_params, 6, 0, slitphi);
04485
04486 }
04487 else {
04488 cpl_msg_error(fctid, "Invalid number of physical optical "
04489 "parameters, aborting...");
04490
04491 if (wloffsets != NULL) {
04492 cpl_matrix_delete(wloffsets);
04493 }
04494
04495 _giraffe_wcalsolution_delete(wcalib_solution);
04496 _giraffe_grating_delete(grating_data);
04497 _giraffe_fiberposition_delete(fiber_slit_position);
04498 _giraffe_slitgeo_delete(subslit_fibers);
04499 return 6;
04500 }
04501
04502 }
04503 else {
04504 cpl_msg_error(fctid, "Invalid optical model, aborting...");
04505
04506 if (wloffsets != NULL) {
04507 cpl_matrix_delete(wloffsets);
04508 }
04509
04510 _giraffe_wcalsolution_delete(wcalib_solution);
04511 _giraffe_grating_delete(grating_data);
04512 _giraffe_fiberposition_delete(fiber_slit_position);
04513 _giraffe_slitgeo_delete(subslit_fibers);
04514 return 5;
04515 }
04516
04517
04518 if (wcalib_solution->wav_coeffs != NULL) {
04519
04520 GiSlitGeo* coeffs = wcalib_solution->wav_coeffs;
04521
04522 xres_polynom_deg.xdeg =
04523 cpl_matrix_get_nrow(_giraffe_slitgeo_get(coeffs, 0));
04524 xres_polynom_deg.ydeg =
04525 cpl_matrix_get_ncol(_giraffe_slitgeo_get(coeffs, 0));
04526 }
04527
04528 }
04529 else {
04530 cpl_msg_error(fctid, "No Wavelength Calibration solution found, "
04531 "aborting...");
04532
04533 if (wloffsets != NULL) {
04534 cpl_matrix_delete(wloffsets);
04535 }
04536
04537 _giraffe_wcalsolution_delete(wcalib_solution);
04538 _giraffe_grating_delete(grating_data);
04539 _giraffe_fiberposition_delete(fiber_slit_position);
04540 _giraffe_slitgeo_delete(subslit_fibers);
04541 return 4;
04542 }
04543
04544 if (config->xresiduals==FALSE) {
04545 xres_polynom_deg.xdeg = 0;
04546 xres_polynom_deg.ydeg = 0;
04547 }
04548
04549 if (wcalib_solution->wav_coeffs!=NULL) {
04550 wav_coeffs = wcalib_solution->wav_coeffs;
04551 }
04552
04553 if (wcalib_solution->wav_limits!=NULL) {
04554 wav_limits = wcalib_solution->wav_limits;
04555 }
04556
04557
04558
04559
04560
04561
04562 grat_params = cpl_matrix_new(7,1);
04563
04564 cpl_matrix_set(grat_params, 0, 0, grating_data->theta);
04565 cpl_matrix_set(grat_params, 1, 0, grating_data->order);
04566 cpl_matrix_set(grat_params, 2, 0, grating_data->wlenmin / GI_MM_TO_NM);
04567 cpl_matrix_set(grat_params, 3, 0, grating_data->wlen0 / GI_MM_TO_NM);
04568 cpl_matrix_set(grat_params, 4, 0, grating_data->wlenmax / GI_MM_TO_NM);
04569 cpl_matrix_set(grat_params, 5, 0, grating_data->resol);
04570 cpl_matrix_set(grat_params, 6, 0, grating_data->space );
04571
04572
04573
04574
04575
04576
04577 cpl_msg_info(fctid, "Performing Rebinning of spectra, stepsize=%.4f "
04578 "[nm], resulting image size=%d, using x residuals : %s",
04579 rbin_stepsize * GI_MM_TO_NM, calc_rebinned_size,
04580 config->xresiduals ? "Yes" : "No");
04581
04582
04583 switch (config->rmethod) {
04584 case GIREBIN_METHOD_LINEAR:
04585 cpl_msg_info(fctid, "Rebinning method : linear");
04586 break;
04587
04588 case GIREBIN_METHOD_SPLINE:
04589 cpl_msg_info(fctid, "Rebinning method : spline");
04590 break;
04591
04592 default:
04593 cpl_msg_info(fctid, "Rebinning method : undefined");
04594 break;
04595 }
04596
04597 switch (config->scmethod) {
04598 case GIREBIN_SCALE_LOG:
04599 cpl_msg_info(fctid, "Scaling method : logarithmic, "
04600 "log(wavelength [nm]): min,max,range = %.3f, %.3f, %.3f",
04601 log(grating_data->wlenmin),
04602 log(grating_data->wlenmax),
04603 log(grating_data->wlenmax) -
04604 log(grating_data->wlenmin));
04605 break;
04606
04607 case GIREBIN_SCALE_LINEAR:
04608 cpl_msg_info(fctid, "Scaling method : linear, wavelength [nm]: "
04609 "min,max,range = %.3f, %.3f, %.3f",
04610 grating_data->wlenmin,
04611 grating_data->wlenmax,
04612 grating_data->wlenmax - grating_data->wlenmin);
04613 break;
04614
04615 default:
04616 cpl_msg_info(fctid, "Scaling method : undefined");
04617 break;
04618 }
04619
04620 switch (config->range) {
04621 case GIREBIN_RANGE_SETUP:
04622 cpl_msg_info(fctid, "Wavelength range : Setup");
04623 break;
04624
04625 case GIREBIN_RANGE_COMMON:
04626 cpl_msg_info(fctid, "Wavelength range : Common");
04627 break;
04628
04629 default:
04630 cpl_msg_info(fctid, "Wavelength range : undefined");
04631 break;
04632 }
04633
04634
04635
04636
04637
04638
04639 status = _giraffe_resample_spectra(rebinning, extraction,
04640 localization, fiber_slit_position,
04641 subslit_fibers, wav_limits,
04642 wav_coeffs, &xres_polynom_deg,
04643 grat_params, opt_mod_params,
04644 wloffsets, rbin_stepsize,
04645 config->rmethod, config->range,
04646 config->scmethod);
04647
04648 if (status != 0) {
04649
04650 if (wloffsets != NULL) {
04651 cpl_matrix_delete(wloffsets);
04652 }
04653
04654 cpl_matrix_delete(opt_mod_params);
04655 cpl_matrix_delete(grat_params);
04656
04657 _giraffe_wcalsolution_delete(wcalib_solution);
04658 _giraffe_grating_delete(grating_data);
04659 _giraffe_fiberposition_delete(fiber_slit_position);
04660 _giraffe_slitgeo_delete(subslit_fibers);
04661
04662 return 8;
04663
04664 }
04665
04666
04667
04668
04669
04670
04671 if (wloffsets != NULL) {
04672 cpl_matrix_delete(wloffsets);
04673 }
04674
04675 cpl_matrix_delete(opt_mod_params);
04676 cpl_matrix_delete(grat_params);
04677
04678 _giraffe_wcalsolution_delete(wcalib_solution);
04679 _giraffe_grating_delete(grating_data);
04680 _giraffe_fiberposition_delete(fiber_slit_position);
04681 _giraffe_slitgeo_delete(subslit_fibers);
04682
04683 return 0;
04684
04685 }
04686
04687
04700 GiRebinning*
04701 giraffe_rebinning_new(void)
04702 {
04703
04704 GiRebinning *rebinn = cx_malloc(sizeof(GiRebinning));
04705
04706 rebinn->spectra = NULL;
04707 rebinn->errors = NULL;
04708
04709 return rebinn;
04710
04711 }
04712
04729 GiRebinning*
04730 giraffe_rebinning_create(GiImage *spectra, GiImage *errors)
04731 {
04732
04733 GiRebinning *rebin = giraffe_rebinning_new();
04734
04735 if (spectra) {
04736 rebin->spectra = spectra;
04737 }
04738
04739 if (errors) {
04740 rebin->errors = errors;
04741 }
04742
04743 return rebin;
04744
04745 }
04746
04747
04766 void
04767 giraffe_rebinning_delete(GiRebinning *rebinning)
04768 {
04769
04770 if (rebinning) {
04771 cx_free(rebinning);
04772 }
04773
04774 return;
04775
04776 }
04777
04778
04794 void
04795 giraffe_rebinning_destroy(GiRebinning *rebinning)
04796 {
04797
04798 if (rebinning) {
04799
04800 if (rebinning->spectra) {
04801 giraffe_image_delete(rebinning->spectra);
04802 rebinning->spectra = NULL;
04803 }
04804
04805 if (rebinning->errors) {
04806 giraffe_image_delete(rebinning->errors);
04807 rebinning->errors = NULL;
04808 }
04809
04810 cx_free(rebinning);
04811 }
04812
04813 return;
04814
04815 }
04816
04817
04832 GiRebinConfig *
04833 giraffe_rebin_config_create(cpl_parameterlist *list)
04834 {
04835
04836 const cxchar *fctid = "giraffe_rebin_config_create";
04837
04838 const cxchar *s;
04839
04840 cpl_parameter *p;
04841
04842 GiRebinConfig *config = NULL;
04843
04844
04845 if (!list) {
04846 return NULL;
04847 }
04848
04849 config = cx_calloc(1, sizeof *config);
04850
04851
04852 config->rmethod = GIREBIN_METHOD_UNDEFINED;
04853 config->xresiduals = FALSE;
04854 config->lstep = 0.0;
04855 config->scmethod = GIREBIN_SCALE_UNDEFINED;
04856 config->size = 0;
04857 config->range = GIREBIN_RANGE_UNDEFINED;
04858
04859
04860 p = cpl_parameterlist_find(list, "giraffe.rebinning.method");
04861 s = cpl_parameter_get_string(p);
04862 if (strcmp(s, "linear")==0) {
04863 config->rmethod = GIREBIN_METHOD_LINEAR;
04864 } else if (strcmp(s, "spline")==0) {
04865 config->rmethod = GIREBIN_METHOD_SPLINE;
04866 }
04867
04868 p = cpl_parameterlist_find(list, "giraffe.rebinning.xresiduals");
04869 config->xresiduals = cpl_parameter_get_bool(p);
04870
04871 p = cpl_parameterlist_find(list, "giraffe.rebinning.lstep");
04872 config->lstep = cpl_parameter_get_double(p);
04873
04874 p = cpl_parameterlist_find(list, "giraffe.rebinning.scalemethod");
04875 s = cpl_parameter_get_string(p);
04876 if (strcmp(s, "log")==0) {
04877 config->scmethod = GIREBIN_SCALE_LOG;
04878 } else if (strcmp(s, "linear")==0) {
04879 config->scmethod = GIREBIN_SCALE_LINEAR;
04880 }
04881
04882 p = cpl_parameterlist_find(list, "giraffe.rebinning.size");
04883 config->size = cpl_parameter_get_int(p);
04884
04885 p = cpl_parameterlist_find(list, "giraffe.rebinning.range");
04886 s = cpl_parameter_get_string(p);
04887 if (strcmp(s, "setup")==0) {
04888 config->range = GIREBIN_RANGE_SETUP;
04889 } else if (strcmp(s, "common")==0) {
04890 config->range = GIREBIN_RANGE_COMMON;
04891 }
04892
04893
04894
04895 if (config->rmethod==GIREBIN_METHOD_UNDEFINED) {
04896 cpl_msg_info(fctid, "Invalid Rebinning method, aborting");
04897 cx_free(config);
04898 return NULL;
04899 }
04900
04901 if (config->scmethod==GIREBIN_SCALE_UNDEFINED) {
04902 cpl_msg_info(fctid, "Invalid Rebinning scaling method, aborting");
04903 cx_free(config);
04904 return NULL;
04905 }
04906
04907 if (config->range==GIREBIN_RANGE_UNDEFINED) {
04908 cpl_msg_info(fctid, "Invalid Rebinning range, aborting");
04909 cx_free(config);
04910 return NULL;
04911 }
04912
04913 return config;
04914
04915 }
04916
04917
04932 void
04933 giraffe_rebin_config_destroy(GiRebinConfig *config)
04934 {
04935
04936 if (config) {
04937 cx_free(config);
04938 }
04939
04940 return;
04941
04942 }
04943
04956 void
04957 giraffe_rebin_config_add(cpl_parameterlist *list)
04958 {
04959
04960 cpl_parameter *p;
04961
04962 if (!list) {
04963 return;
04964 }
04965
04966 p = cpl_parameter_new_enum("giraffe.rebinning.method",
04967 CPL_TYPE_STRING,
04968 "Method to use : `linear' or `spline'",
04969 "giraffe.rebinning.method",
04970 "linear", 2, "linear", "spline");
04971 cpl_parameter_set_alias(p, CPL_PARAMETER_MODE_CLI, "rbin-method");
04972 cpl_parameterlist_append(list, p);
04973
04974 p = cpl_parameter_new_value("giraffe.rebinning.xresiduals",
04975 CPL_TYPE_BOOL,
04976 "Use x residuals during rebinning? `true'/"
04977 "`false'",
04978 "giraffe.rebinning.xresiduals",
04979 TRUE);
04980 cpl_parameter_set_alias(p, CPL_PARAMETER_MODE_CLI, "rbin-xresid");
04981 cpl_parameterlist_append(list, p);
04982
04983 p = cpl_parameter_new_value("giraffe.rebinning.lstep",
04984 CPL_TYPE_DOUBLE,
04985 "Lambda step size, only used if "
04986 "scaling method is 'linear'",
04987 "giraffe.rebinning.lstep",
04988 0.005);
04989 cpl_parameter_set_alias(p, CPL_PARAMETER_MODE_CLI, "rbin-lstep");
04990 cpl_parameterlist_append(list, p);
04991
04992 p = cpl_parameter_new_enum("giraffe.rebinning.scalemethod",
04993 CPL_TYPE_STRING,
04994 "Scaling method: `log' or `linear'",
04995 "giraffe.rebinning.scalemethod",
04996 "linear", 2, "linear", "log");
04997 cpl_parameter_set_alias(p, CPL_PARAMETER_MODE_CLI, "rbin-scmethod");
04998 cpl_parameterlist_append(list, p);
04999
05000 p = cpl_parameter_new_value("giraffe.rebinning.size",
05001 CPL_TYPE_INT,
05002 "Size of output rebinned spectra, 0 means "
05003 "calculate size based on wavelength range "
05004 "and lambda stepsize",
05005 "giraffe.rebinning.size",
05006 0);
05007 cpl_parameter_set_alias(p, CPL_PARAMETER_MODE_CLI, "rbin-size");
05008 cpl_parameterlist_append(list, p);
05009
05010 p = cpl_parameter_new_enum("giraffe.rebinning.range",
05011 CPL_TYPE_STRING,
05012 "Rebinning range: `setup' or `common'",
05013 "giraffe.rebinning.scalemethod",
05014 "setup", 2, "setup", "common");
05015 cpl_parameter_set_alias(p, CPL_PARAMETER_MODE_CLI, "rbin-range");
05016 cpl_parameterlist_append(list, p);
05017
05018 return;
05019
05020 }