GIRAFFE Pipeline Reference Manual

giwlsolution.c

00001 /* $Id: giwlsolution.c,v 1.17 2007/08/23 08:39:06 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: 2007/08/23 08:39:06 $
00024  * $Revision: 1.17 $
00025  * $Name: giraffe-2_9 $
00026  */
00027 
00028 #ifdef HAVE_CONFIG_H
00029 #  include <config.h>
00030 #endif
00031 
00032 #include <stdlib.h>
00033 #include <math.h>
00034 
00035 #include <cxmap.h>
00036 #include <cxstring.h>
00037 #include <cxstrutils.h>
00038 
00039 #include <cpl_error.h>
00040 #include <cpl_propertylist.h>
00041 
00042 #include "gialias.h"
00043 #include "gierror.h"
00044 #include "giimage.h"
00045 #include "gitable.h"
00046 #include "gichebyshev.h"
00047 #include "giwlsolution.h"
00048 
00049 
00058 struct GiWlSolution {
00059 
00060     GiModel *model;
00061 
00062     cxbool subslits;
00063     GiWlResiduals *residuals;
00064 
00065 };
00066 
00067 
00068 inline static GiWlSolution *
00069 _giraffe_wlsolution_new(const cxchar *name)
00070 {
00071 
00072     GiWlSolution *self = cx_calloc(1, sizeof *self);
00073 
00074 
00075     if (self) {
00076 
00077         self->model = giraffe_model_new(name);
00078 
00079         if (self->model == NULL) {
00080             giraffe_wlsolution_delete(self);
00081             return NULL;
00082         }
00083 
00084         if (giraffe_model_get_type(self->model) != GI_MODEL_XOPT) {
00085             giraffe_wlsolution_delete(self);
00086             return NULL;
00087         }
00088 
00089         self->subslits = FALSE;
00090         self->residuals = NULL;
00091 
00092     }
00093 
00094     return self;
00095 
00096 }
00097 
00098 
00099 GiWlSolution *
00100 giraffe_wlsolution_new(const cxchar *name, cxint orientation, cxint npixels,
00101                        cxdouble pixelsize, GiGrating *grating)
00102 {
00103 
00104     GiWlSolution *self = NULL;
00105 
00106 
00107     if (name == NULL) {
00108         return self;
00109     }
00110 
00111     if (grating == NULL) {
00112         return self;
00113     }
00114 
00115 
00116     self = _giraffe_wlsolution_new(name);
00117 
00118     if (self) {
00119 
00120         orientation = orientation < 0 ? -npixels : npixels;
00121         pixelsize /= 1000.;
00122 
00123         giraffe_error_push();
00124 
00125         giraffe_model_set_parameter(self->model, "Orientation",
00126                                     orientation);
00127         giraffe_model_set_parameter(self->model, "Order",
00128                                     grating->order);
00129         giraffe_model_set_parameter(self->model, "PixelSize",
00130                                     pixelsize);
00131         giraffe_model_set_parameter(self->model, "FocalLength",
00132                                     grating->fcoll);
00133         giraffe_model_set_parameter(self->model, "Magnification",
00134                                     grating->gcam);
00135         giraffe_model_set_parameter(self->model, "Angle",
00136                                     grating->theta);
00137         giraffe_model_set_parameter(self->model, "Spacing",
00138                                     grating->space);
00139 
00140         if (strcmp(name, "xoptmod2") == 0) {
00141 
00142             giraffe_model_set_parameter(self->model, "Sdx", grating->sdx);
00143             giraffe_model_set_parameter(self->model, "Sdy", grating->sdy);
00144             giraffe_model_set_parameter(self->model, "Sphi", grating->sphi);
00145 
00146         }
00147 
00148         if (cpl_error_get_code() != CPL_ERROR_NONE) {
00149             giraffe_wlsolution_delete(self);
00150             return NULL;
00151         }
00152 
00153         giraffe_error_pop();
00154 
00155     }
00156 
00157     return self;
00158 
00159 }
00160 
00161 
00175 GiWlSolution *
00176 giraffe_wlsolution_clone(const GiWlSolution *other)
00177 {
00178 
00179     GiWlSolution *self = NULL;
00180 
00181 
00182     if (other != NULL) {
00183 
00184         self = cx_calloc(1, sizeof(GiWlSolution));
00185 
00186         self->model = giraffe_model_clone(other->model);
00187 
00188         self->subslits = other->subslits;
00189         self->residuals = giraffe_wlresiduals_clone(other->residuals);
00190 
00191     }
00192 
00193     return self;
00194 
00195 }
00196 
00197 
00213 GiWlSolution *
00214 giraffe_wlsolution_create(GiTable *solution, GiImage *spectra,
00215                           GiGrating *grating)
00216 {
00217 
00218     const cxchar *name = NULL;
00219 
00220     cxint npixels = 0;
00221     cxint orientation = 0;
00222 
00223     cxdouble pixelsize = 0.;
00224     cxdouble fcoll = 0.;
00225     cxdouble gcam = 0.;
00226     cxdouble theta = 0.;
00227     cxdouble sdx = 0.;
00228     cxdouble sdy = 0.;
00229     cxdouble sphi = 0.;
00230 
00231 
00232     cpl_propertylist *properties = NULL;
00233 
00234     GiWlSolution *self = NULL;
00235 
00236 
00237 
00238     if (solution == NULL) {
00239         return NULL;
00240     }
00241 
00242     if (giraffe_table_get_properties(solution) == NULL) {
00243         return NULL;
00244     }
00245 
00246     if (giraffe_table_get(solution) == NULL) {
00247         return NULL;
00248     }
00249 
00250 
00251     if (spectra == NULL) {
00252         return NULL;
00253     }
00254 
00255     if (giraffe_image_get_properties(spectra) == NULL) {
00256         return NULL;
00257     }
00258 
00259     if (giraffe_image_get(spectra) == NULL) {
00260         return NULL;
00261     }
00262 
00263 
00264     if (grating == NULL) {
00265         return NULL;
00266     }
00267 
00268 
00269     /*
00270      * Setup the optical model from the wavelength solution table properties,
00271      * the grating setup and the reference spectrum.
00272      */
00273 
00274     /*
00275      * Reference image: number of pixels and pixel size
00276      */
00277 
00278     properties = giraffe_image_get_properties(spectra);
00279 
00280     if (!cpl_propertylist_has(properties, GIALIAS_PIXSIZX)) {
00281         return NULL;
00282     }
00283     else {
00284 
00285         /*
00286          * Get pixel size and convert it from microns to mm.
00287          */
00288 
00289         pixelsize = cpl_propertylist_get_double(properties, GIALIAS_PIXSIZX);
00290         pixelsize /= 1000.;
00291 
00292     }
00293 
00294     npixels = cpl_image_get_size_y(giraffe_image_get(spectra));
00295 
00296 
00297     /*
00298      * Wavelength solution properties: orientation, collimator focal
00299      * length, camera magnification, grating angle and slit offsets.
00300      */
00301 
00302     properties = giraffe_table_get_properties(solution);
00303 
00304 
00305     if (!cpl_propertylist_has(properties, GIALIAS_WSOL_OMNAME)) {
00306         return NULL;
00307     }
00308     else {
00309         name = cpl_propertylist_get_string(properties, GIALIAS_WSOL_OMNAME);
00310     }
00311 
00312 
00313     self = _giraffe_wlsolution_new(name);
00314 
00315     if (self) {
00316 
00317         if (!cpl_propertylist_has(properties, GIALIAS_WSOL_SUBSLITS)) {
00318             giraffe_wlsolution_delete(self);
00319             return NULL;
00320         }
00321         else {
00322 
00323             self->subslits = cpl_propertylist_get_bool(properties,
00324                                                        GIALIAS_WSOL_SUBSLITS);
00325 
00326         }
00327 
00328         if (!cpl_propertylist_has(properties, GIALIAS_WSOL_OMDIR)) {
00329             giraffe_wlsolution_delete(self);
00330             return NULL;
00331         }
00332         else {
00333             orientation = cpl_propertylist_get_int(properties,
00334                                                    GIALIAS_WSOL_OMDIR);
00335             orientation = orientation < 0 ? -fabs(npixels) : fabs(npixels);
00336         }
00337 
00338 
00339         if (!cpl_propertylist_has(properties, GIALIAS_WSOL_OMFCOLL)) {
00340             giraffe_wlsolution_delete(self);
00341             return NULL;
00342         }
00343         else {
00344             fcoll = cpl_propertylist_get_double(properties,
00345                                                 GIALIAS_WSOL_OMFCOLL);
00346         }
00347 
00348 
00349         if (!cpl_propertylist_has(properties, GIALIAS_WSOL_OMGCAM)) {
00350             giraffe_wlsolution_delete(self);
00351             return NULL;
00352         }
00353         else {
00354             gcam = cpl_propertylist_get_double(properties,
00355                                                GIALIAS_WSOL_OMGCAM);
00356         }
00357 
00358 
00359         if (!cpl_propertylist_has(properties, GIALIAS_WSOL_OMGTHETA)) {
00360             giraffe_wlsolution_delete(self);
00361             return NULL;
00362         }
00363         else {
00364             theta = cpl_propertylist_get_double(properties,
00365                                                 GIALIAS_WSOL_OMGTHETA);
00366         }
00367 
00368 
00369         if (strcmp(name, "xoptmod2") == 0) {
00370 
00371             if (!cpl_propertylist_has(properties, GIALIAS_WSOL_OMSDX)) {
00372                 giraffe_wlsolution_delete(self);
00373                 return NULL;
00374             }
00375             else {
00376                 sdx = cpl_propertylist_get_double(properties,
00377                                                   GIALIAS_WSOL_OMSDX);
00378             }
00379 
00380 
00381             if (!cpl_propertylist_has(properties, GIALIAS_WSOL_OMSDY)) {
00382                 giraffe_wlsolution_delete(self);
00383                 return NULL;
00384             }
00385             else {
00386                 sdy = cpl_propertylist_get_double(properties,
00387                                                   GIALIAS_WSOL_OMSDY);
00388             }
00389 
00390 
00391             if (!cpl_propertylist_has(properties, GIALIAS_WSOL_OMSPHI)) {
00392                 giraffe_wlsolution_delete(self);
00393                 return NULL;
00394             }
00395             else {
00396                 sphi = cpl_propertylist_get_double(properties,
00397                                                    GIALIAS_WSOL_OMSPHI);
00398             }
00399 
00400         }
00401 
00402 
00403         /*
00404          * Initialize the optical model parameters
00405          */
00406 
00407         giraffe_error_push();
00408 
00409         giraffe_model_set_parameter(self->model, "Orientation", orientation);
00410         giraffe_model_set_parameter(self->model, "Order", grating->order);
00411         giraffe_model_set_parameter(self->model, "PixelSize", pixelsize);
00412         giraffe_model_set_parameter(self->model, "FocalLength", fcoll);
00413         giraffe_model_set_parameter(self->model, "Magnification", gcam);
00414         giraffe_model_set_parameter(self->model, "Angle", theta);
00415         giraffe_model_set_parameter(self->model, "Spacing", grating->space);
00416 
00417         if (strcmp(name, "xoptmod2") == 0) {
00418             giraffe_model_set_parameter(self->model, "Sdx", sdx);
00419             giraffe_model_set_parameter(self->model, "Sdy", sdy);
00420             giraffe_model_set_parameter(self->model, "Sphi", sphi);
00421         }
00422 
00423         if (cpl_error_get_code() != CPL_ERROR_NONE) {
00424             giraffe_wlsolution_delete(self);
00425             return NULL;
00426         }
00427 
00428         giraffe_error_pop();
00429 
00430 
00431         /*
00432          * Get the wavelength residuals fit coefficients from the wavelength
00433          * solution table.
00434          */
00435 
00436         self->residuals = giraffe_wlresiduals_create(solution);
00437 
00438         if (self->residuals == NULL) {
00439             self->subslits = FALSE;
00440         }
00441 
00442     }
00443 
00444     return self;
00445 
00446 }
00447 
00448 
00449 void
00450 giraffe_wlsolution_delete(GiWlSolution *self)
00451 {
00452 
00453     if (self != NULL) {
00454 
00455         if (self->model != NULL) {
00456             giraffe_model_delete(self->model);
00457         }
00458 
00459         if (self->residuals != NULL) {
00460             giraffe_wlresiduals_delete(self->residuals);
00461         }
00462 
00463         cx_free(self);
00464 
00465     }
00466 
00467     return;
00468 
00469 }
00470 
00471 
00472 const cxchar *
00473 giraffe_wlsolution_name(const GiWlSolution *self)
00474 {
00475 
00476     GiModel *model = NULL;
00477 
00478 
00479     cx_assert(self != NULL);
00480 
00481     model = self->model;
00482     cx_assert(model != NULL);
00483 
00484     return giraffe_model_get_name(model);
00485 
00486 }
00487 
00488 
00489 GiModel *
00490 giraffe_wlsolution_model(const GiWlSolution *self)
00491 {
00492 
00493     cx_assert(self != NULL);
00494 
00495     return self->model;
00496 
00497 }
00498 
00499 
00500 cxint
00501 giraffe_wlsolution_set_subslits(GiWlSolution *self, cxbool flag)
00502 {
00503 
00504     cx_assert(self != NULL);
00505 
00506     if (self->residuals != NULL) {
00507         return 1;
00508     }
00509 
00510     self->subslits = flag;
00511 
00512     return 0;
00513 
00514 }
00515 
00516 
00517 cxbool
00518 giraffe_wlsolution_get_subslits(const GiWlSolution *self)
00519 {
00520 
00521     cx_assert(self != NULL);
00522 
00523     return self->subslits;
00524 
00525 }
00526 
00527 
00528 cxint
00529 giraffe_wlsolution_set_residuals(GiWlSolution *self,
00530                                  const GiWlResiduals *residuals)
00531 {
00532 
00533     cxbool subslits = FALSE;
00534 
00535 
00536     cx_assert(self != NULL);
00537 
00538     if (residuals == NULL) {
00539         return 1;
00540     }
00541 
00542 
00543     /* FIXME: This is a very weak check whether the residuals to accept
00544      *        are valid for the current subslits flag setting. A better
00545      *        mechanism needs to be put here, but this needs to be supported
00546      *        by the GiWlResidual class.
00547      */
00548 
00549     subslits = giraffe_wlresiduals_get(residuals, 0) == NULL;
00550 
00551     if (self->subslits != subslits) {
00552         return 2;
00553     }
00554 
00555     giraffe_wlsolution_reset_residuals(self);
00556 
00557     self->residuals = (GiWlResiduals *)residuals;
00558 
00559     return 0;
00560 
00561 }
00562 
00563 
00564 GiWlResiduals *
00565 giraffe_wlsolution_get_residuals(const GiWlSolution *self)
00566 {
00567 
00568     cx_assert(self != NULL);
00569 
00570     return self->residuals;
00571 
00572 }
00573 
00574 
00575 void
00576 giraffe_wlsolution_reset_residuals(GiWlSolution *self)
00577 {
00578 
00579     cx_assert(self != NULL);
00580 
00581     if (self->residuals != NULL) {
00582         giraffe_wlresiduals_delete(self->residuals);
00583         self->residuals = NULL;
00584     }
00585 
00586     return;
00587 
00588 }
00589 
00590 
00591 cxdouble
00592 giraffe_wlsolution_compute_pixel(const GiWlSolution *self, cxdouble lambda,
00593                                  cxdouble x, cxdouble y, cxint *status)
00594 {
00595 
00596     cxint code = 0;
00597     cxint _status = 0;
00598 
00599     cxdouble result = 0.;
00600 
00601 
00602     cx_assert(self != NULL);
00603 
00604     giraffe_error_push();
00605 
00606     giraffe_model_set_argument(self->model, "xf", x);
00607     giraffe_model_set_argument(self->model, "yf", y);
00608     giraffe_model_set_argument(self->model, "lambda", lambda);
00609 
00610     if (cpl_error_get_code() != CPL_ERROR_NONE) {
00611 
00612         if (status != NULL) {
00613             *status = -128;
00614         }
00615 
00616         return result;
00617     }
00618 
00619     giraffe_error_pop();
00620 
00621     code = giraffe_model_evaluate(self->model, &result, &_status);
00622 
00623     if (code != 0) {
00624 
00625         if (status != NULL) {
00626             *status = -128;
00627         }
00628 
00629         return result;
00630 
00631     }
00632 
00633     if (status != NULL) {
00634         *status = _status;
00635     }
00636 
00637     return result;
00638 
00639 }
00640 
00641 
00642 cxdouble
00643 giraffe_wlsolution_compute_residual(const GiWlSolution *self, cxdouble x,
00644                                     cxdouble y)
00645 {
00646 
00647     cxint i;
00648 
00649     cxdouble r = 0.;
00650 
00651     const GiWlResiduals *residuals = NULL;
00652 
00653 
00654     cx_assert(self != NULL);
00655 
00656     residuals = giraffe_wlsolution_get_residuals(self);
00657 
00658     if (residuals == NULL) {
00659         return r;
00660     }
00661 
00662 
00663     /*
00664      * Find first residual fit with matching ranges. This is used
00665      * for the residual computation assuming that the intervals
00666      * for which the fits are valid do not overlap.
00667      */
00668 
00669     for (i = 0; (cxsize)i < giraffe_wlresiduals_get_size(residuals); i++) {
00670 
00671         const GiChebyshev2D *fit = giraffe_wlresiduals_get(residuals, i);
00672 
00673         if (fit != NULL) {
00674 
00675             cxdouble ax;
00676             cxdouble bx;
00677             cxdouble ay;
00678             cxdouble by;
00679 
00680             giraffe_chebyshev2d_get_range(fit, &ax, &bx, &ay, &by);
00681 
00682             if (ax <= x && x <= bx && ay <= y && y <= by) {
00683                 r = giraffe_chebyshev2d_eval(fit, x, y);
00684                 break;
00685             }
00686 
00687         }
00688 
00689     }
00690 
00691     return r;
00692 
00693 }
00694 
00695 
00696 GiTable *
00697 giraffe_wlsolution_create_table(const GiWlSolution *solution)
00698 {
00699 
00700 
00701     cxint sign = 1;
00702 
00703     cxdouble value = 0.;
00704 
00705     cpl_propertylist *properties = NULL;
00706 
00707     GiTable *result = NULL;
00708 
00709     const GiModel *model = NULL;
00710 
00711     const GiWlResiduals *residuals = NULL;
00712 
00713 
00714     if (solution == NULL) {
00715         return NULL;
00716     }
00717 
00718 
00719     result = giraffe_table_new();
00720     cx_assert(result != NULL);
00721 
00722     properties = cpl_propertylist_new();
00723     cx_assert(properties != NULL);
00724 
00725 
00726     /*
00727      * Build up wavelength solution properties
00728      */
00729 
00730     cpl_propertylist_update_string(properties, GIALIAS_GIRFTYPE,
00731                                    "WLSOLUTION");
00732     cpl_propertylist_set_comment(properties, GIALIAS_GIRFTYPE,
00733                                  "Giraffe frame type.");
00734 
00735     cpl_propertylist_update_string(properties, GIALIAS_WSOL_OMNAME,
00736                                    giraffe_wlsolution_name(solution));
00737     cpl_propertylist_set_comment(properties, GIALIAS_WSOL_OMNAME,
00738                                  "Optical model name");
00739 
00740     model = giraffe_wlsolution_model(solution);
00741 
00742     sign = giraffe_model_get_parameter(model,"Orientation") < 0 ? -1 : 1;
00743     cpl_propertylist_update_int(properties, GIALIAS_WSOL_OMDIR, sign);
00744     cpl_propertylist_set_comment(properties, GIALIAS_WSOL_OMDIR,
00745                                  "Optical model orientation");
00746 
00747     value = giraffe_model_get_parameter(model, "FocalLength");
00748     cpl_propertylist_update_double(properties, GIALIAS_WSOL_OMFCOLL, value);
00749     cpl_propertylist_set_comment(properties, GIALIAS_WSOL_OMFCOLL,
00750                                  "Optical model focal length");
00751 
00752     value = giraffe_model_get_parameter(model, "Magnification");
00753     cpl_propertylist_update_double(properties, GIALIAS_WSOL_OMGCAM, value);
00754     cpl_propertylist_set_comment(properties, GIALIAS_WSOL_OMGCAM,
00755                                  "Optical model camera factor");
00756 
00757     value = giraffe_model_get_parameter(model, "Angle");
00758     cpl_propertylist_update_double(properties, GIALIAS_WSOL_OMGTHETA,
00759                                    value);
00760     cpl_propertylist_set_comment(properties, GIALIAS_WSOL_OMGTHETA,
00761                                  "Optical model grating angle");
00762 
00763     if (strcmp(giraffe_wlsolution_name(solution), "xoptmod2") == 0) {
00764 
00765         value = giraffe_model_get_parameter(model, "Sdx");
00766         cpl_propertylist_update_double(properties, GIALIAS_WSOL_OMSDX,
00767                                        value);
00768         cpl_propertylist_set_comment(properties, GIALIAS_WSOL_OMSDX,
00769                                      "Optical model slit x-offset");
00770 
00771         value = giraffe_model_get_parameter(model, "Sdy");
00772         cpl_propertylist_update_double(properties, GIALIAS_WSOL_OMSDY,
00773                                        value);
00774         cpl_propertylist_set_comment(properties, GIALIAS_WSOL_OMSDY,
00775                                      "Optical model slit y-offset");
00776 
00777         value = giraffe_model_get_parameter(model, "Sphi");
00778         cpl_propertylist_update_double(properties, GIALIAS_WSOL_OMSPHI,
00779                                        value);
00780         cpl_propertylist_set_comment(properties, GIALIAS_WSOL_OMSPHI,
00781                                      "Optical model slit rotation");
00782 
00783     }
00784 
00785 
00786     /*
00787      * Add optical model residuals fit coefficients, if they are present
00788      * in the wavelength solution.
00789      */
00790 
00791     residuals = giraffe_wlsolution_get_residuals(solution);
00792 
00793     if (residuals != NULL) {
00794 
00795         cpl_table *coeffs = giraffe_wlresiduals_table(residuals);
00796 
00797         if (coeffs != NULL) {
00798             giraffe_table_set(result, coeffs);
00799         }
00800 
00801     }
00802 
00803     giraffe_table_set_properties(result, properties);
00804 
00805     cpl_propertylist_delete(properties);
00806     properties = NULL;
00807 
00808     return result;
00809 
00810 }

This file is part of the GIRAFFE Pipeline Reference Manual 2.9.0.
Documentation copyright © 2002-2006 European Southern Observatory.
Generated on Thu Jan 26 14:20:29 2012 by doxygen 1.6.3 written by Dimitri van Heesch, © 1997-2004