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