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