GIRAFFE Pipeline Reference Manual

girebinning.c

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

This file is part of the GIRAFFE Pipeline Reference Manual 2.10.
Documentation copyright © 2002-2006 European Southern Observatory.
Generated on Thu Mar 7 14:11:02 2013 by doxygen 1.4.7 written by Dimitri van Heesch, © 1997-2004