00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
00027
00028 #ifdef HAVE_CONFIG_H
00029 # include <config.h>
00030 #endif
00031
00032 #include <math.h>
00033
00034 #include <cxmacros.h>
00035 #include <cxtypes.h>
00036 #include <cxmemory.h>
00037
00038 #include <cpl_parameter.h>
00039 #include <cpl_parameterlist.h>
00040 #include <cpl_image.h>
00041 #include <cpl_msg.h>
00042
00043 #include "gimacros.h"
00044 #include "gidebug.h"
00045 #include "gierror.h"
00046 #include "gialias.h"
00047 #include "gimatrix.h"
00048 #include "gimessages.h"
00049 #include "gimath.h"
00050 #include "gimath_lm.h"
00051 #include "gifiberutils.h"
00052 #include "giutils.h"
00053 #include "girebinning.h"
00054
00055
00064 #define GIFITS_KEYWORD_MISSING_MSG "FITS KEYWORD [%s] not found!! Aborting..."
00065 #define GIWAVECAL_GRATING_WAVELENGTH_EPSILON 0.0001
00066
00067
00068 enum GiLocDataType {
00069 GILOCDATATYPE_UNDEFINED,
00070 GILOCDATATYPE_FITTED_DATA,
00071 GILOCDATATYPE_FIT_COEFFS
00072 };
00073
00074 typedef enum GiLocDataType GiLocDataType;
00075
00076
00077 struct GiGrat {
00078 cx_string *name;
00079 cx_string *filter_name;
00080 cx_string *setup_name;
00081 cx_string *slit_name;
00082 cxint order;
00083 cxdouble wlen0;
00084 cxdouble wlenmin;
00085 cxdouble wlenmax;
00086 cxdouble band;
00087 cxdouble resol;
00088 cxdouble space;
00089 cxdouble theta;
00090 cxdouble fcoll;
00091 cxdouble gcam;
00092 cxdouble slitdx;
00093 cxdouble slitdy;
00094 cxdouble slitphi;
00095 };
00096
00097 typedef struct GiGrat GiGrat;
00098
00099
00100 struct GiFiberPosition {
00101 cpl_matrix *x_fiber;
00102 cpl_matrix *y_fiber;
00103 };
00104
00105 typedef struct GiFiberPosition GiFiberPosition;
00106
00107
00108 struct GiLocPosition {
00109 cxint ydeg;
00110 cxint wdeg;
00111 GiLocDataType type;
00112 cpl_image *centroids;
00113 cpl_image *widths;
00114 };
00115
00116 typedef struct GiLocPosition GiLocPosition;
00117
00118
00119 struct GiBinnParams {
00120 cxint xdeg;
00121 cxint ydeg;
00122 };
00123
00124 typedef struct GiBinnParams GiBinnParams;
00125
00126
00127 struct GiSlitGeo {
00128 cxint nsubslits;
00129 cpl_matrix **subslits;
00130 };
00131
00132 typedef struct GiSlitGeo GiSlitGeo;
00133
00134 struct GiWcalSolution {
00135 cxbool subslitfit;
00136 lmrq_model_id opt_mod;
00137 cpl_matrix *opt_mod_params;
00138 GiSlitGeo *wav_coeffs;
00139 GiSlitGeo *wav_limits;
00140 };
00141
00142 typedef struct GiWcalSolution GiWcalSolution;
00143
00144
00145 struct GiRebinInfo {
00146 const cxchar* method;
00147 const cxchar* scale;
00148 const cxchar* range;
00149 const cxchar* units;
00150
00151 cxdouble wmin;
00152 cxdouble wcenter;
00153 cxdouble wmax;
00154 cxdouble wstep;
00155
00156 cxint offset;
00157
00158 };
00159
00160 typedef struct GiRebinInfo GiRebinInfo;
00161
00162
00163
00164
00165
00166
00167 static cxdouble ddb, dde;
00168
00169
00170 inline static cxint
00171 _giraffe_resample_update_properties(GiImage* spectra, GiRebinInfo* info)
00172 {
00173
00174 cpl_image* image = giraffe_image_get(spectra);
00175
00176 cpl_propertylist* properties = giraffe_image_get_properties(spectra);
00177
00178
00179 giraffe_error_push();
00180
00181 cpl_propertylist_update_double(properties, GIALIAS_DATAMIN,
00182 cpl_image_get_min(image));
00183 cpl_propertylist_update_double(properties, GIALIAS_DATAMAX,
00184 cpl_image_get_max(image));
00185
00186 cpl_propertylist_update_string(properties, GIALIAS_GIRFTYPE,
00187 "BINSP");
00188
00189 cpl_propertylist_update_int(properties, GIALIAS_BINWNX,
00190 cpl_image_get_size_y(image));
00191 cpl_propertylist_update_int(properties, GIALIAS_BINWNS,
00192 cpl_image_get_size_x(image));
00193
00194 cpl_propertylist_update_string(properties, GIALIAS_CTYPE2,
00195 info->units);
00196 cpl_propertylist_update_double(properties, GIALIAS_CRPIX2,
00197 info->offset + 1);
00198 cpl_propertylist_update_double(properties, GIALIAS_CRVAL2,
00199 info->wmin);
00200 cpl_propertylist_update_double(properties, GIALIAS_CDELT2,
00201 info->wstep);
00202
00203 cpl_propertylist_update_double(properties, GIALIAS_BINWLMIN,
00204 info->wmin);
00205 cpl_propertylist_update_double(properties, GIALIAS_BINWL0,
00206 info->wcenter);
00207 cpl_propertylist_update_double(properties, GIALIAS_BINWLMAX,
00208 info->wmax);
00209 cpl_propertylist_update_double(properties, GIALIAS_BINSTEP,
00210 info->wstep);
00211 cpl_propertylist_update_string(properties, GIALIAS_BINMETHOD,
00212 info->method);
00213 cpl_propertylist_update_string(properties, GIALIAS_BINSCALE,
00214 info->scale);
00215 cpl_propertylist_update_string(properties, GIALIAS_BINRANGE,
00216 info->range);
00217
00218 if (cpl_error_get_code() != CPL_ERROR_NONE) {
00219 return 1;
00220 }
00221
00222 giraffe_error_pop();
00223
00224 return 0;
00225
00226 }
00227
00228
00229 static GiGrat*
00230 _giraffe_grating_new(void)
00231 {
00232
00233 GiGrat *grating = NULL;
00234
00235 grating = (GiGrat*) cx_calloc(1, (cxsize)sizeof(GiGrat));
00236
00237 grating->name = cx_string_create("UNKNOWN");
00238 grating->filter_name = cx_string_create("UNKNOWN");
00239 grating->setup_name = cx_string_create("UNKNOWN");
00240 grating->slit_name = cx_string_create("UNKNOWN");
00241
00242 return grating;
00243
00244 }
00245
00246
00247 static void
00248 _giraffe_grating_delete(GiGrat *grating)
00249 {
00250
00251 if (grating==NULL) { return; }
00252
00253 if (grating->name!=NULL) {
00254 cx_string_delete(grating->name);
00255 }
00256 if (grating->filter_name!=NULL) {
00257 cx_string_delete(grating->filter_name);
00258 }
00259 if (grating->setup_name!=NULL) {
00260 cx_string_delete(grating->setup_name);
00261 }
00262 if (grating->slit_name!=NULL) {
00263 cx_string_delete(grating->slit_name);
00264 }
00265 cx_free(grating);
00266
00267 }
00268
00269
00270 static cxint
00271 _giraffe_grating_setup(const GiTable *grating_table,
00272 const GiImage *grating_ass_img, GiGrat *grating_setup)
00273 {
00274
00275
00276
00277
00278
00279 const cxchar *fctid = "_giraffe_grating_setup";
00280
00281 cxdouble wlen_match = 0.0,
00282 wlen = 0.0,
00283 tmp_gratgrv = 0.0;
00284
00285 cxint32 row_match = 0,
00286 row_nulls,
00287 i = 0;
00288
00289 const cxchar *c_name_setup = "SETUP";
00290 const cxchar *c_name_order = "ORDER";
00291 const cxchar *c_name_wl0 = "WLEN0";
00292 const cxchar *c_name_wlmin = "WLMIN";
00293 const cxchar *c_name_wlmax = "WLMAX";
00294 const cxchar *c_name_band = "BAND";
00295 const cxchar *c_name_theta = "THETA";
00296 const cxchar *c_name_fcoll = "FCOLL";
00297 const cxchar *c_name_gcam = "GCAM";
00298 const cxchar *c_name_sdx = "SDX";
00299 const cxchar *c_name_sdy = "SDY";
00300 const cxchar *c_name_sdphi = "SPHI";
00301 const cxchar *c_name_rmed = "RMED";
00302 const cxchar *c_name_rifa = "RIFA";
00303
00304 cpl_propertylist *ref_plimg = NULL;
00305 cpl_table *ref_gtable = NULL;
00306 cx_string *slit_name = NULL;
00307
00308 GiInstrumentMode instrument_mode;
00309
00310
00311
00312
00313
00314
00315 if (grating_table ==NULL) { return 1; }
00316 if (grating_ass_img==NULL) { return 1; }
00317 if (grating_setup ==NULL) { return 1; }
00318
00319 if ((ref_plimg=giraffe_image_get_properties(grating_ass_img))==NULL) {
00320 return 128;
00321 }
00322
00323 if ((ref_gtable = giraffe_table_get(grating_table))==NULL) {
00324 return 128;
00325 }
00326
00327 slit_name = cx_string_new();
00328
00329
00330
00331
00332
00333
00334
00335
00336
00337 if (!cpl_propertylist_has(ref_plimg, GIALIAS_GRATWLEN)) {
00338 cpl_msg_error(fctid, GIFITS_KEYWORD_MISSING_MSG, GIALIAS_GRATWLEN);
00339 cx_string_delete(slit_name);
00340 return 2;
00341 }
00342 else {
00343 grating_setup->wlen0 = cpl_propertylist_get_double(ref_plimg,
00344 GIALIAS_GRATWLEN);
00345 }
00346
00347 if (!cpl_propertylist_has(ref_plimg, GIALIAS_GRATORDER)) {
00348 cpl_msg_error(fctid, GIFITS_KEYWORD_MISSING_MSG, GIALIAS_GRATORDER);
00349 cx_string_delete(slit_name);
00350 return 2;
00351 }
00352 else {
00353 grating_setup->order = cpl_propertylist_get_int(ref_plimg, GIALIAS_GRATORDER);
00354 }
00355
00356 if (!cpl_propertylist_has(ref_plimg, GIALIAS_SLITNAME)) {
00357
00358 cpl_msg_error(fctid, GIFITS_KEYWORD_MISSING_MSG, GIALIAS_SLITNAME);
00359 cx_string_delete(slit_name);
00360 return 2;
00361 } else {
00362 cx_string_set(slit_name,
00363 cpl_propertylist_get_string(ref_plimg, GIALIAS_SLITNAME));
00364 }
00365
00366 if (!cpl_propertylist_has(ref_plimg, GIALIAS_GRATGRV)) {
00367
00368 cpl_msg_error(fctid, GIFITS_KEYWORD_MISSING_MSG, GIALIAS_GRATGRV);
00369 cx_string_delete(slit_name);
00370 return 2;
00371 } else {
00372 tmp_gratgrv = cpl_propertylist_get_double(ref_plimg, GIALIAS_GRATGRV );
00373 }
00374
00375 if (!cpl_propertylist_has(ref_plimg, GIALIAS_GRATNAME)) {
00376 cpl_msg_error(fctid, GIFITS_KEYWORD_MISSING_MSG, GIALIAS_GRATNAME);
00377 cx_string_delete(slit_name);
00378 return 2;
00379 } else {
00380 cx_string_set(grating_setup->name,
00381 cpl_propertylist_get_string(ref_plimg, GIALIAS_GRATNAME));
00382 }
00383
00384 if (!cpl_propertylist_has(ref_plimg, GIALIAS_FILTNAME)) {
00385 cpl_msg_error(fctid, GIFITS_KEYWORD_MISSING_MSG, GIALIAS_FILTNAME);
00386 cx_string_delete(slit_name);
00387 return 2;
00388 }
00389 else {
00390 cx_string_set(grating_setup->filter_name,
00391 cpl_propertylist_get_string(ref_plimg, GIALIAS_FILTNAME));
00392 }
00393
00394
00395
00396
00397
00398
00399 for (i = 0; i < cpl_table_get_nrow(ref_gtable); i++) {
00400
00401 cxint _order = cpl_table_get_int(ref_gtable, c_name_order, i, NULL);
00402
00403 if (_order == grating_setup->order) {
00404
00405 wlen = cpl_table_get(ref_gtable, c_name_wl0, i, &row_nulls);
00406
00407 if (fabs(wlen - grating_setup->wlen0) <
00408 fabs(wlen_match - grating_setup->wlen0)) {
00409 wlen_match = wlen;
00410 row_match = i;
00411 }
00412
00413 }
00414 }
00415
00416
00417
00418
00419
00420
00421 if (fabs(wlen_match - grating_setup->wlen0) >
00422 GIWAVECAL_GRATING_WAVELENGTH_EPSILON) {
00423
00424 cpl_msg_error(fctid, "Grating setup (wavelength %.2f nm, order %d) "
00425 "not found in grating table!", grating_setup->wlen0,
00426 grating_setup->order);
00427 cx_string_delete(slit_name);
00428 return 3;
00429 }
00430 else {
00431 cpl_msg_debug(fctid, "Found wlen0 in grating table at position %d",
00432 row_match);
00433 }
00434
00435
00436
00437
00438
00439
00440 cx_string_set(grating_setup->setup_name,
00441 (cxchar*) cpl_table_get_string(ref_gtable, c_name_setup,
00442 row_match));
00443
00444 cx_string_set(grating_setup->slit_name, cx_string_get(slit_name));
00445
00446 grating_setup->wlenmin = cpl_table_get(ref_gtable, c_name_wlmin,
00447 row_match, &row_nulls);
00448
00449 grating_setup->wlenmax = cpl_table_get(ref_gtable, c_name_wlmax,
00450 row_match, &row_nulls);
00451
00452 grating_setup->band = cpl_table_get(ref_gtable, c_name_band,
00453 row_match, &row_nulls);
00454
00455 grating_setup->theta = cpl_table_get(ref_gtable, c_name_theta,
00456 row_match, &row_nulls);
00457
00458 grating_setup->space = 1.0 / fabs(GI_MM_TO_NM * tmp_gratgrv);
00459
00460
00461 instrument_mode = giraffe_get_mode(ref_plimg);
00462
00463 switch (instrument_mode) {
00464 case GIMODE_MEDUSA:
00465 grating_setup->resol = cpl_table_get(ref_gtable, c_name_rmed,
00466 row_match, &row_nulls);
00467 break;
00468
00469 case GIMODE_IFU:
00470 grating_setup->resol = cpl_table_get(ref_gtable, c_name_rifa,
00471 row_match, &row_nulls);
00472 break;
00473
00474 case GIMODE_ARGUS:
00475 grating_setup->resol = cpl_table_get(ref_gtable, c_name_rifa,
00476 row_match, &row_nulls);
00477 break;
00478
00479 default:
00480 grating_setup->resol = -1.0;
00481 break;
00482 }
00483
00484 grating_setup->fcoll =
00485 cpl_table_get(ref_gtable, c_name_fcoll, row_match, &row_nulls);
00486
00487 grating_setup->gcam =
00488 cpl_table_get(ref_gtable, c_name_gcam, row_match, &row_nulls);
00489
00490 grating_setup->slitdx =
00491 cpl_table_get(ref_gtable, c_name_sdx, row_match, &row_nulls);
00492
00493 grating_setup->slitdy =
00494 cpl_table_get(ref_gtable, c_name_sdy, row_match, &row_nulls);
00495
00496 grating_setup->slitphi =
00497 cpl_table_get(ref_gtable, c_name_sdphi, row_match, &row_nulls);
00498
00499 cx_string_delete(slit_name);
00500
00501 return 0;
00502
00503 }
00504
00505
00506 static GiFiberPosition*
00507 _giraffe_fiberposition_new(void)
00508 {
00509
00510 GiFiberPosition* tmp = NULL;
00511
00512 tmp = (GiFiberPosition*) cx_calloc(1, sizeof(GiFiberPosition));
00513
00514 tmp->x_fiber = NULL;
00515 tmp->y_fiber = NULL;
00516
00517 return tmp;
00518 }
00519
00520
00521 static void
00522 _giraffe_fiberposition_delete(GiFiberPosition *fp)
00523 {
00524
00525 if (fp != NULL) {
00526
00527 if (fp->x_fiber) {
00528 cpl_matrix_delete(fp->x_fiber);
00529 }
00530
00531 if (fp->y_fiber) {
00532 cpl_matrix_delete(fp->y_fiber);
00533 }
00534
00535 cx_free(fp);
00536
00537 }
00538
00539 return;
00540
00541 }
00542
00543
00544 static GiSlitGeo*
00545 _giraffe_slitgeo_new(void)
00546 {
00547
00548 GiSlitGeo *sgeometry = NULL;
00549
00550 sgeometry = cx_malloc(sizeof(GiSlitGeo));
00551
00552 sgeometry->subslits = NULL;
00553 sgeometry->nsubslits = 0;
00554
00555 return sgeometry;
00556
00557 }
00558
00559
00560 static void
00561 _giraffe_slitgeo_delete(GiSlitGeo *sgeometry)
00562 {
00563
00564 if (sgeometry != NULL) {
00565
00566 if (sgeometry->subslits != NULL) {
00567
00568 cxint i;
00569
00570 for (i = 0; i < sgeometry->nsubslits; i++) {
00571 cpl_matrix_delete(sgeometry->subslits[i]);
00572 }
00573
00574 cx_free(sgeometry->subslits);
00575 }
00576
00577 cx_free(sgeometry);
00578
00579 }
00580
00581 return;
00582
00583 }
00584
00585
00586 static cxint
00587 _giraffe_slitgeo_size(GiSlitGeo *sgeometry)
00588 {
00589
00590 if (sgeometry == NULL) {
00591 return -1;
00592 }
00593
00594 if (sgeometry->subslits != NULL) {
00595 return sgeometry->nsubslits;
00596 }
00597
00598 return -1;
00599
00600 }
00601
00602
00603 static void
00604 _giraffe_slitgeo_resize(GiSlitGeo *sgeometry, cxint size)
00605 {
00606
00607 if (sgeometry == NULL) {
00608 return;
00609 }
00610
00611 if (size == sgeometry->nsubslits) {
00612 return;
00613 }
00614
00615 if (sgeometry->subslits != NULL) {
00616
00617 cxint i;
00618
00619 for (i = 0; i < sgeometry->nsubslits; i++) {
00620 cpl_matrix_delete(sgeometry->subslits[i]);
00621 }
00622 }
00623
00624 cx_free(sgeometry->subslits);
00625
00626 sgeometry->nsubslits = size;
00627 sgeometry->subslits = cx_calloc(sgeometry->nsubslits, sizeof(cpl_matrix*));
00628
00629 return;
00630
00631 }
00632
00633
00634 static void
00635 _giraffe_slitgeo_create(GiSlitGeo *sgeometry, cxint idx, cxint nrow,
00636 cxint ncol)
00637 {
00638
00639 if (sgeometry == NULL) {
00640 return;
00641 }
00642
00643 if (sgeometry->subslits == NULL) {
00644 return;
00645 }
00646
00647 if ((idx < 0) || (idx > sgeometry->nsubslits)) {
00648 return;
00649 }
00650
00651 if (sgeometry->subslits[idx] != NULL) {
00652 cpl_matrix_delete(sgeometry->subslits[idx]);
00653 }
00654
00655 sgeometry->subslits[idx] = cpl_matrix_new(nrow, ncol);
00656
00657 return;
00658
00659 }
00660
00661
00662 static void
00663 _giraffe_slitgeo_set(GiSlitGeo *sgeometry, cxint idx, cpl_matrix *nm)
00664 {
00665
00666 if (sgeometry == NULL) {
00667 return;
00668 }
00669
00670 if (sgeometry->subslits == NULL) {
00671 return;
00672 }
00673
00674 if ((idx < 0) || (idx > sgeometry->nsubslits)) {
00675 return;
00676 }
00677
00678 if (sgeometry->subslits[idx] != NULL) {
00679 cpl_matrix_delete(sgeometry->subslits[idx]);
00680 }
00681
00682 if (nm) {
00683 sgeometry->subslits[idx] = cpl_matrix_duplicate(nm);
00684 }
00685 else {
00686 sgeometry->subslits[idx] = NULL;
00687 }
00688
00689 }
00690
00691
00692 static cpl_matrix*
00693 _giraffe_slitgeo_get(GiSlitGeo *sgeometry, cxint idx)
00694 {
00695
00696 if (sgeometry == NULL) {
00697 return NULL;
00698 }
00699
00700 if (sgeometry->subslits == NULL) {
00701 return NULL;
00702 }
00703
00704 if ((idx < 0)||(idx > sgeometry->nsubslits)) {
00705 return NULL;
00706 }
00707
00708 return (sgeometry->subslits[idx]);
00709
00710 }
00711
00712
00713 static cxint
00714 _giraffe_slitgeo_setup(const GiTable *slitgeo,
00715 GiFiberPosition *fiber_slit_position,
00716 GiSlitGeo *subslits, cxbool fitsubslit)
00717 {
00718
00719 const cxchar *const fctid = "_giraffe_slitgeo_setup";
00720
00721
00722 const cxchar *c_name_xf = "XF";
00723 const cxchar *c_name_yf = "YF";
00724 const cxchar *c_name_nspec = "FPS";
00725 const cxchar *c_name_ssn = "SSN";
00726
00727
00728 cpl_matrix *nspec = NULL;
00729 cpl_matrix *nsubslits = NULL;
00730
00731 cxint nr_slitgeo = 0,
00732 max_nsubslits = 0,
00733 i = 0,
00734 j = 0,
00735 row_null = 0,
00736 count = 0,
00737 column_index = 0,
00738 tmp_nspec = 0,
00739 tmp_nsubslits = 0;
00740
00741 cxdouble tmp_xf,
00742 tmp_yf;
00743
00744 cpl_table *ref_slitgeo = NULL;
00745
00746 cpl_error_code ce_code;
00747
00748
00749
00750
00751
00752
00753 if (slitgeo ==NULL) { return 1; }
00754 if (fiber_slit_position==NULL) { return 1; }
00755 if (subslits ==NULL) { return 1; }
00756
00757
00758
00759
00760
00761 ref_slitgeo = giraffe_table_get(slitgeo);
00762 nr_slitgeo = cpl_table_get_nrow(ref_slitgeo);
00763
00764 fiber_slit_position->x_fiber = cpl_matrix_new(nr_slitgeo, 1);
00765 fiber_slit_position->y_fiber = cpl_matrix_new(nr_slitgeo, 1);
00766
00767 nspec = cpl_matrix_new(nr_slitgeo, 1);
00768 nsubslits = cpl_matrix_new(nr_slitgeo, 1);
00769
00770
00771
00772
00773
00774 max_nsubslits = 0;
00775
00776 for (i = 0; i < nr_slitgeo; i++) {
00777
00778 tmp_xf = cpl_table_get(ref_slitgeo, c_name_xf, i, &row_null);
00779 tmp_yf = cpl_table_get(ref_slitgeo, c_name_yf, i, &row_null);
00780
00781 tmp_nspec = cpl_table_get_int(ref_slitgeo, c_name_nspec, i,
00782 &row_null) - 1;
00783
00784 tmp_nsubslits = cpl_table_get_int(ref_slitgeo, c_name_ssn, i,
00785 &row_null);
00786
00787 if (tmp_nsubslits>max_nsubslits) {
00788 max_nsubslits = tmp_nsubslits;
00789 }
00790
00791 ce_code = cpl_matrix_set(fiber_slit_position->x_fiber, i, 0, tmp_xf);
00792 ce_code = cpl_matrix_set(fiber_slit_position->y_fiber, i, 0, tmp_yf);
00793
00794 ce_code = cpl_matrix_set(nspec, i, 0, (cxdouble)tmp_nspec);
00795 ce_code = cpl_matrix_set(nsubslits, i, 0, (cxdouble)tmp_nsubslits);
00796
00797 }
00798
00799
00800
00801
00802
00803 if (fitsubslit) {
00804
00805
00806
00807 _giraffe_slitgeo_resize(subslits, max_nsubslits);
00808
00809 for (i = 1; i <= max_nsubslits; i++) {
00810
00811 cpl_matrix *ref_matrix = NULL;
00812 cxint curr_ssn;
00813
00814 count = 0;
00815 for (j=0; j<nr_slitgeo; j++) {
00816 curr_ssn = (cxint) cpl_matrix_get(nsubslits, j, 0);
00817 if (i==curr_ssn) {
00818 ++count;
00819 }
00820 }
00821
00822 _giraffe_slitgeo_create(subslits, i-1, count, 1);
00823
00824 ref_matrix = _giraffe_slitgeo_get(subslits, i-1);
00825
00826 column_index = 0;
00827 for (j = 0; j < nr_slitgeo; j++) {
00828
00829 curr_ssn = (cxint) cpl_matrix_get(nsubslits, j, 0);
00830
00831 if (i == curr_ssn) {
00832 ce_code = cpl_matrix_set(ref_matrix, column_index, 0,
00833 (cxdouble)j);
00834 column_index++;
00835 }
00836
00837 }
00838 }
00839
00840 cpl_msg_debug(fctid, "Using multiple slits for Slit Geometry");
00841
00842 }
00843 else {
00844
00845 const cxchar *idx = giraffe_fiberlist_query_index(ref_slitgeo);
00846
00847
00848
00849
00850
00851
00852 cpl_matrix *ref_matrix = NULL;
00853
00854 _giraffe_slitgeo_resize(subslits, 1);
00855 _giraffe_slitgeo_create(subslits, 0, nr_slitgeo, 1);
00856
00857 ref_matrix = _giraffe_slitgeo_get(subslits, 0);
00858
00859 for (j = 0; j < nr_slitgeo; j++) {
00860
00861 cxint cs = cpl_table_get_int(ref_slitgeo, idx, j, NULL) - 1;
00862 ce_code = cpl_matrix_set(ref_matrix, j, 0, cs);
00863
00864
00865 }
00866
00867 cpl_msg_debug(fctid, "Using single slit for Slit Geometry");
00868
00869 }
00870
00871 cpl_matrix_delete(nspec);
00872 nspec = NULL;
00873
00874 cpl_matrix_delete(nsubslits);
00875 nsubslits = NULL;
00876
00877 return 0;
00878
00879 }
00880
00881
00882 static GiWcalSolution*
00883 _giraffe_wcalsolution_new(void)
00884 {
00885
00886 GiWcalSolution* tmp = NULL;
00887
00888 tmp = (GiWcalSolution*) cx_calloc(1, sizeof(GiWcalSolution));
00889
00890 tmp->subslitfit = FALSE;
00891 tmp->opt_mod = LMRQ_UNDEFINED;
00892 tmp->opt_mod_params = NULL;
00893 tmp->wav_coeffs = NULL;
00894 tmp->wav_limits = NULL;
00895
00896 return tmp;
00897 }
00898
00899
00900 static void
00901 _giraffe_wcalsolution_delete(GiWcalSolution *ws)
00902 {
00903
00904 if (ws != NULL) {
00905
00906 if (ws->opt_mod_params!=NULL) {
00907 cpl_matrix_delete(ws->opt_mod_params);
00908 }
00909
00910 if (ws->wav_coeffs!=NULL) {
00911 _giraffe_slitgeo_delete(ws->wav_coeffs);
00912 }
00913
00914 if (ws->wav_limits!=NULL) {
00915 _giraffe_slitgeo_delete(ws->wav_limits);
00916 }
00917
00918 cx_free(ws);
00919
00920 }
00921
00922 return;
00923
00924 }
00925
00926
00927 static GiWcalSolution*
00928 _giraffe_wcalsolution_create(const GiTable *wavesolution)
00929 {
00930
00931 cxchar buffer[68];
00932
00933 cxint i = 0;
00934 cxint poly_x_deg = 0;
00935 cxint poly_y_deg = 0;
00936 cxint ncoefficients = 0;
00937
00938 cxdouble* pd_coefficients = NULL;
00939
00940 cpl_matrix* coefficients = NULL;
00941 cpl_matrix* limits = NULL;
00942
00943 cpl_propertylist* _properties = NULL;
00944
00945 cpl_table* _table = NULL;
00946
00947 GiWcalSolution* wavcoeff = NULL;
00948
00949
00950
00951 if (wavesolution == NULL) {
00952 return NULL;
00953 }
00954
00955 wavcoeff = _giraffe_wcalsolution_new();
00956
00957 _properties = giraffe_table_get_properties(wavesolution);
00958
00959
00960
00961
00962
00963
00964 if (cpl_propertylist_has(_properties, GIALIAS_OPT_MOD) == TRUE) {
00965
00966 const cxchar* optmod = cpl_propertylist_get_string(_properties,
00967 GIALIAS_OPT_MOD);
00968
00969 if (strncmp(optmod, "xoptmod2", 8) == 0) {
00970 wavcoeff->opt_mod = LMRQ_XOPTMOD2;
00971 }
00972 else if (strncmp(optmod, "xoptmod", 7) == 0) {
00973 wavcoeff->opt_mod = LMRQ_XOPTMOD;
00974 }
00975 else {
00976 wavcoeff->opt_mod = LMRQ_UNDEFINED;
00977 }
00978 }
00979
00980 if (wavcoeff->opt_mod == LMRQ_XOPTMOD2) {
00981
00982 wavcoeff->opt_mod_params = cpl_matrix_new(7,1);
00983
00984 if (cpl_propertylist_has(_properties, GIALIAS_OPTMDIR)) {
00985 cpl_matrix_set(
00986 wavcoeff->opt_mod_params,
00987 0,
00988 0,
00989 cpl_propertylist_get_int(_properties, GIALIAS_OPTMDIR)
00990 );
00991 } else {
00992 _giraffe_wcalsolution_delete(wavcoeff);
00993 return NULL;
00994 }
00995
00996 if (cpl_propertylist_has(_properties, GIALIAS_WSOL_OPTMFCOLL)) {
00997 cpl_matrix_set(
00998 wavcoeff->opt_mod_params,
00999 1,
01000 0,
01001 cpl_propertylist_get_double(_properties, GIALIAS_WSOL_OPTMFCOLL)
01002 );
01003 } else {
01004 _giraffe_wcalsolution_delete(wavcoeff);
01005 return NULL;
01006 }
01007
01008 if (cpl_propertylist_has(_properties, GIALIAS_WSOL_OPTMGCAM)) {
01009 cpl_matrix_set(
01010 wavcoeff->opt_mod_params,
01011 2,
01012 0,
01013 cpl_propertylist_get_double(_properties, GIALIAS_WSOL_OPTMGCAM)
01014 );
01015 } else {
01016 _giraffe_wcalsolution_delete(wavcoeff);
01017 return NULL;
01018 }
01019
01020 if (cpl_propertylist_has(_properties, GIALIAS_WSOL_OPTMTHETA)) {
01021 cpl_matrix_set(
01022 wavcoeff->opt_mod_params,
01023 3,
01024 0,
01025 cpl_propertylist_get_double(_properties, GIALIAS_WSOL_OPTMTHETA)
01026 );
01027 } else {
01028 _giraffe_wcalsolution_delete(wavcoeff);
01029 return NULL;
01030 }
01031
01032 if (cpl_propertylist_has(_properties, GIALIAS_WSOL_OPTMSDX)) {
01033 cpl_matrix_set(
01034 wavcoeff->opt_mod_params,
01035 4,
01036 0,
01037 cpl_propertylist_get_double(_properties, GIALIAS_WSOL_OPTMSDX)
01038 );
01039 } else {
01040 _giraffe_wcalsolution_delete(wavcoeff);
01041 return NULL;
01042 }
01043
01044 if (cpl_propertylist_has(_properties, GIALIAS_WSOL_OPTMSDY)) {
01045
01046
01047
01048 cpl_matrix_set(
01049 wavcoeff->opt_mod_params,
01050 5,
01051 0,
01052 cpl_propertylist_get_double(_properties, GIALIAS_WSOL_OPTMSDY)
01053 );
01054
01055 } else {
01056 _giraffe_wcalsolution_delete(wavcoeff);
01057 return NULL;
01058 }
01059
01060 if (cpl_propertylist_has(_properties, GIALIAS_WSOL_OPTMSPHI)) {
01061 cpl_matrix_set(
01062 wavcoeff->opt_mod_params,
01063 6,
01064 0,
01065 cpl_propertylist_get_double(_properties, GIALIAS_WSOL_OPTMSPHI)
01066 );
01067
01068 } else {
01069 _giraffe_wcalsolution_delete(wavcoeff);
01070 return NULL;
01071 }
01072
01073 } else if (wavcoeff->opt_mod==LMRQ_XOPTMOD) {
01074
01075 wavcoeff->opt_mod_params = cpl_matrix_new(4,1);
01076
01077 if (cpl_propertylist_has(_properties, GIALIAS_OPTMDIR)) {
01078 cpl_matrix_set(
01079 wavcoeff->opt_mod_params,
01080 0,
01081 0,
01082 cpl_propertylist_get_int(_properties, GIALIAS_OPTMDIR)
01083 );
01084 } else {
01085 _giraffe_wcalsolution_delete(wavcoeff);
01086 return NULL;
01087 }
01088
01089 if (cpl_propertylist_has(_properties, GIALIAS_WSOL_OPTMFCOLL)) {
01090 cpl_matrix_set(
01091 wavcoeff->opt_mod_params,
01092 1,
01093 0,
01094 cpl_propertylist_get_double(_properties, GIALIAS_WSOL_OPTMFCOLL)
01095 );
01096 } else {
01097 _giraffe_wcalsolution_delete(wavcoeff);
01098 return NULL;
01099 }
01100
01101 if (cpl_propertylist_has(_properties, GIALIAS_WSOL_OPTMGCAM)) {
01102 cpl_matrix_set(
01103 wavcoeff->opt_mod_params,
01104 2,
01105 0,
01106 cpl_propertylist_get_double(_properties, GIALIAS_WSOL_OPTMGCAM)
01107 );
01108 } else {
01109 _giraffe_wcalsolution_delete(wavcoeff);
01110 return NULL;
01111 }
01112
01113 if (cpl_propertylist_has(_properties, GIALIAS_WSOL_OPTMTHETA)) {
01114 cpl_matrix_set(
01115 wavcoeff->opt_mod_params,
01116 3,
01117 0,
01118 cpl_propertylist_get_double(_properties, GIALIAS_WSOL_OPTMTHETA)
01119 );
01120 } else {
01121 _giraffe_wcalsolution_delete(wavcoeff);
01122 return NULL;
01123 }
01124
01125
01126 } else {
01127
01128 _giraffe_wcalsolution_delete(wavcoeff);
01129 return NULL;
01130
01131 }
01132
01133
01134
01135
01136
01137
01138 _table = giraffe_table_get(wavesolution);
01139
01140 if (_table != NULL) {
01141
01142
01143 if (cpl_propertylist_has(_properties, GIALIAS_SSF)) {
01144
01145 if (cpl_propertylist_get_bool(_properties, GIALIAS_SSF) == 0) {
01146 wavcoeff->subslitfit = FALSE;
01147 }
01148 else {
01149 wavcoeff->subslitfit = TRUE;
01150 }
01151
01152 }
01153 else {
01154
01155 _giraffe_wcalsolution_delete(wavcoeff);
01156 return NULL;
01157
01158 }
01159
01160 wavcoeff->wav_limits = _giraffe_slitgeo_new();
01161 _giraffe_slitgeo_resize(wavcoeff->wav_limits, 1);
01162
01163 limits = cpl_matrix_new(1, 4);
01164 cpl_matrix_fill(limits, -1.);
01165
01166 if (cpl_table_has_column(_table, "XMIN") &&
01167 cpl_table_has_column(_table, "XMAX")) {
01168 cpl_matrix_set(limits, 0, 0,
01169 cpl_table_get_double(_table, "XMIN", 0, NULL));
01170 cpl_matrix_set(limits, 0, 1,
01171 cpl_table_get_double(_table, "XMAX", 0, NULL));
01172 }
01173
01174 if (cpl_table_has_column(_table, "YMIN") &&
01175 cpl_table_has_column(_table, "YMAX")) {
01176 cpl_matrix_set(limits, 0, 2,
01177 cpl_table_get_double(_table, "YMIN", 0, NULL));
01178 cpl_matrix_set(limits, 0, 3,
01179 cpl_table_get_double(_table, "YMAX", 0, NULL));
01180 }
01181
01182 _giraffe_slitgeo_set(wavcoeff->wav_limits, 0, limits);
01183
01184 cpl_matrix_delete(limits);
01185 limits = NULL;
01186
01187 wavcoeff->wav_coeffs = _giraffe_slitgeo_new();
01188 _giraffe_slitgeo_resize(wavcoeff->wav_coeffs, 1);
01189
01190 if (cpl_propertylist_has(_properties, GIALIAS_XRES_PDEG)) {
01191
01192 cxchar *l, *r, *tmpstr;
01193
01194 tmpstr = (cxchar*) cpl_propertylist_get_string(_properties,
01195 GIALIAS_XRES_PDEG);
01196
01197 l = &(tmpstr[0]);
01198 r = &(tmpstr[2]);
01199
01200 poly_x_deg = atoi(l) + 1;
01201 poly_y_deg = atoi(r) + 1;
01202
01203 }
01204 else {
01205
01206 _giraffe_wcalsolution_delete(wavcoeff);
01207 return NULL;
01208
01209 }
01210
01211 ncoefficients = poly_x_deg * poly_y_deg;
01212
01213 coefficients = cpl_matrix_new(poly_x_deg,poly_y_deg);
01214 pd_coefficients = cpl_matrix_get_data(coefficients);
01215
01216 for (i=0; i<ncoefficients; i++) {
01217
01218 snprintf(buffer, sizeof buffer, "XC%-d", i);
01219
01220 pd_coefficients[i] =
01221 cpl_table_get_double(_table, buffer, 0, NULL);
01222
01223 }
01224
01225 _giraffe_slitgeo_set(wavcoeff->wav_coeffs, 0, coefficients);
01226
01227 cpl_matrix_delete(coefficients);
01228 coefficients = NULL;
01229
01230 }
01231
01232 return wavcoeff;
01233
01234 }
01235
01236
01237 static cpl_image*
01238 _giraffe_compute_pixel_abscissa(cpl_matrix* m_wavelengths,
01239 cpl_matrix* m_wloffset,
01240 GiFiberPosition* fiber_slit_position,
01241 cpl_matrix* m_opt_mod_params,
01242 lmrq_model lmrq_opt_mod_x)
01243 {
01244
01245
01246
01247
01248
01249 const cxchar *fctid = "_giraffe_compute_pixel_abscissa";
01250
01251 register cxint n;
01252 register cxint line;
01253 register cxint nwlen;
01254 register cxint ns;
01255
01256 cxint nr_m_opt_mod_params = 0;
01257
01258 cxdouble xccd = 0.;
01259 cxdouble* pd_xref = NULL;
01260 cxdouble* pd_m_inputs = NULL;
01261 cxdouble* pd_m_yfibre = NULL;
01262 cxdouble* pd_m_xfibre = NULL;
01263 cxdouble* pd_m_wavelengths = NULL;
01264 cxdouble* pd_m_opt_mod_params = NULL;
01265
01266 cpl_image* xref = NULL;
01267
01268 cpl_matrix* m_inputs = NULL;
01269
01270
01271
01272
01273
01274
01275 if (m_wavelengths == NULL) {
01276 return NULL;
01277 }
01278
01279 if ((fiber_slit_position == NULL) ||
01280 (fiber_slit_position->x_fiber == NULL) ||
01281 (fiber_slit_position->y_fiber == NULL)) {
01282 return NULL;
01283 }
01284
01285 if (m_opt_mod_params == NULL) {
01286 return NULL;
01287 }
01288
01289
01290 nwlen = cpl_matrix_get_nrow(m_wavelengths);
01291 ns = cpl_matrix_get_nrow(fiber_slit_position->y_fiber);
01292
01293 if ((m_wloffset != NULL) && (cpl_matrix_get_nrow(m_wloffset) != ns)) {
01294 return NULL;
01295 }
01296
01297
01298
01299
01300
01301
01302 xref = cpl_image_new(ns, nwlen, CPL_TYPE_DOUBLE);
01303 pd_xref = cpl_image_get_data_double(xref);
01304
01305 m_inputs = cpl_matrix_new(lmrq_opt_mod_x.ninputs, 1);
01306 pd_m_inputs = cpl_matrix_get_data(m_inputs);
01307
01308 pd_m_yfibre = cpl_matrix_get_data(fiber_slit_position->y_fiber);
01309 pd_m_xfibre = cpl_matrix_get_data(fiber_slit_position->x_fiber);
01310 pd_m_wavelengths = cpl_matrix_get_data(m_wavelengths);
01311
01312 pd_m_opt_mod_params = cpl_matrix_get_data(m_opt_mod_params);
01313 nr_m_opt_mod_params = cpl_matrix_get_nrow(m_opt_mod_params);
01314
01315
01316
01317
01318
01319
01320 if (m_wloffset != NULL) {
01321
01322 cxdouble* pd_m_wloffset = cpl_matrix_get_data(m_wloffset);
01323
01324 for (n = 0; n < ns; n++) {
01325
01326 pd_m_inputs[2] = pd_m_yfibre[n];
01327 pd_m_inputs[1] = pd_m_xfibre[n];
01328
01329 for (line = 0; line < nwlen; line++) {
01330
01331 pd_m_inputs[0] = pd_m_wavelengths[line] + pd_m_wloffset[n];
01332
01333 lmrq_opt_mod_x.cfunc(pd_m_inputs, pd_m_opt_mod_params,
01334 NULL, &xccd, NULL, nr_m_opt_mod_params);
01335
01336 pd_xref[line * ns + n] = xccd;
01337
01338 }
01339
01340 }
01341
01342 }
01343 else {
01344
01345 for (n = 0; n < ns; n++) {
01346
01347 pd_m_inputs[2] = pd_m_yfibre[n];
01348 pd_m_inputs[1] = pd_m_xfibre[n];
01349
01350 for (line = 0; line < nwlen; line++) {
01351
01352 pd_m_inputs[0] = pd_m_wavelengths[line];
01353
01354 lmrq_opt_mod_x.cfunc(pd_m_inputs, pd_m_opt_mod_params,
01355 NULL, &xccd, NULL, nr_m_opt_mod_params);
01356
01357 pd_xref[line * ns + n] = xccd;
01358
01359 }
01360
01361 }
01362
01363 }
01364
01365 cpl_matrix_delete(m_inputs);
01366
01367 cpl_msg_debug(fctid, "Processing completed: Returning image [x,y] ="
01368 " [%" CPL_SIZE_FORMAT ",%" CPL_SIZE_FORMAT "]",
01369 cpl_image_get_size_x(xref), cpl_image_get_size_y(xref));
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(fctid, "Processing complete : returning image "
03405 "[%" CPL_SIZE_FORMAT ", %" CPL_SIZE_FORMAT "]",
03406 cpl_image_get_size_x(abcissa), cpl_image_get_size_y(abcissa));
03407
03408 return abcissa;
03409
03410 }
03411
03439 inline static cxint
03440 _giraffe_resample_spectra(GiRebinning* result,
03441 const GiExtraction* extraction,
03442 const GiLocalization* localization,
03443 GiFiberPosition* fiber_position,
03444 GiSlitGeo* subslits,
03445 GiSlitGeo* xres_limits,
03446 GiSlitGeo* xres_coeff,
03447 GiBinnParams* xres_order,
03448 cpl_matrix* grating_data,
03449 cpl_matrix* optical_model,
03450 cpl_matrix* wlen_offsets,
03451 cxdouble rbstep,
03452 GiRebinMethod method,
03453 GiRebinRange range,
03454 GiRebinScale scale)
03455 {
03456
03457 const cxchar* const fctid = "_giraffe_resample_spectra";
03458
03459
03460 cxbool log_scale = FALSE;
03461
03462 cxint i = 0;
03463 cxint status = 0;
03464 cxint om_sign = 0;
03465 cxint rbsize = 0;
03466 cxint nspectra = 0;
03467
03468 cxdouble wlmin = 0.;
03469 cxdouble wlmax = 0.;
03470 cxdouble* _optical_model = NULL;
03471
03472 cpl_matrix* wavelengths = NULL;
03473
03474 cpl_image* _exspectra = NULL;
03475 cpl_image* _exerrors = NULL;
03476 cpl_image* _rbspectra = NULL;
03477 cpl_image* _rberrors = NULL;
03478 cpl_image* abscissa = NULL;
03479
03480 cpl_propertylist* properties = NULL;
03481
03482 GiImage* rbspectra = NULL;
03483 GiImage* rberrors = NULL;
03484
03485 GiLocPosition locPos;
03486
03487 GiRebinParams binPrms;
03488
03489 GiRebinInfo setup;
03490
03491
03492
03493
03494
03495
03496
03497 lmrq_model_id opt_mod_id = LMRQ_XOPTMOD2;
03498
03499
03500 if (result == NULL || extraction == NULL || localization == NULL) {
03501 return 1;
03502 }
03503
03504 if (result->spectra != NULL || result->errors != NULL) {
03505 return 1;
03506 }
03507
03508 if (extraction->spectra == NULL) {
03509 return 1;
03510 }
03511
03512 if (localization->locy == NULL || localization->locw == NULL) {
03513 return 1;
03514 }
03515
03516 if (fiber_position == NULL) {
03517 return 1;
03518 }
03519
03520 if (subslits == NULL) {
03521 return 1;
03522 }
03523
03524 if (grating_data == NULL) {
03525 return 1;
03526 }
03527
03528 if (optical_model == NULL) {
03529 return 1;
03530 }
03531
03532
03533 if (xres_coeff != NULL) {
03534 if (xres_limits == NULL || xres_order == NULL) {
03535 return 1;
03536 }
03537 }
03538
03539
03540
03541
03542
03543
03544
03545 _exspectra = giraffe_image_get(extraction->spectra);
03546
03547 if (extraction->error != NULL) {
03548 _exerrors = giraffe_image_get(extraction->error);
03549 }
03550
03551 _optical_model = cpl_matrix_get_data(optical_model);
03552
03553 nspectra = cpl_image_get_size_x(_exspectra);
03554
03555 om_sign = (_optical_model[O_NX] >= 0) ? 1 : -1;
03556
03557 if (scale == GIREBIN_SCALE_LOG) {
03558 log_scale = TRUE;
03559 }
03560
03561
03562
03563
03564
03565
03566 if (range == GIREBIN_RANGE_SETUP) {
03567
03568
03569
03570
03571
03572 wlmin = cpl_matrix_get(grating_data, 2, 0);
03573 wlmax = cpl_matrix_get(grating_data, 4, 0);
03574
03575 if (log_scale == TRUE) {
03576 wlmin = log(wlmin);
03577 wlmax = log(wlmax);
03578 }
03579
03580 }
03581 else {
03582
03583
03584
03585
03586
03587 status = giraffe_rebin_compute_lambda_range(fiber_position,
03588 optical_model,
03589 grating_data, log_scale,
03590 TRUE, &wlmin, &wlmax);
03591
03592 }
03593
03594 rbsize = 1 + (cxint) ((wlmax - wlmin) / rbstep);
03595
03596 if (rbsize < 0) {
03597
03598 cpl_msg_debug(fctid, "Invalid dispersion direction [%d], changing "
03599 "optical model orientation", om_sign);
03600
03601 om_sign = -om_sign;
03602 _optical_model[O_NX] = -_optical_model[O_NX];
03603
03604 status = giraffe_rebin_compute_lambda_range(fiber_position,
03605 optical_model,
03606 grating_data, log_scale,
03607 TRUE, &wlmin, &wlmax);
03608
03609 rbsize = 1 + (cxint) ((wlmax - wlmin) / rbstep);
03610
03611 }
03612
03613 if (rbsize < 1) {
03614 cpl_msg_error(fctid, "Invalid size %d of rebinned spectra, "
03615 "aborting...", rbsize);
03616 return 2;
03617 }
03618
03619
03620
03621
03622
03623
03624 locPos.type = GILOCDATATYPE_FITTED_DATA;
03625 locPos.centroids = giraffe_image_get(localization->locy);
03626 locPos.widths = giraffe_image_get(localization->locw);
03627
03628 binPrms.min = wlmin;
03629 binPrms.step = rbstep;
03630 binPrms.size = rbsize;
03631 binPrms.log = log_scale;
03632
03633 if (xres_coeff == NULL || (xres_order->xdeg == 0 &&
03634 xres_order->ydeg == 0)) {
03635 binPrms.xres = FALSE;
03636 }
03637 else {
03638 binPrms.xres = TRUE;
03639 }
03640
03641 abscissa = giraffe_rebin_compute_rebin_abcissa(fiber_position, &locPos,
03642 subslits, xres_limits,
03643 xres_coeff, grating_data,
03644 optical_model, wlen_offsets,
03645 lmrq_models[opt_mod_id],
03646 binPrms);
03647
03648
03649
03650
03651
03652
03653 wavelengths = cpl_matrix_new(rbsize, 1);
03654
03655 for (i = 0; i < rbsize; i++) {
03656 cpl_matrix_set(wavelengths, i, 0, wlmin + (cxdouble) i * rbstep);
03657 }
03658
03659 rbspectra = giraffe_image_create(CPL_TYPE_DOUBLE, nspectra, rbsize);
03660 _rbspectra = giraffe_image_get(rbspectra);
03661
03662 if (_exerrors != NULL) {
03663 rberrors = giraffe_image_create(CPL_TYPE_DOUBLE, nspectra, rbsize);
03664 _rberrors = giraffe_image_get(rberrors);
03665 }
03666
03667 switch (method) {
03668 case GIREBIN_METHOD_LINEAR:
03669 status = _giraffe_resample_linear(_rbspectra, _rberrors, abscissa,
03670 _exspectra, _exerrors, om_sign);
03671 break;
03672
03673 case GIREBIN_METHOD_SPLINE:
03674 status = _giraffe_resample_spline(_rbspectra, _rberrors, abscissa,
03675 _exspectra, _exerrors, om_sign);
03676 break;
03677
03678 default:
03679
03680
03681
03682 gi_error("Invalid rebinning method!");
03683 break;
03684 }
03685
03686 cpl_image_delete(abscissa);
03687 abscissa = NULL;
03688
03689 if (status != 0) {
03690 cpl_msg_error(fctid, "Error during rebinning, aborting...");
03691
03692 cpl_matrix_delete(wavelengths);
03693 wavelengths = NULL;
03694
03695 giraffe_image_delete(rbspectra);
03696 rbspectra = NULL;
03697
03698 if (rberrors != NULL) {
03699 giraffe_image_delete(rberrors);
03700 rberrors = NULL;
03701 }
03702
03703 return 3;
03704 }
03705
03706
03707
03708
03709
03710
03711
03712 switch (scale) {
03713 case GIREBIN_SCALE_LOG:
03714 {
03715 cxsize nw = cpl_matrix_get_nrow(wavelengths);
03716
03717 cxdouble mm2nm = log(GI_MM_TO_NM);
03718
03719 setup.wmin = mm2nm + cpl_matrix_get(wavelengths, 0, 0);
03720 setup.wcenter = mm2nm + cpl_matrix_get(wavelengths, nw / 2, 0);
03721 setup.wmax = mm2nm + cpl_matrix_get(wavelengths, nw - 1, 0);
03722 setup.wstep = rbstep;
03723
03724 setup.units = "log(nm)";
03725 setup.offset = 0;
03726 }
03727 break;
03728
03729 case GIREBIN_SCALE_LINEAR:
03730 {
03731 cxsize nw = cpl_matrix_get_nrow(wavelengths);
03732
03733 setup.wmin = GI_MM_TO_NM * cpl_matrix_get(wavelengths, 0, 0);
03734 setup.wcenter = GI_MM_TO_NM * cpl_matrix_get(wavelengths,
03735 nw / 2, 0);
03736 setup.wmax = GI_MM_TO_NM * cpl_matrix_get(wavelengths,
03737 nw - 1, 0);
03738 setup.wstep = GI_MM_TO_NM * rbstep;
03739
03740 setup.units = "nm";
03741 setup.offset = 0;
03742 }
03743 break;
03744
03745 default:
03746
03747
03748
03749 gi_error("Invalid scaling option!");
03750 break;
03751 }
03752
03753 cpl_matrix_delete(wavelengths);
03754 wavelengths = NULL;
03755
03756
03757 switch (method) {
03758 case GIREBIN_METHOD_LINEAR:
03759 setup.method = "linear";
03760 break;
03761
03762 case GIREBIN_METHOD_SPLINE:
03763 setup.method = "spline";
03764 break;
03765
03766 default:
03767
03768
03769
03770 gi_error("Invalid rebinning method!");
03771 break;
03772 }
03773
03774
03775 switch (scale) {
03776 case GIREBIN_SCALE_LINEAR:
03777 setup.scale = "linear";
03778 break;
03779
03780 case GIREBIN_SCALE_LOG:
03781 setup.scale = "logarithmic";
03782 break;
03783
03784 default:
03785
03786
03787
03788 gi_error("Invalid scaling option!");
03789 break;
03790 }
03791
03792 switch (range) {
03793 case GIREBIN_RANGE_SETUP:
03794 setup.range = "setup";
03795 break;
03796
03797 case GIREBIN_RANGE_COMMON:
03798 setup.range = "common";
03799 break;
03800
03801 default:
03802
03803
03804
03805 gi_error("Invalid range option!");
03806 break;
03807 }
03808
03809
03810
03811
03812
03813
03814 giraffe_error_push();
03815
03816 properties = giraffe_image_get_properties(extraction->spectra);
03817 giraffe_image_set_properties(rbspectra, properties);
03818
03819 if (cpl_error_get_code() != CPL_ERROR_NONE) {
03820 giraffe_image_delete(rbspectra);
03821 rbspectra = NULL;
03822
03823 if (rberrors != NULL) {
03824 giraffe_image_delete(rberrors);
03825 rberrors = NULL;
03826 }
03827
03828 return 4;
03829 }
03830
03831 giraffe_error_pop();
03832
03833 status = _giraffe_resample_update_properties(rbspectra, &setup);
03834
03835 if (status != 0) {
03836 giraffe_image_delete(rbspectra);
03837 rbspectra = NULL;
03838
03839 if (rberrors != NULL) {
03840 giraffe_image_delete(rberrors);
03841 rberrors = NULL;
03842 }
03843
03844 return 4;
03845 }
03846
03847
03848
03849
03850
03851
03852 if (_rberrors != NULL) {
03853
03854 giraffe_error_push();
03855
03856 properties = giraffe_image_get_properties(extraction->error);
03857 giraffe_image_set_properties(rberrors, properties);
03858
03859 if (cpl_error_get_code() != CPL_ERROR_NONE) {
03860 giraffe_image_delete(rbspectra);
03861 rbspectra = NULL;
03862
03863 if (rberrors != NULL) {
03864 giraffe_image_delete(rberrors);
03865 rberrors = NULL;
03866 }
03867
03868 return 5;
03869 }
03870
03871 giraffe_error_pop();
03872
03873 status = _giraffe_resample_update_properties(rberrors, &setup);
03874
03875 if (status != 0) {
03876 giraffe_image_delete(rbspectra);
03877 rbspectra = NULL;
03878
03879 if (rberrors != NULL) {
03880 giraffe_image_delete(rberrors);
03881 rberrors = NULL;
03882 }
03883
03884 return 5;
03885 }
03886
03887 }
03888
03889 result->spectra = rbspectra;
03890 result->errors = rberrors;
03891
03892 return 0;
03893
03894 }
03895
03896
03904 GiRange *
03905 giraffe_rebin_get_wavelength_range(GiImage *spectra, GiTable *wlsolution,
03906 GiTable *grating, GiTable *slitgeometry,
03907 cxbool common)
03908 {
03909
03910 cxint status = 0;
03911
03912 cxdouble min = 0.;
03913 cxdouble max = 0.;
03914
03915 cpl_matrix *optical_model = NULL;
03916 cpl_matrix *grating_data = NULL;
03917
03918 GiFiberPosition *positions = NULL;
03919 GiSlitGeo *subslits = NULL;
03920
03921 GiWcalSolution *wcal = NULL;
03922
03923 GiRange *range = NULL;
03924
03925
03926 if (spectra == NULL) {
03927 return NULL;
03928 }
03929
03930 if (grating == NULL) {
03931 return NULL;
03932 }
03933
03934 if (slitgeometry == NULL) {
03935 return NULL;
03936 }
03937
03938
03939 wcal = _giraffe_wcalsolution_create(wlsolution);
03940
03941 if (wcal == NULL) {
03942 return NULL;
03943 }
03944
03945 optical_model = _giraffe_rebin_setup_model(spectra, wcal);
03946
03947 if (optical_model == NULL) {
03948 _giraffe_wcalsolution_delete(wcal);
03949 return NULL;
03950 }
03951
03952 _giraffe_wcalsolution_delete(wcal);
03953
03954 grating_data = _giraffe_rebin_setup_grating(spectra, grating,
03955 wlsolution);
03956
03957 if (grating_data == NULL) {
03958
03959 cpl_matrix_delete(grating_data);
03960 cpl_matrix_delete(optical_model);
03961
03962 return NULL;
03963
03964 }
03965
03966 positions = _giraffe_fiberposition_new();
03967 subslits = _giraffe_slitgeo_new();
03968
03969 status = _giraffe_slitgeo_setup(slitgeometry, positions, subslits,
03970 FALSE);
03971
03972 if (status != 0) {
03973
03974 _giraffe_slitgeo_delete(subslits);
03975 _giraffe_fiberposition_delete(positions);
03976
03977 cpl_matrix_delete(grating_data);
03978 cpl_matrix_delete(optical_model);
03979
03980 return NULL;
03981
03982 }
03983
03984 status = giraffe_rebin_compute_lambda_range(positions, optical_model,
03985 grating_data,
03986 GIREBIN_SCALE_LINEAR,
03987 common, &min, &max);
03988
03989
03990
03991
03992
03993 min *= GI_MM_TO_NM;
03994 max *= GI_MM_TO_NM;
03995
03996 _giraffe_slitgeo_delete(subslits);
03997 _giraffe_fiberposition_delete(positions);
03998
03999 cpl_matrix_delete(grating_data);
04000 cpl_matrix_delete(optical_model);
04001
04002 range = giraffe_range_create(min, max);
04003
04004 return range;
04005
04006 }
04007
04008
04042 cxint
04043 giraffe_rebin_spectra(GiRebinning *rebinning,
04044 const GiExtraction *extraction,
04045 const GiTable *fibers,
04046 const GiLocalization *localization,
04047 const GiTable *grating,
04048 const GiTable *slitgeo,
04049 const GiTable *solution,
04050 const GiRebinConfig *config)
04051 {
04052
04053 const cxchar* const fctid = "giraffe_rebin_spectra";
04054
04055
04056 cxint status = 0;
04057 cxint ex_sp_extr_pixels = 0;
04058 cxint calc_rebinned_size = 0;
04059 cxint default_rebinned_size = GIREBIN_SIZE_Y_DEFAULT;
04060
04061 cxdouble rbin_multiplier = 0.;
04062 cxdouble ex_sp_pixsize_x = 0.;
04063 cxdouble rbin_stepsize = 0.;
04064
04065 cpl_matrix* grat_params = NULL;
04066 cpl_matrix* opt_mod_params = NULL;
04067 cpl_matrix* wloffsets = NULL;
04068
04069 cpl_table* _fibers = NULL;
04070
04071 cpl_propertylist* _pl_ext_sp = NULL;
04072 cpl_propertylist* _pl_wsol = NULL;
04073
04074 GiImage* ex_sp_frame = NULL;
04075 GiImage* ex_sp_err_frame = NULL;
04076 GiImage* loc_y_frame = NULL;
04077 GiImage* loc_w_frame = NULL;
04078
04079 GiSlitGeo* subslit_fibers = NULL;
04080 GiSlitGeo* wav_coeffs = NULL;
04081 GiSlitGeo* wav_limits = NULL;
04082
04083 GiGrat* grating_data = NULL;
04084
04085 GiFiberPosition* fiber_slit_position = NULL;
04086
04087 GiWcalSolution* wcalib_solution = NULL;
04088
04089 GiBinnParams xres_polynom_deg = {0, 0};
04090
04091
04092
04093
04094
04095
04096
04097 if (extraction == NULL) {
04098 cpl_msg_error(fctid, "No extracted data, aborting...");
04099 return 1;
04100 }
04101
04102 if (extraction->spectra == NULL) {
04103 cpl_msg_error(fctid, "No extracted spectra, aborting...");
04104 return 1;
04105 }
04106
04107 if (fibers == NULL) {
04108 cpl_msg_error(fctid, "No fiber table, aborting ...");
04109 return 1;
04110 }
04111
04112 if (localization == NULL) {
04113 cpl_msg_error(fctid, "No localization data, aborting...");
04114 return 1;
04115 }
04116
04117 if (localization->locy == NULL) {
04118 cpl_msg_error(fctid, "No localization centroids, aborting...");
04119 return 1;
04120 }
04121
04122 if (localization->locw == NULL) {
04123 cpl_msg_error(fctid, "No localization widths, aborting...");
04124 return 1;
04125 }
04126
04127 if (grating == NULL) {
04128 cpl_msg_error(fctid, "No grating data, aborting...");
04129 return 1;
04130 }
04131
04132 if (rebinning == NULL) {
04133 cpl_msg_error(fctid, "No rebinning results container, aborting...");
04134 return 1;
04135 }
04136
04137 if (config == NULL) {
04138 cpl_msg_error(fctid, "No rebinning configuration data, aborting...");
04139 return 1;
04140 }
04141
04142 if (solution == NULL) {
04143 cpl_msg_error(fctid, "No wavecalibration solution, aborting...");
04144 return 1;
04145 }
04146
04147 ex_sp_frame = extraction->spectra;
04148 ex_sp_err_frame = extraction->error;
04149 loc_y_frame = localization->locy;
04150 loc_w_frame = localization->locw;
04151
04152 _pl_ext_sp = giraffe_image_get_properties(ex_sp_frame);
04153 _pl_wsol = giraffe_table_get_properties(solution);
04154
04155
04156 _fibers = giraffe_table_get(fibers);
04157 cx_assert(_fibers != NULL);
04158
04159
04160
04161
04162
04163
04164
04165
04166
04167
04168
04169 if (cpl_propertylist_has(_pl_ext_sp, GIALIAS_PIXSIZX) == TRUE) {
04170 ex_sp_pixsize_x = cpl_propertylist_get_double(_pl_ext_sp,
04171 GIALIAS_PIXSIZX);
04172
04173 }
04174 else {
04175 cpl_msg_error(fctid, "%s Keyword missing in Extracted Spectra "
04176 "Frame, aborting ...", GIALIAS_PIXSIZX);
04177 return 2;
04178 }
04179
04180
04181
04182
04183
04184
04185 if (ex_sp_pixsize_x > 1.) {
04186 ex_sp_pixsize_x /= 1000.;
04187 }
04188
04189
04190
04191
04192
04193
04194 if (cpl_propertylist_has(_pl_ext_sp, GIALIAS_GRATNAME) == TRUE) {
04195
04196 const cxchar* _string = NULL;
04197
04198 _string = cpl_propertylist_get_string(_pl_ext_sp, GIALIAS_GRATNAME);
04199
04200 if (strncmp(_string, "LR", 2) == 0) {
04201 rbin_multiplier = 4.;
04202 }
04203 else if (strncmp(_string, "HR", 2) == 0) {
04204 rbin_multiplier = 1.;
04205 }
04206 else {
04207 rbin_multiplier = 1.;
04208 }
04209
04210 }
04211 else {
04212 cpl_msg_error(fctid, "%s Keyword missing in Extracted Spectra Frame, "
04213 "aborting ...", GIALIAS_GRATNAME);
04214 return 2;
04215 }
04216
04217
04218
04219
04220
04221
04222 if (cpl_propertylist_has(_pl_ext_sp, GIALIAS_EXT_NX) == TRUE) {
04223 ex_sp_extr_pixels = cpl_propertylist_get_int(_pl_ext_sp,
04224 GIALIAS_EXT_NX);
04225
04226 }
04227 else {
04228 cpl_msg_error(fctid, "%s Keyword missing in Extracted Spectra Frame, "
04229 "aborting ...", GIALIAS_EXT_NX);
04230 return 2;
04231 }
04232
04233
04234
04235
04236
04237
04238 grating_data = _giraffe_grating_new();
04239
04240 status = _giraffe_grating_setup(grating, ex_sp_frame, grating_data);
04241
04242 if (status != 0) {
04243 cpl_msg_error(fctid, "Unable to retrieve grating information, "
04244 "aborting...");
04245 _giraffe_grating_delete(grating_data);
04246 return 3;
04247 }
04248
04249
04250
04251
04252
04253 fiber_slit_position = _giraffe_fiberposition_new();
04254 subslit_fibers = _giraffe_slitgeo_new();
04255
04256 status = _giraffe_slitgeo_setup(slitgeo, fiber_slit_position,
04257 subslit_fibers, FALSE);
04258
04259 if (status != 0) {
04260 cpl_msg_error(fctid, "Unable to retrieve slit geometry information, "
04261 "aborting...");
04262 _giraffe_grating_delete(grating_data);
04263 _giraffe_fiberposition_delete(fiber_slit_position);
04264 _giraffe_slitgeo_delete(subslit_fibers);
04265 return 7;
04266 }
04267
04268
04269 wcalib_solution = _giraffe_wcalsolution_create(solution);
04270
04271 if (wcalib_solution == NULL) {
04272 cpl_msg_error(fctid, "Cannot create wavelength solution, "
04273 "aborting ...");
04274 _giraffe_grating_delete(grating_data);
04275 _giraffe_fiberposition_delete(fiber_slit_position);
04276 _giraffe_slitgeo_delete(subslit_fibers);
04277 return 4;
04278 }
04279
04280 if (cpl_propertylist_has(_pl_wsol, GIALIAS_WSOL_OMFCOLL) == TRUE) {
04281 grating_data->fcoll =
04282 cpl_propertylist_get_double(_pl_wsol, GIALIAS_WSOL_OMFCOLL);
04283 }
04284
04285 if (cpl_propertylist_has(_pl_wsol, GIALIAS_WSOL_OMGCAM) == TRUE) {
04286 grating_data->gcam =
04287 cpl_propertylist_get_double(_pl_wsol, GIALIAS_WSOL_OMGCAM);
04288 }
04289
04290 if (cpl_propertylist_has(_pl_wsol, GIALIAS_WSOL_OMGTHETA) == TRUE) {
04291 grating_data->theta =
04292 cpl_propertylist_get_double(_pl_wsol, GIALIAS_WSOL_OMGTHETA);
04293 }
04294
04295 if (cpl_propertylist_has(_pl_wsol, GIALIAS_WSOL_OMSDX) == TRUE) {
04296 grating_data->slitdx =
04297 cpl_propertylist_get_double(_pl_wsol, GIALIAS_WSOL_OMSDX);
04298 }
04299
04300 if (cpl_propertylist_has(_pl_wsol, GIALIAS_WSOL_OMSDY) == TRUE) {
04301 grating_data->slitdy =
04302 cpl_propertylist_get_double(_pl_wsol, GIALIAS_WSOL_OMSDY);
04303 }
04304
04305 if (cpl_propertylist_has(_pl_wsol, GIALIAS_WSOL_OMSPHI) == TRUE) {
04306 grating_data->slitphi =
04307 cpl_propertylist_get_double(_pl_wsol, GIALIAS_WSOL_OMSPHI);
04308 }
04309
04310
04311
04312
04313
04314
04315
04316
04317 if (cpl_table_has_column(_fibers, "WLRES") != 0) {
04318
04319 cxint fiber = 0;
04320 cxint nfibers = cpl_table_get_nrow(_fibers);
04321
04322
04323 wloffsets = cpl_matrix_new(nfibers, 1);
04324
04325 for (fiber = 0; fiber < nfibers; ++fiber) {
04326
04327 cxdouble wloffset = cpl_table_get_double(_fibers, "WLRES",
04328 fiber, NULL);
04329
04330
04331 wloffset *= -GI_NM_TO_MM;
04332 cpl_matrix_set(wloffsets, fiber, 0, wloffset);
04333
04334 }
04335
04336 cpl_msg_info(fctid, "Applying SIMCAL wavelength corrections ...");
04337
04338 }
04339
04340
04341
04342
04343
04344
04345
04346
04347
04348
04349
04350
04351 if (config->scmethod == GIREBIN_SCALE_LOG) {
04352
04353 cxint rebin_size;
04354
04355 cxdouble wlenmax;
04356 cxdouble wlenmin;
04357
04358 rebin_size = default_rebinned_size;
04359
04360 wlenmin = log(grating_data->wlenmin / GI_MM_TO_NM);
04361 wlenmax = log(grating_data->wlenmax / GI_MM_TO_NM);
04362
04363 if ((config->size != rebin_size) && (config->size != 0)) {
04364 rebin_size = config->size;
04365 }
04366
04367 rbin_stepsize = (wlenmax - wlenmin) / rebin_size;
04368
04369 calc_rebinned_size = 1 + (cxint) ((wlenmax-wlenmin)/ rbin_stepsize);
04370
04371 }
04372 else {
04373
04374 cxint rebin_size;
04375
04376 cxdouble wlenmax;
04377 cxdouble wlenmin;
04378
04379 wlenmin = grating_data->wlenmin / GI_MM_TO_NM;
04380 wlenmax = grating_data->wlenmax / GI_MM_TO_NM;
04381
04382 rbin_stepsize = (config->lstep / GI_MM_TO_NM) * rbin_multiplier;
04383 rebin_size = (wlenmax - wlenmin) / rbin_stepsize;
04384
04385 if ((config->size != rebin_size) && (config->size != 0)) {
04386 rebin_size = config->size;
04387 rbin_stepsize = (wlenmax - wlenmin) / rebin_size;
04388 }
04389
04390 calc_rebinned_size = 1 + (cxint) ((wlenmax-wlenmin) / rbin_stepsize);
04391
04392 }
04393
04394
04395
04396
04397
04398 if (wcalib_solution!=NULL) {
04399
04400 if (wcalib_solution->opt_mod==LMRQ_XOPTMOD) {
04401
04402 cxint nrow;
04403 cxdouble opt_direction, fcoll, cfact;
04404
04405 nrow = cpl_matrix_get_nrow(wcalib_solution->opt_mod_params);
04406 if (nrow==4) {
04407 opt_direction =
04408 cpl_matrix_get(wcalib_solution->opt_mod_params, 0, 0);
04409 fcoll =
04410 cpl_matrix_get(wcalib_solution->opt_mod_params, 1, 0);
04411 cfact =
04412 cpl_matrix_get(wcalib_solution->opt_mod_params, 2, 0);
04413
04414 opt_mod_params = cpl_matrix_new(4,1);
04415 cpl_matrix_set(opt_mod_params, 0, 0,
04416 ex_sp_extr_pixels * opt_direction);
04417 cpl_matrix_set(opt_mod_params, 1, 0, ex_sp_pixsize_x);
04418 cpl_matrix_set(opt_mod_params, 2, 0, fcoll);
04419 cpl_matrix_set(opt_mod_params, 3, 0, cfact);
04420 }
04421 else {
04422 cpl_msg_error(fctid, "Invalid number of physical optical "
04423 "parameters, aborting...");
04424
04425 if (wloffsets != NULL) {
04426 cpl_matrix_delete(wloffsets);
04427 }
04428
04429 _giraffe_wcalsolution_delete(wcalib_solution);
04430 _giraffe_grating_delete(grating_data);
04431 _giraffe_fiberposition_delete(fiber_slit_position);
04432 _giraffe_slitgeo_delete(subslit_fibers);
04433 return 6;
04434 }
04435
04436 }
04437 else if (wcalib_solution->opt_mod==LMRQ_XOPTMOD2) {
04438
04439 cxint nrow;
04440 cxdouble opt_direction, fcoll, cfact, gtheta, slitdx,
04441 slitdy, slitphi;
04442
04443 nrow = cpl_matrix_get_nrow(wcalib_solution->opt_mod_params);
04444 if (nrow==7) {
04445 opt_direction =
04446 cpl_matrix_get(wcalib_solution->opt_mod_params, 0, 0);
04447 fcoll =
04448 cpl_matrix_get(wcalib_solution->opt_mod_params, 1, 0);
04449 cfact =
04450 cpl_matrix_get(wcalib_solution->opt_mod_params, 2, 0);
04451 gtheta =
04452 cpl_matrix_get(wcalib_solution->opt_mod_params, 3, 0);
04453 slitdx =
04454 cpl_matrix_get(wcalib_solution->opt_mod_params, 4, 0);
04455 slitdy =
04456 cpl_matrix_get(wcalib_solution->opt_mod_params, 5, 0);
04457 slitphi =
04458 cpl_matrix_get(wcalib_solution->opt_mod_params, 6, 0);
04459
04460 opt_mod_params = cpl_matrix_new(7,1);
04461 cpl_matrix_set(opt_mod_params, 0, 0,
04462 ex_sp_extr_pixels * opt_direction);
04463 cpl_matrix_set(opt_mod_params, 1, 0, ex_sp_pixsize_x);
04464 cpl_matrix_set(opt_mod_params, 2, 0, fcoll);
04465 cpl_matrix_set(opt_mod_params, 3, 0, cfact);
04466 cpl_matrix_set(opt_mod_params, 4, 0, slitdx);
04467 cpl_matrix_set(opt_mod_params, 5, 0, slitdy);
04468 cpl_matrix_set(opt_mod_params, 6, 0, slitphi);
04469
04470 }
04471 else {
04472 cpl_msg_error(fctid, "Invalid number of physical optical "
04473 "parameters, aborting...");
04474
04475 if (wloffsets != NULL) {
04476 cpl_matrix_delete(wloffsets);
04477 }
04478
04479 _giraffe_wcalsolution_delete(wcalib_solution);
04480 _giraffe_grating_delete(grating_data);
04481 _giraffe_fiberposition_delete(fiber_slit_position);
04482 _giraffe_slitgeo_delete(subslit_fibers);
04483 return 6;
04484 }
04485
04486 }
04487 else {
04488 cpl_msg_error(fctid, "Invalid optical model, aborting...");
04489
04490 if (wloffsets != NULL) {
04491 cpl_matrix_delete(wloffsets);
04492 }
04493
04494 _giraffe_wcalsolution_delete(wcalib_solution);
04495 _giraffe_grating_delete(grating_data);
04496 _giraffe_fiberposition_delete(fiber_slit_position);
04497 _giraffe_slitgeo_delete(subslit_fibers);
04498 return 5;
04499 }
04500
04501
04502 if (wcalib_solution->wav_coeffs != NULL) {
04503
04504 GiSlitGeo* coeffs = wcalib_solution->wav_coeffs;
04505
04506 xres_polynom_deg.xdeg =
04507 cpl_matrix_get_nrow(_giraffe_slitgeo_get(coeffs, 0));
04508 xres_polynom_deg.ydeg =
04509 cpl_matrix_get_ncol(_giraffe_slitgeo_get(coeffs, 0));
04510 }
04511
04512 }
04513 else {
04514 cpl_msg_error(fctid, "No Wavelength Calibration solution found, "
04515 "aborting...");
04516
04517 if (wloffsets != NULL) {
04518 cpl_matrix_delete(wloffsets);
04519 }
04520
04521 _giraffe_wcalsolution_delete(wcalib_solution);
04522 _giraffe_grating_delete(grating_data);
04523 _giraffe_fiberposition_delete(fiber_slit_position);
04524 _giraffe_slitgeo_delete(subslit_fibers);
04525 return 4;
04526 }
04527
04528 if (config->xresiduals==FALSE) {
04529 xres_polynom_deg.xdeg = 0;
04530 xres_polynom_deg.ydeg = 0;
04531 }
04532
04533 if (wcalib_solution->wav_coeffs!=NULL) {
04534 wav_coeffs = wcalib_solution->wav_coeffs;
04535 }
04536
04537 if (wcalib_solution->wav_limits!=NULL) {
04538 wav_limits = wcalib_solution->wav_limits;
04539 }
04540
04541
04542
04543
04544
04545
04546 grat_params = cpl_matrix_new(7,1);
04547
04548 cpl_matrix_set(grat_params, 0, 0, grating_data->theta);
04549 cpl_matrix_set(grat_params, 1, 0, grating_data->order);
04550 cpl_matrix_set(grat_params, 2, 0, grating_data->wlenmin / GI_MM_TO_NM);
04551 cpl_matrix_set(grat_params, 3, 0, grating_data->wlen0 / GI_MM_TO_NM);
04552 cpl_matrix_set(grat_params, 4, 0, grating_data->wlenmax / GI_MM_TO_NM);
04553 cpl_matrix_set(grat_params, 5, 0, grating_data->resol);
04554 cpl_matrix_set(grat_params, 6, 0, grating_data->space );
04555
04556
04557
04558
04559
04560
04561 cpl_msg_info(fctid, "Performing Rebinning of spectra, stepsize=%.4f "
04562 "[nm], resulting image size=%d, using x residuals : %s",
04563 rbin_stepsize * GI_MM_TO_NM, calc_rebinned_size,
04564 config->xresiduals ? "Yes" : "No");
04565
04566
04567 switch (config->rmethod) {
04568 case GIREBIN_METHOD_LINEAR:
04569 cpl_msg_info(fctid, "Rebinning method : linear");
04570 break;
04571
04572 case GIREBIN_METHOD_SPLINE:
04573 cpl_msg_info(fctid, "Rebinning method : spline");
04574 break;
04575
04576 default:
04577 cpl_msg_info(fctid, "Rebinning method : undefined");
04578 break;
04579 }
04580
04581 switch (config->scmethod) {
04582 case GIREBIN_SCALE_LOG:
04583 cpl_msg_info(fctid, "Scaling method : logarithmic, "
04584 "log(wavelength [nm]): min,max,range = %.3f, %.3f, %.3f",
04585 log(grating_data->wlenmin),
04586 log(grating_data->wlenmax),
04587 log(grating_data->wlenmax) -
04588 log(grating_data->wlenmin));
04589 break;
04590
04591 case GIREBIN_SCALE_LINEAR:
04592 cpl_msg_info(fctid, "Scaling method : linear, wavelength [nm]: "
04593 "min,max,range = %.3f, %.3f, %.3f",
04594 grating_data->wlenmin,
04595 grating_data->wlenmax,
04596 grating_data->wlenmax - grating_data->wlenmin);
04597 break;
04598
04599 default:
04600 cpl_msg_info(fctid, "Scaling method : undefined");
04601 break;
04602 }
04603
04604 switch (config->range) {
04605 case GIREBIN_RANGE_SETUP:
04606 cpl_msg_info(fctid, "Wavelength range : Setup");
04607 break;
04608
04609 case GIREBIN_RANGE_COMMON:
04610 cpl_msg_info(fctid, "Wavelength range : Common");
04611 break;
04612
04613 default:
04614 cpl_msg_info(fctid, "Wavelength range : undefined");
04615 break;
04616 }
04617
04618
04619
04620
04621
04622
04623 status = _giraffe_resample_spectra(rebinning, extraction,
04624 localization, fiber_slit_position,
04625 subslit_fibers, wav_limits,
04626 wav_coeffs, &xres_polynom_deg,
04627 grat_params, opt_mod_params,
04628 wloffsets, rbin_stepsize,
04629 config->rmethod, config->range,
04630 config->scmethod);
04631
04632 if (status != 0) {
04633
04634 if (wloffsets != NULL) {
04635 cpl_matrix_delete(wloffsets);
04636 }
04637
04638 cpl_matrix_delete(opt_mod_params);
04639 cpl_matrix_delete(grat_params);
04640
04641 _giraffe_wcalsolution_delete(wcalib_solution);
04642 _giraffe_grating_delete(grating_data);
04643 _giraffe_fiberposition_delete(fiber_slit_position);
04644 _giraffe_slitgeo_delete(subslit_fibers);
04645
04646 return 8;
04647
04648 }
04649
04650
04651
04652
04653
04654
04655 if (wloffsets != NULL) {
04656 cpl_matrix_delete(wloffsets);
04657 }
04658
04659 cpl_matrix_delete(opt_mod_params);
04660 cpl_matrix_delete(grat_params);
04661
04662 _giraffe_wcalsolution_delete(wcalib_solution);
04663 _giraffe_grating_delete(grating_data);
04664 _giraffe_fiberposition_delete(fiber_slit_position);
04665 _giraffe_slitgeo_delete(subslit_fibers);
04666
04667 return 0;
04668
04669 }
04670
04671
04684 GiRebinning*
04685 giraffe_rebinning_new(void)
04686 {
04687
04688 GiRebinning *rebinn = cx_malloc(sizeof(GiRebinning));
04689
04690 rebinn->spectra = NULL;
04691 rebinn->errors = NULL;
04692
04693 return rebinn;
04694
04695 }
04696
04713 GiRebinning*
04714 giraffe_rebinning_create(GiImage *spectra, GiImage *errors)
04715 {
04716
04717 GiRebinning *rebin = giraffe_rebinning_new();
04718
04719 if (spectra) {
04720 rebin->spectra = spectra;
04721 }
04722
04723 if (errors) {
04724 rebin->errors = errors;
04725 }
04726
04727 return rebin;
04728
04729 }
04730
04731
04750 void
04751 giraffe_rebinning_delete(GiRebinning *rebinning)
04752 {
04753
04754 if (rebinning) {
04755 cx_free(rebinning);
04756 }
04757
04758 return;
04759
04760 }
04761
04762
04778 void
04779 giraffe_rebinning_destroy(GiRebinning *rebinning)
04780 {
04781
04782 if (rebinning) {
04783
04784 if (rebinning->spectra) {
04785 giraffe_image_delete(rebinning->spectra);
04786 rebinning->spectra = NULL;
04787 }
04788
04789 if (rebinning->errors) {
04790 giraffe_image_delete(rebinning->errors);
04791 rebinning->errors = NULL;
04792 }
04793
04794 cx_free(rebinning);
04795 }
04796
04797 return;
04798
04799 }
04800
04801
04816 GiRebinConfig *
04817 giraffe_rebin_config_create(cpl_parameterlist *list)
04818 {
04819
04820 const cxchar *fctid = "giraffe_rebin_config_create";
04821
04822 const cxchar *s;
04823
04824 cpl_parameter *p;
04825
04826 GiRebinConfig *config = NULL;
04827
04828
04829 if (!list) {
04830 return NULL;
04831 }
04832
04833 config = cx_calloc(1, sizeof *config);
04834
04835
04836 config->rmethod = GIREBIN_METHOD_UNDEFINED;
04837 config->xresiduals = FALSE;
04838 config->lstep = 0.0;
04839 config->scmethod = GIREBIN_SCALE_UNDEFINED;
04840 config->size = 0;
04841 config->range = GIREBIN_RANGE_UNDEFINED;
04842
04843
04844 p = cpl_parameterlist_find(list, "giraffe.rebinning.method");
04845 s = cpl_parameter_get_string(p);
04846 if (strcmp(s, "linear")==0) {
04847 config->rmethod = GIREBIN_METHOD_LINEAR;
04848 } else if (strcmp(s, "spline")==0) {
04849 config->rmethod = GIREBIN_METHOD_SPLINE;
04850 }
04851
04852 p = cpl_parameterlist_find(list, "giraffe.rebinning.xresiduals");
04853 config->xresiduals = cpl_parameter_get_bool(p);
04854
04855 p = cpl_parameterlist_find(list, "giraffe.rebinning.lstep");
04856 config->lstep = cpl_parameter_get_double(p);
04857
04858 p = cpl_parameterlist_find(list, "giraffe.rebinning.scalemethod");
04859 s = cpl_parameter_get_string(p);
04860 if (strcmp(s, "log")==0) {
04861 config->scmethod = GIREBIN_SCALE_LOG;
04862 } else if (strcmp(s, "linear")==0) {
04863 config->scmethod = GIREBIN_SCALE_LINEAR;
04864 }
04865
04866 p = cpl_parameterlist_find(list, "giraffe.rebinning.size");
04867 config->size = cpl_parameter_get_int(p);
04868
04869 p = cpl_parameterlist_find(list, "giraffe.rebinning.range");
04870 s = cpl_parameter_get_string(p);
04871 if (strcmp(s, "setup")==0) {
04872 config->range = GIREBIN_RANGE_SETUP;
04873 } else if (strcmp(s, "common")==0) {
04874 config->range = GIREBIN_RANGE_COMMON;
04875 }
04876
04877
04878
04879 if (config->rmethod==GIREBIN_METHOD_UNDEFINED) {
04880 cpl_msg_info(fctid, "Invalid Rebinning method, aborting");
04881 cx_free(config);
04882 return NULL;
04883 }
04884
04885 if (config->scmethod==GIREBIN_SCALE_UNDEFINED) {
04886 cpl_msg_info(fctid, "Invalid Rebinning scaling method, aborting");
04887 cx_free(config);
04888 return NULL;
04889 }
04890
04891 if (config->range==GIREBIN_RANGE_UNDEFINED) {
04892 cpl_msg_info(fctid, "Invalid Rebinning range, aborting");
04893 cx_free(config);
04894 return NULL;
04895 }
04896
04897 return config;
04898
04899 }
04900
04901
04916 void
04917 giraffe_rebin_config_destroy(GiRebinConfig *config)
04918 {
04919
04920 if (config) {
04921 cx_free(config);
04922 }
04923
04924 return;
04925
04926 }
04927
04940 void
04941 giraffe_rebin_config_add(cpl_parameterlist *list)
04942 {
04943
04944 cpl_parameter *p;
04945
04946 if (!list) {
04947 return;
04948 }
04949
04950 p = cpl_parameter_new_enum("giraffe.rebinning.method",
04951 CPL_TYPE_STRING,
04952 "Method to use : `linear' or `spline'",
04953 "giraffe.rebinning.method",
04954 "linear", 2, "linear", "spline");
04955 cpl_parameter_set_alias(p, CPL_PARAMETER_MODE_CLI, "rbin-method");
04956 cpl_parameterlist_append(list, p);
04957
04958 p = cpl_parameter_new_value("giraffe.rebinning.xresiduals",
04959 CPL_TYPE_BOOL,
04960 "Use x residuals during rebinning? `true'/"
04961 "`false'",
04962 "giraffe.rebinning.xresiduals",
04963 TRUE);
04964 cpl_parameter_set_alias(p, CPL_PARAMETER_MODE_CLI, "rbin-xresid");
04965 cpl_parameterlist_append(list, p);
04966
04967 p = cpl_parameter_new_value("giraffe.rebinning.lstep",
04968 CPL_TYPE_DOUBLE,
04969 "Lambda step size, only used if "
04970 "scaling method is 'linear'",
04971 "giraffe.rebinning.lstep",
04972 0.005);
04973 cpl_parameter_set_alias(p, CPL_PARAMETER_MODE_CLI, "rbin-lstep");
04974 cpl_parameterlist_append(list, p);
04975
04976 p = cpl_parameter_new_enum("giraffe.rebinning.scalemethod",
04977 CPL_TYPE_STRING,
04978 "Scaling method: `log' or `linear'",
04979 "giraffe.rebinning.scalemethod",
04980 "linear", 2, "linear", "log");
04981 cpl_parameter_set_alias(p, CPL_PARAMETER_MODE_CLI, "rbin-scmethod");
04982 cpl_parameterlist_append(list, p);
04983
04984 p = cpl_parameter_new_value("giraffe.rebinning.size",
04985 CPL_TYPE_INT,
04986 "Size of output rebinned spectra, 0 means "
04987 "calculate size based on wavelength range "
04988 "and lambda stepsize",
04989 "giraffe.rebinning.size",
04990 0);
04991 cpl_parameter_set_alias(p, CPL_PARAMETER_MODE_CLI, "rbin-size");
04992 cpl_parameterlist_append(list, p);
04993
04994 p = cpl_parameter_new_enum("giraffe.rebinning.range",
04995 CPL_TYPE_STRING,
04996 "Rebinning range: `setup' or `common'",
04997 "giraffe.rebinning.scalemethod",
04998 "setup", 2, "setup", "common");
04999 cpl_parameter_set_alias(p, CPL_PARAMETER_MODE_CLI, "rbin-range");
05000 cpl_parameterlist_append(list, p);
05001
05002 return;
05003
05004 }