isaac_spc_startrace.c

00001 /* $Id: isaac_spc_startrace.c,v 1.47 2010/03/02 13:26:12 llundin Exp $
00002  *
00003  * This file is part of the ISAAC Pipeline
00004  * Copyright (C) 2002,2003 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., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
00019  */
00020 
00021 /*
00022  * $Author: llundin $
00023  * $Date: 2010/03/02 13:26:12 $
00024  * $Revision: 1.47 $
00025  * $Name: HEAD $
00026  */
00027 
00028 #ifdef HAVE_CONFIG_H
00029 #include <config.h>
00030 #endif
00031 
00032 /*-----------------------------------------------------------------------------
00033                                 Includes
00034  -----------------------------------------------------------------------------*/
00035 
00036 #include <math.h>
00037 #include <float.h>
00038 #include <cpl.h>
00039 
00040 #include "irplib_plugin.h"
00041 #include "irplib_utils.h"
00042 #include "irplib_spectrum.h"
00043 
00044 #include "isaac_utils.h"
00045 #include "isaac_pfits.h"
00046 #include "isaac_dfs.h"
00047 
00048 /*-----------------------------------------------------------------------------
00049                                 Define
00050  -----------------------------------------------------------------------------*/
00051 
00052 #define RECIPE_STRING "isaac_spc_startrace"
00053 
00054 #define Z_LR_LEFT_REJ       300
00055 #define Z_LR_RIGHT_REJ      325
00056 #define SZ_LR_LEFT_REJ      300
00057 #define SZ_LR_RIGHT_REJ     325
00058 #define J_LR_LEFT_REJ       200
00059 #define J_LR_RIGHT_REJ      200
00060 #define SH_LR_LEFT_REJ      150 
00061 #define SH_LR_RIGHT_REJ     175
00062 #define SK_LR_LEFT_REJ      150
00063 #define SK_LR_RIGHT_REJ     175
00064 #define MR_LEFT_REJ         30
00065 #define MR_RIGHT_REJ        30
00066 
00067 /*-----------------------------------------------------------------------------
00068                             Functions prototypes
00069  -----------------------------------------------------------------------------*/
00070 
00071 static cpl_error_code isaac_spc_startrace_reduce(cpl_frameset *,
00072                                                  const cpl_frameset *,
00073                                                  const cpl_matrix *, char, 
00074                                                  const cpl_parameterlist *);
00075 
00076 static int * isaac_spc_startrace_resol(cpl_frameset *);
00077 static cpl_imagelist * isaac_spc_startrace_load(const cpl_frameset *);
00078 static cpl_matrix * isaac_spc_startrace_starpos(const cpl_frameset *);
00079 static cpl_polynomial * isaac_spc_startrace_shape(cpl_image *, double, char, 
00080         double *);
00081 static cpl_polynomial * isaac_spc_startrace_distor(cpl_polynomial **, 
00082         cpl_vector *, int, int);
00083 static cpl_error_code isaac_spc_startrace_save(cpl_frameset *,
00084                                                const cpl_table *,
00085                                                const cpl_matrix *,
00086                                                const cpl_vector *,
00087                                                cpl_polynomial **,
00088                                                const cpl_frameset *,
00089                                                char, 
00090                                                const cpl_parameterlist *);
00091  
00092 static
00093 cpl_error_code isaac_spc_startrace_fill_parameterlist(cpl_parameterlist *);
00094 
00095 CPL_RECIPE_DEFINE(isaac_spc_startrace, ISAAC_BINARY_VERSION,
00096                   isaac_spc_startrace_fill_parameterlist(recipe->parameters),
00097                   "Lars Lundin", PACKAGE_BUGREPORT, "2002, 2003, 2008", 
00098                   "ISAAC Spectro startrace recipe",
00099                   RECIPE_STRING " -- ISAAC Spectro startrace recipe\n"
00100                   "The files listed in the Set Of Frames (sof-file) " 
00101                   "must be tagged:\n"
00102                   "raw-file.fits "ISAAC_SPC_STARTRACE_IM_RAW" or\n"
00103                   "raw-file.fits "ISAAC_SPC_STARTRACE_SP_RAW"\n"
00104                   "Given N imaging frames, the spectro frames must consist of "
00105                   "N (or zero) low resolution frames and "
00106                   "N (or zero) medium resolution frames.");
00107 
00108 /*-----------------------------------------------------------------------------
00109                             Static variables
00110  -----------------------------------------------------------------------------*/
00111 
00112 static struct {
00113     /* Inputs */
00114     int         degree;
00115     int         spec_width;
00116     int         reject_left;
00117     int         reject_right;
00118     int         display;
00119     /* Outputs */
00120     int         arm;
00121     isaac_band  band;
00122     double      corr_is1;
00123     double      corr_is2;
00124     double      corr_is3;
00125     double      shapes_fit_q;
00126     double      dist1;
00127     double      distx;
00128     double      disty;
00129     double      distxy;
00130     double      distxx;
00131     double      distyy;
00132 } isaac_spc_startrace_config;
00133 
00134 /*-----------------------------------------------------------------------------
00135                                 Functions code
00136  -----------------------------------------------------------------------------*/
00137 
00138 /*----------------------------------------------------------------------------*/
00146 /*----------------------------------------------------------------------------*/
00147 static
00148 cpl_error_code isaac_spc_startrace_fill_parameterlist(cpl_parameterlist * self)
00149 {
00150     const char * context = PACKAGE "." RECIPE_STRING;
00151     cpl_error_code err;
00152 
00153     cpl_ensure_code(self, CPL_ERROR_NULL_INPUT);
00154 
00155     /* Fill the parameters list */
00156 
00157     /* --degree */
00158     err = irplib_parameterlist_set_int(self, PACKAGE, RECIPE_STRING,
00159                                        "degree", 3, "deg",
00160                                        context, "polynomial degree");
00161     cpl_ensure_code(!err, err);
00162 
00163     /* --spec_width */
00164     err = irplib_parameterlist_set_int(self, PACKAGE, RECIPE_STRING,
00165                                        "spectrum_width", 40, "spec_width",
00166                                        context, "spectrum width");
00167     cpl_ensure_code(!err, err);
00168 
00169      /* --reject_left */
00170     err = irplib_parameterlist_set_int(self, PACKAGE, RECIPE_STRING,
00171                                        "reject_left", -1, NULL,
00172                                        context, "left part rejection");
00173     cpl_ensure_code(!err, err);
00174 
00175      /* --reject_right */
00176     err = irplib_parameterlist_set_int(self, PACKAGE, RECIPE_STRING,
00177                                        "reject_right", -1, NULL,
00178                                        context, "right part rejection");
00179     cpl_ensure_code(!err, err);
00180 
00181     /* --display */
00182     err = irplib_parameterlist_set_bool(self, PACKAGE, RECIPE_STRING,
00183                                         "display", CPL_FALSE, NULL, context,
00184                                         "Flag to make plots");
00185     cpl_ensure_code(!err, err);
00186 
00187     return CPL_ERROR_NONE;
00188 }
00189 
00190 
00191 /*----------------------------------------------------------------------------*/
00199 /*----------------------------------------------------------------------------*/
00200 static int isaac_spc_startrace(cpl_frameset            * framelist,
00201                                const cpl_parameterlist * parlist)
00202 {
00203     const char          *   sval;
00204     int                 *   labels = NULL;
00205     const cpl_frame     *   cur_frame;
00206     cpl_propertylist    *   plist = NULL;
00207     cpl_frameset        *   imframes = NULL;
00208     cpl_frameset        *   spframes = NULL;
00209     cpl_frameset        *   spframes_lr = NULL;
00210     cpl_frameset        *   spframes_mr = NULL;
00211     cpl_matrix          *   star_pos = NULL;
00212     int                     ndone = 0;
00213     
00214 
00215     bug_if(0);
00216 
00217     /* Retrieve input parameters */
00218 
00219     /* Polynomial degree */
00220     isaac_spc_startrace_config.degree
00221         = irplib_parameterlist_get_int(parlist, PACKAGE, RECIPE_STRING,
00222                                        "degree");
00223     /* Spectrum width */
00224     isaac_spc_startrace_config.spec_width
00225         = irplib_parameterlist_get_int(parlist, PACKAGE, RECIPE_STRING,
00226                                        "spectrum_width");
00227     /* Rejection parameters */
00228     isaac_spc_startrace_config.reject_left
00229         = irplib_parameterlist_get_int(parlist, PACKAGE, RECIPE_STRING,
00230                                        "reject_left");
00231     isaac_spc_startrace_config.reject_right
00232         = irplib_parameterlist_get_int(parlist, PACKAGE, RECIPE_STRING,
00233                                        "reject_right");
00234     /* Display */
00235     isaac_spc_startrace_config.display
00236         = irplib_parameterlist_get_bool(parlist, PACKAGE, RECIPE_STRING,
00237                                         "display");
00238 
00239     /* Identify the RAW and CALIB frames in the input frameset */
00240     skip_if (isaac_dfs_set_groups(framelist));
00241  
00242     /* Get the arm used (SW or LW) */
00243     cur_frame = cpl_frameset_get_first_const(framelist);
00244     error_if(cur_frame == NULL, CPL_ERROR_DATA_NOT_FOUND,
00245              "Could not get 1st frame from frameset");
00246     plist = cpl_propertylist_load(cpl_frame_get_filename(cur_frame), 0);
00247     any_if("Could not load propertylist from 1st frame");
00248 
00249     sval = isaac_pfits_get_arm(plist);
00250     any_if("Could not get the arm");
00251 
00252     if (sval[0] == 'S') {
00253         isaac_spc_startrace_config.arm = 1;
00254     } else if (sval[0] == 'L') {
00255         isaac_spc_startrace_config.arm = 2;
00256     } else {
00257         error_if(1, CPL_ERROR_UNSUPPORTED_MODE, "Unsupported arm: %s", sval);
00258     }
00259 
00260     /* Get the band */
00261     sval = isaac_pfits_get_filter(plist);
00262     any_if("Could not get the filter");
00263 
00264     isaac_spc_startrace_config.band = isaac_get_bbfilter(sval);
00265     any_if("Could not get the band");
00266 
00267     cpl_propertylist_empty(plist);
00268     
00269     /* Retrieve raw frames */
00270     imframes = isaac_extract_frameset(framelist, ISAAC_SPC_STARTRACE_IM_RAW);
00271     error_if(imframes == NULL, CPL_ERROR_DATA_NOT_FOUND, "Could not find the "
00272              "imframes in the input list");
00273 
00274     spframes = isaac_extract_frameset(framelist, ISAAC_SPC_STARTRACE_SP_RAW);
00275     error_if(spframes == NULL, CPL_ERROR_DATA_NOT_FOUND, "Could not find the "
00276              "spframes in the input list");
00277 
00278     /* Separate LR and MR spectra */
00279     labels = isaac_spc_startrace_resol(spframes);
00280     error_if(labels == NULL, cpl_error_get_code(), "Could not differentiate "
00281              "LR and MR");
00282 
00283     spframes_lr = cpl_frameset_extract(spframes, labels, 1);
00284     spframes_mr = cpl_frameset_extract(spframes, labels, 2);
00285     cpl_free(labels);
00286     labels = NULL;
00287     cpl_frameset_delete(spframes);
00288     spframes = NULL;
00289     
00290     /* Get the star positions */
00291     cpl_msg_info(cpl_func, "Get the star positions");
00292     star_pos = isaac_spc_startrace_starpos(imframes);
00293     error_if(star_pos == NULL, cpl_error_get_code(), "Could not find star the "
00294              "positions");
00295 
00296     cpl_frameset_delete(imframes);
00297     imframes = NULL;
00298 
00299     error_if (spframes_lr == NULL && spframes_mr == NULL,
00300               CPL_ERROR_UNSUPPORTED_MODE, "The %d spectro frames are not LR "
00301               "nor MR", cpl_frameset_get_size(spframes));
00302 
00303     if (spframes_lr != NULL) {
00304         cpl_errorstate prestate = cpl_errorstate_get();
00305         /* Reduction in LR */
00306         cpl_msg_info(cpl_func, "Reducing the LR spectra");
00307         if (isaac_spc_startrace_reduce(framelist, spframes_lr, star_pos,
00308                                        'L', parlist)) {
00309             irplib_error_recover(prestate, "Could not reduce the LR spectra");
00310         } else {
00311             ndone++;
00312         }
00313         cpl_frameset_delete(spframes_lr);
00314         spframes_lr = NULL;
00315     }
00316     if (spframes_mr != NULL) {
00317         cpl_errorstate prestate = cpl_errorstate_get();
00318         /* Reduction in MR */
00319         cpl_msg_info(cpl_func, "Reducing the MR spectra");
00320         if (isaac_spc_startrace_reduce(framelist, spframes_mr, star_pos,
00321                                        'M', parlist)) {
00322             irplib_error_recover(prestate, "Could not reduce the MR spectra");
00323         } else {
00324             ndone++;
00325         }
00326         cpl_frameset_delete(spframes_mr);
00327         spframes_mr = NULL;
00328     }
00329 
00330     error_if(!ndone, CPL_ERROR_ILLEGAL_INPUT, "Could not reduce the spectra");
00331 
00332     end_skip;
00333 
00334     cpl_free(labels);
00335     cpl_propertylist_delete(plist);
00336     cpl_frameset_delete(imframes);
00337     cpl_frameset_delete(spframes);
00338     cpl_frameset_delete(spframes_lr);
00339     cpl_frameset_delete(spframes_mr);
00340     cpl_matrix_delete(star_pos);
00341 
00342     return cpl_error_get_code();
00343 }
00344 
00345 /*----------------------------------------------------------------------------*/
00356 /*----------------------------------------------------------------------------*/
00357 static
00358 cpl_error_code isaac_spc_startrace_reduce(cpl_frameset            * framelist,
00359                                           const cpl_frameset      * spframes,
00360                                           const cpl_matrix        * star_pos,
00361                                           char                      resol,
00362                                           const cpl_parameterlist * parlist)
00363 {
00364     /* Load the input images */
00365     cpl_imagelist   * ilist = isaac_spc_startrace_load(spframes);
00366     const int         nframes = cpl_frameset_get_size(spframes);
00367     cpl_vector      * spec_pos = cpl_vector_new(nframes);
00368     double          * pspec_pos = cpl_vector_get_data(spec_pos);
00369     cpl_polynomial  * corresp = cpl_polynomial_new(1);
00370     cpl_polynomial ** shapes = cpl_calloc(nframes, sizeof(cpl_polynomial*));
00371     cpl_vector      * fit_q = cpl_vector_new(nframes);
00372     double          * pfit_q = cpl_vector_get_data(fit_q);
00373     const int         nx = cpl_image_get_size_x(cpl_imagelist_get(ilist, 0));
00374     cpl_polynomial  * distor = NULL;
00375     cpl_table       * out_tab = NULL;
00376     int               power[2];
00377     const int         maxdeg = 2;
00378     int               i;
00379 
00380     bug_if(0);
00381     bug_if(framelist == NULL);
00382     bug_if(star_pos == NULL);
00383     bug_if(parlist == NULL);
00384 
00385     error_if(cpl_matrix_get_ncol(star_pos) != nframes,
00386              CPL_ERROR_INCOMPATIBLE_INPUT, "Number of spectro frames (%d) "
00387              "differ from number of star positions (%d)", nframes,
00388              cpl_matrix_get_ncol(star_pos));
00389 
00390     /* Find the spectra positions */
00391     for (i=0; i<nframes; i++) {
00392         const cpl_image * image = cpl_imagelist_get_const(ilist, i);
00393         const double mean = cpl_image_get_mean(image);
00394         const double min_bright = 20.0 * mean;
00395 
00396         error_if (irplib_spectrum_find_brightest(image, 0, NO_SHADOW,
00397                                                  min_bright, 0, &(pspec_pos[i])),
00398                   cpl_error_get_code(), "Could not detect spectrum in frame %d "
00399                   "of %d with mean flux=%g", i+1, nframes, mean);
00400     }
00401 
00402     /* Compute spectra / star correspondance */
00403     error_if (cpl_polynomial_fit(corresp, star_pos, NULL, spec_pos, NULL,
00404                                  CPL_FALSE, NULL, &maxdeg), cpl_error_get_code(),
00405               "Could not fit a %d degree polynomial to the %d positions",
00406               maxdeg, nframes);
00407 
00408     /* Store the result coefficients */
00409     i = 0;
00410     isaac_spc_startrace_config.corr_is1 = cpl_polynomial_get_coeff(corresp, &i);
00411     i = 1;
00412     isaac_spc_startrace_config.corr_is2 = cpl_polynomial_get_coeff(corresp, &i);
00413     i = 2;
00414     isaac_spc_startrace_config.corr_is3 = cpl_polynomial_get_coeff(corresp, &i);
00415     cpl_polynomial_delete(corresp);
00416     corresp = NULL;
00417     
00418     /* Compute the spectra shapes */
00419     for (i=0; i<nframes; i++) {
00420         shapes[i] = isaac_spc_startrace_shape(cpl_imagelist_get(ilist, i),
00421                                               cpl_vector_get(spec_pos, i), 
00422                                               resol, 
00423                                               &(pfit_q[i]));
00424 
00425         error_if (shapes[i] == NULL, cpl_error_get_code(), "Could not get the "
00426                   "shape of frame %d of %d", 1+i,nframes);
00427 
00428         cpl_msg_info(cpl_func, "Spectrum %d : Y = %g; Fit mse = %g", i+1,
00429                      cpl_vector_get(spec_pos, i), pfit_q[i]);
00430     }
00431     isaac_spc_startrace_config.shapes_fit_q = cpl_vector_get_median_const(fit_q);
00432     cpl_vector_delete(fit_q);
00433     fit_q = NULL;
00434     cpl_imagelist_delete(ilist);
00435     ilist = NULL;
00436 
00437     /* Compute the 2d distortion */
00438     distor = isaac_spc_startrace_distor(shapes, spec_pos, nframes, nx);
00439     error_if (distor == NULL, cpl_error_get_code(),  "Could not compute the "
00440               "distortion");
00441    
00442     /* Create the table */
00443     out_tab = cpl_table_new(6);
00444     cpl_table_new_column(out_tab, "Degree_of_x", CPL_TYPE_INT);
00445     cpl_table_new_column(out_tab, "Degree_of_y", CPL_TYPE_INT);
00446     cpl_table_new_column(out_tab, "poly2d_coef", CPL_TYPE_DOUBLE);
00447     power[0] = 0; power[1] = 0;
00448     cpl_table_set_int(out_tab, "Degree_of_x", 0, power[0]);
00449     cpl_table_set_int(out_tab, "Degree_of_y", 0, power[1]);
00450     isaac_spc_startrace_config.dist1 = cpl_polynomial_get_coeff(distor, power);
00451     cpl_table_set_double(out_tab, "poly2d_coef", 0,
00452             isaac_spc_startrace_config.dist1);
00453     power[0] = 1; power[1] = 0;
00454     cpl_table_set_int(out_tab, "Degree_of_x", 1, power[0]);
00455     cpl_table_set_int(out_tab, "Degree_of_y", 1, power[1]);
00456     isaac_spc_startrace_config.distx = cpl_polynomial_get_coeff(distor, power);
00457     cpl_table_set_double(out_tab, "poly2d_coef", 1,
00458             isaac_spc_startrace_config.distx);
00459     power[0] = 0; power[1] = 1;
00460     cpl_table_set_int(out_tab, "Degree_of_x", 2, power[0]);
00461     cpl_table_set_int(out_tab, "Degree_of_y", 2, power[1]);
00462     isaac_spc_startrace_config.disty = cpl_polynomial_get_coeff(distor, power);
00463     cpl_table_set_double(out_tab, "poly2d_coef", 2,
00464             isaac_spc_startrace_config.disty);
00465     power[0] = 1; power[1] = 1;
00466     cpl_table_set_int(out_tab, "Degree_of_x", 3, power[0]);
00467     cpl_table_set_int(out_tab, "Degree_of_y", 3, power[1]);
00468     isaac_spc_startrace_config.distxy = cpl_polynomial_get_coeff(distor, power);
00469     cpl_table_set_double(out_tab, "poly2d_coef", 3,
00470             isaac_spc_startrace_config.distxy);
00471     power[0] = 2; power[1] = 0;
00472     cpl_table_set_int(out_tab, "Degree_of_x", 4, power[0]);
00473     cpl_table_set_int(out_tab, "Degree_of_y", 4, power[1]);
00474     isaac_spc_startrace_config.distxx = cpl_polynomial_get_coeff(distor, power);
00475     cpl_table_set_double(out_tab, "poly2d_coef", 4,
00476             isaac_spc_startrace_config.distxx);
00477     power[0] = 0; power[1] = 2;
00478     cpl_table_set_int(out_tab, "Degree_of_x", 5, power[0]);
00479     cpl_table_set_int(out_tab, "Degree_of_y", 5, power[1]);
00480     isaac_spc_startrace_config.distyy = cpl_polynomial_get_coeff(distor, power);
00481     cpl_table_set_double(out_tab, "poly2d_coef", 5,
00482             isaac_spc_startrace_config.distyy);
00483 
00484     cpl_polynomial_delete(distor);
00485     distor = NULL;
00486 
00487     /* Display result */
00488     cpl_msg_info(cpl_func, 
00489             "Distortion : Y(x,y) = a + bx + cy + dxy + exx + fyy");
00490     cpl_msg_info(cpl_func, "a = %g", isaac_spc_startrace_config.dist1);
00491     cpl_msg_info(cpl_func, "b = %g", isaac_spc_startrace_config.distx);
00492     cpl_msg_info(cpl_func, "c = %g", isaac_spc_startrace_config.disty);
00493     cpl_msg_info(cpl_func, "d = %g", isaac_spc_startrace_config.distxy);
00494     cpl_msg_info(cpl_func, "e = %g", isaac_spc_startrace_config.distxx);
00495     cpl_msg_info(cpl_func, "f = %g", isaac_spc_startrace_config.distyy);
00496 
00497     /* Write the product */
00498     skip_if (isaac_spc_startrace_save(framelist, out_tab, star_pos, spec_pos,
00499                                       shapes, spframes, resol, parlist));
00500 
00501     end_skip;
00502 
00503     cpl_polynomial_delete(distor);
00504     cpl_vector_delete(fit_q);
00505     cpl_polynomial_delete(corresp);
00506     if (shapes != NULL) {
00507         for (i = 0; i < nframes; i++) cpl_polynomial_delete(shapes[i]);
00508         cpl_free(shapes);
00509     }
00510     cpl_vector_delete(spec_pos);
00511     cpl_imagelist_delete(ilist);
00512     cpl_table_delete(out_tab);
00513 
00514     return cpl_error_get_code();
00515 }
00516 
00517 /*----------------------------------------------------------------------------*/
00525 /*----------------------------------------------------------------------------*/
00526 static int * isaac_spc_startrace_resol(cpl_frameset * spframes)
00527 {
00528     int                     nframes;
00529     int                 *   labels;
00530     cpl_frame           *   cur_frame;
00531     cpl_propertylist    *   plist;
00532     const char          *   sval;
00533     int                     i;
00534 
00535     /* Test entries */
00536     if (spframes == NULL) return NULL;
00537 
00538     /* Initialise */
00539     nframes = cpl_frameset_get_size(spframes);
00540 
00541     /* Create output array */
00542     labels = cpl_malloc(nframes * sizeof(int));
00543 
00544     /* Loop on the frames */
00545     for (i=0; i<nframes; i++) {
00546         cur_frame = cpl_frameset_get_frame(spframes, i);
00547         plist=cpl_propertylist_load(cpl_frame_get_filename(cur_frame), 0);
00548         /* Get the resolution */
00549         if ((sval = isaac_pfits_get_resolution(plist)) == NULL) {
00550             cpl_free(labels);
00551             cpl_msg_error(cpl_func,"cannot get the resolution");
00552             return NULL;
00553         }
00554         if (sval[0]=='L') labels[i] = 1;
00555         else if (sval[0]=='M') labels[i] = 2;
00556         else labels[i] = 0;
00557         cpl_propertylist_delete(plist);
00558     }
00559     return labels;
00560 }
00561    
00562 /*----------------------------------------------------------------------------*/
00569 /*----------------------------------------------------------------------------*/
00570 static cpl_matrix * isaac_spc_startrace_starpos(const cpl_frameset * imframes)
00571 {
00572     int                     nframes;
00573     cpl_matrix          *   ypositions;
00574     cpl_apertures       *   objects;
00575     double              *   ypos;
00576     cpl_imagelist       *   ilist;
00577     int                     i;
00578 
00579     /* Test entries */
00580     if (imframes == NULL) return NULL;
00581 
00582     /* Load the input images */
00583     if ((ilist = isaac_spc_startrace_load(imframes)) == NULL) return NULL;
00584 
00585     /* Initialise */
00586     nframes = cpl_frameset_get_size(imframes);
00587 
00588     /* Create bivector */
00589     ypositions = cpl_matrix_new(1, nframes);
00590     ypos = cpl_matrix_get_data(ypositions);
00591 
00592     /* Loop on the frames */
00593     for (i=0; i<nframes; i++) {
00594         double xpos;
00595         if ((objects = cpl_apertures_extract_sigma(cpl_imagelist_get(ilist, i),
00596                         2.0)) == NULL) {
00597             cpl_msg_error(cpl_func, "cannot detect any object");
00598             cpl_matrix_delete(ypositions);
00599             cpl_imagelist_delete(ilist);
00600             return NULL;
00601         }
00602         cpl_apertures_sort_by_flux(objects);
00603         xpos = cpl_apertures_get_centroid_x(objects, 1);
00604         ypos[i] = cpl_apertures_get_centroid_y(objects, 1);
00605         cpl_apertures_delete(objects);
00606         cpl_msg_info(cpl_func, "Image %d: Position (%g, %g)", i+1,xpos, ypos[i]);
00607     }
00608     cpl_imagelist_delete(ilist);
00609     return ypositions;
00610 }
00611  
00612 /*----------------------------------------------------------------------------*/
00619 /*----------------------------------------------------------------------------*/
00620 static cpl_imagelist * isaac_spc_startrace_load(const cpl_frameset * inframes)
00621 {
00622     cpl_imagelist       *   ilist;
00623     int                     nframes;
00624     cpl_image           *   tmp_im;
00625     int                     i;
00626 
00627     /* Test entries */
00628     if (inframes == NULL) return NULL;
00629 
00630     /* Initialise */
00631     nframes = cpl_frameset_get_size(inframes);
00632 
00633     /* Load the images */
00634     if ((ilist = cpl_imagelist_load_frameset(inframes, CPL_TYPE_FLOAT, 1, 
00635                     0)) == NULL) return NULL;
00636 
00637     /* In LW that's it */
00638     if (isaac_spc_startrace_config.arm == 2) return ilist; 
00639 
00640     /* In SW, the frames are subtracted to remove the background */
00641     tmp_im = cpl_image_duplicate(cpl_imagelist_get(ilist, 0));
00642     for (i=0; i<nframes-1; i++) {
00643         if (cpl_image_subtract(cpl_imagelist_get(ilist, i),
00644                 cpl_imagelist_get(ilist, i+1)) != CPL_ERROR_NONE) {
00645             cpl_msg_error(cpl_func, "cannot subtract images");
00646             cpl_imagelist_delete(ilist);
00647             cpl_image_delete(tmp_im);
00648             return NULL;
00649         }
00650     }
00651     /* Handle last frame */
00652     if (cpl_image_subtract(cpl_imagelist_get(ilist, nframes-1), 
00653             tmp_im) != CPL_ERROR_NONE) {
00654         cpl_msg_error(cpl_func, "cannot subtract images");
00655         cpl_imagelist_delete(ilist);
00656         cpl_image_delete(tmp_im);
00657         return NULL;
00658     }
00659     cpl_image_delete(tmp_im);
00660 
00661     /* Set negative pixels to 0  */
00662     cpl_imagelist_threshold(ilist, 0.0, DBL_MAX, 0.0, 0.0);
00663     
00664     return ilist;
00665 }
00666 
00667 /*----------------------------------------------------------------------------*/
00677 /*----------------------------------------------------------------------------*/
00678 static cpl_polynomial * isaac_spc_startrace_shape(
00679         cpl_image       *   in,
00680         double              ypos,
00681         char                resol,
00682         double          *   fit_quality)
00683 {
00684     int                     reject_left, reject_right;
00685     cpl_image           *   filtered;
00686     int                     low_side, up_side;
00687     cpl_mask            *   kernel;
00688     cpl_matrix          *   fit_x;
00689     cpl_vector          *   fit_y;
00690     double              *   pfit_x;
00691     double              *   pfit_y;
00692     cpl_polynomial      *   fitted;
00693     cpl_bivector        *   toplot;
00694     int                     i;
00695     int                     nsamples;
00696     const cpl_boolean       sampsym = CPL_TRUE; /* fit_x is symmetric */
00697 
00698     /* Check entries */
00699     if ((in == NULL) || (ypos < 0) || (fit_quality == NULL)) return NULL;
00700    
00701     /* Initialise */
00702     reject_left = isaac_spc_startrace_config.reject_left;
00703     reject_right = isaac_spc_startrace_config.reject_right;
00704     low_side = (int)(ypos - (isaac_spc_startrace_config.spec_width)/2);
00705     up_side = low_side + isaac_spc_startrace_config.spec_width;
00706 
00707     /* Test spectrum position */
00708     if ((low_side < 1) || (up_side > cpl_image_get_size_y(in))) {
00709         cpl_msg_error(cpl_func, "spectrum too close to the image border");
00710         return NULL;
00711     }
00712    
00713     /* Get rejection parameters */
00714     if (isaac_spc_startrace_config.arm == 1) {
00715         /* SW */
00716         if (reject_left < 0) {
00717             if (resol == 'M') reject_left = MR_LEFT_REJ;
00718             else if (resol == 'L') {
00719                 switch (isaac_spc_startrace_config.band) {
00720                     case ISAAC_BAND_Z:    reject_left = Z_LR_LEFT_REJ; break;
00721                     case ISAAC_BAND_SZ:   reject_left = SZ_LR_LEFT_REJ; break;
00722                     case ISAAC_BAND_JBLOCK:
00723                     case ISAAC_BAND_J:    reject_left = J_LR_LEFT_REJ; break;
00724                     case ISAAC_BAND_SH:   reject_left = SH_LR_LEFT_REJ; break;
00725                     case ISAAC_BAND_SK:   reject_left = SK_LR_LEFT_REJ; break;
00726                     default:
00727                         cpl_msg_warning(cpl_func, "unsupported filter");
00728                         reject_left = 0;
00729                         break;
00730                 }
00731             }
00732         }
00733         if (reject_right < 0) {
00734             if (resol == 'M') reject_right = MR_RIGHT_REJ;
00735             else if (resol == 'L') {
00736                 switch (isaac_spc_startrace_config.band) {
00737                     case ISAAC_BAND_Z:    reject_right = Z_LR_RIGHT_REJ; break;
00738                     case ISAAC_BAND_SZ:   reject_right = SZ_LR_RIGHT_REJ;break;
00739                     case ISAAC_BAND_JBLOCK:
00740                     case ISAAC_BAND_J:    reject_right = J_LR_RIGHT_REJ; break;
00741                     case ISAAC_BAND_SH:   reject_right = SH_LR_RIGHT_REJ;break;
00742                     case ISAAC_BAND_SK:   reject_right = SK_LR_RIGHT_REJ;break;
00743                     default:
00744                         cpl_msg_warning(cpl_func, "unsupported filter");
00745                         reject_right = 0;
00746                         break;
00747                 }
00748             }
00749         }
00750     } else if (isaac_spc_startrace_config.arm == 2) {
00751         /* LW */
00752         if (reject_left < 0) reject_left = 150;
00753         if (reject_right < 0) reject_right = 150;
00754     
00755     } else {
00756         cpl_msg_error(cpl_func, "Unrecognized mode - abort");
00757         return NULL;
00758     }
00759 
00760     /* Filter the image */
00761     kernel = cpl_mask_new(3, 3);
00762     cpl_mask_not(kernel);
00763     filtered = cpl_image_new(cpl_image_get_size_x(in), cpl_image_get_size_y(in),
00764                              cpl_image_get_type(in));
00765     if (cpl_image_filter_mask(filtered, in, kernel, CPL_FILTER_MEDIAN,
00766                               CPL_BORDER_FILTER)) {
00767         cpl_msg_error(cpl_func, "cannot filter the image");
00768         cpl_mask_delete(kernel);
00769         return NULL;
00770     }
00771     cpl_mask_delete(kernel);
00772 
00773     /* Fill the vector to fit */
00774     nsamples = cpl_image_get_size_x(in) - reject_right - reject_left;
00775     fit_x = cpl_matrix_new(1, nsamples);
00776     pfit_x = cpl_matrix_get_data(fit_x);
00777     fit_y = cpl_vector_new(nsamples);
00778     pfit_y = cpl_vector_get_data(fit_y);
00779     for (i=0; i < nsamples; i++) {
00780         pfit_x[i] = (double)(i+1+reject_left);
00781         pfit_y[i] = cpl_image_get_centroid_y_window(filtered, i+1+reject_left, 
00782                 low_side, i+1+reject_left, up_side);
00783     }
00784     cpl_image_delete(filtered);
00785     
00786     /* Apply the fit */
00787     fitted = cpl_polynomial_new(1);
00788     if (cpl_polynomial_fit(fitted, fit_x, &sampsym, fit_y, NULL, CPL_FALSE,
00789                            NULL, &(isaac_spc_startrace_config.degree))) {
00790         cpl_msg_error(cpl_func, "cannot fit the shape");
00791         cpl_polynomial_delete(fitted);
00792         cpl_matrix_delete(fit_x);
00793         cpl_vector_delete(fit_y);
00794         return NULL;
00795     }
00796 
00797     /* Display if requested */
00798     if (isaac_spc_startrace_config.display) {
00799         cpl_vector * vfit_x
00800             = cpl_vector_wrap(nsamples, pfit_x);
00801         toplot = cpl_bivector_wrap_vectors(vfit_x, fit_y);
00802         cpl_plot_bivector(NULL, NULL, NULL, toplot);
00803         cpl_bivector_unwrap_vectors(toplot);
00804         (void)cpl_vector_unwrap(vfit_x);
00805     }
00806 
00807     cpl_vector_fill_polynomial_fit_residual(fit_y, fit_y, NULL, fitted,
00808                                             fit_x, NULL);
00809     *fit_quality = cpl_vector_product(fit_y, fit_y) / nsamples;
00810 
00811     /* Display if requested */
00812     if (isaac_spc_startrace_config.display) {
00813         cpl_vector * vfit_x
00814             = cpl_vector_wrap(nsamples, pfit_x);
00815         toplot = cpl_bivector_wrap_vectors(vfit_x, fit_y);
00816         for (i=0; i<nsamples; i++) {
00817             pfit_y[i] = cpl_polynomial_eval_1d(fitted, pfit_x[i], NULL);
00818         }
00819         cpl_plot_bivector(NULL, NULL, NULL, toplot);
00820         cpl_bivector_unwrap_vectors(toplot);
00821         (void)cpl_vector_unwrap(vfit_x);
00822     }
00823 
00824     /* Free and return */
00825     cpl_matrix_delete(fit_x);
00826     cpl_vector_delete(fit_y);
00827     return fitted;
00828 }
00829 
00830 /*----------------------------------------------------------------------------*/
00840 /*----------------------------------------------------------------------------*/
00841 static cpl_polynomial * isaac_spc_startrace_distor(
00842         cpl_polynomial  **  shapes,
00843         cpl_vector      *   spec_pos,
00844         int                 nshapes,
00845         int                 nx)
00846 {
00847     cpl_polynomial      *   distor;
00848     cpl_matrix          *   xy_vec;
00849     double              *   x_data;
00850     double              *   y_data;
00851     cpl_vector          *   z_vec;
00852     double              *   z_data;
00853     int                     nb_xpoints, npoints;
00854     int                     pos;
00855     int                     i, j;
00856     const int               maxdeg = 2;
00857 
00858     /* Initialise */
00859     nb_xpoints = 20;
00860     npoints = nb_xpoints * nshapes;
00861 
00862     /* Prepare the surface */
00863     xy_vec = cpl_matrix_new(2, npoints);
00864     x_data = cpl_matrix_get_data(xy_vec);
00865     y_data = x_data + npoints;
00866     z_vec = cpl_vector_new(npoints);
00867     z_data = cpl_vector_get_data(z_vec);
00868     for (j=0; j<nshapes; j++) {
00869         for (i=0; i<nb_xpoints; i++) {
00870             pos = i + j*nb_xpoints;
00871             x_data[pos] = nx * (i+1) / nb_xpoints;
00872             y_data[pos] = cpl_vector_get(spec_pos, j);
00873             z_data[pos] = cpl_polynomial_eval_1d(shapes[j], x_data[pos], NULL);
00874         }
00875     }
00876     
00877     /* Apply the fit */
00878     distor = cpl_polynomial_new(2);
00879     if (cpl_polynomial_fit(distor, xy_vec, NULL, z_vec, NULL, CPL_FALSE, NULL,
00880                            &maxdeg)) {
00881         cpl_msg_error(cpl_func, "cannot fit the distortion");
00882         cpl_matrix_delete(xy_vec);
00883         cpl_vector_delete(z_vec);
00884         cpl_polynomial_delete(distor);
00885         return NULL;
00886     }
00887     cpl_matrix_delete(xy_vec);
00888     cpl_vector_delete(z_vec);
00889 
00890     return distor;
00891 }
00892 
00893 /*----------------------------------------------------------------------------*/
00907 /*----------------------------------------------------------------------------*/
00908 static
00909 cpl_error_code isaac_spc_startrace_save(cpl_frameset            * set_tot,
00910                                         const cpl_table         * tab,
00911                                         const cpl_matrix        * star_pos,
00912                                         const cpl_vector        * spec_pos,
00913                                         cpl_polynomial         ** shapes,
00914                                         const cpl_frameset      * set,
00915                                         char                      resol,
00916                                         const cpl_parameterlist * parlist)
00917 {
00918     cpl_propertylist    *   plist;
00919     cpl_propertylist    *   qclist;
00920     cpl_propertylist    *   paflist;
00921     const cpl_frame           *   ref_frame;
00922     char                    colname[128];
00923     cpl_table           *   shapes_table;
00924     cpl_table           *   pos_table;
00925     const char          *   procatt;
00926     const char          *   procat;
00927     char                *   filename;
00928     int                     i, j;
00929 
00930     /* Get the QC params in qclist */
00931     qclist = cpl_propertylist_new();
00932 
00933     /* Add QC parameters */
00934     cpl_propertylist_append_double(qclist, "ESO QC CORR_IS1",
00935             isaac_spc_startrace_config.corr_is1);
00936     cpl_propertylist_append_double(qclist, "ESO QC CORR_IS2",
00937             isaac_spc_startrace_config.corr_is2);
00938     cpl_propertylist_append_double(qclist, "ESO QC CORR_IS3",
00939             isaac_spc_startrace_config.corr_is3);
00940     cpl_propertylist_append_double(qclist, "ESO QC FITMSE",
00941             isaac_spc_startrace_config.shapes_fit_q);
00942     cpl_propertylist_append_double(qclist, "ESO QC DIST1",
00943             isaac_spc_startrace_config.dist1);
00944     cpl_propertylist_append_double(qclist, "ESO QC DISTX",
00945             isaac_spc_startrace_config.distx);
00946     cpl_propertylist_append_double(qclist, "ESO QC DISTY",
00947             isaac_spc_startrace_config.disty);
00948     cpl_propertylist_append_double(qclist, "ESO QC DISTXY",
00949             isaac_spc_startrace_config.distxy);
00950     cpl_propertylist_append_double(qclist, "ESO QC DISTXX",
00951             isaac_spc_startrace_config.distxx);
00952     cpl_propertylist_append_double(qclist, "ESO QC DISTYY",
00953             isaac_spc_startrace_config.distyy);
00954     
00955     /* Write the distortion table  */
00956     procatt = isaac_spc_startrace_config.arm == 1
00957         ? ISAAC_SPC_STARTRACE_SW_RES : ISAAC_SPC_STARTRACE_LW_RES;
00958     filename = cpl_sprintf("isaac_spc_startrace_2dpoly_%cR.fits", resol);
00959     irplib_dfs_save_table(set_tot,
00960             parlist,
00961             set,
00962             tab,
00963             NULL,
00964             "isaac_spc_startrace",
00965             procatt,
00966             qclist,
00967             NULL,
00968             PACKAGE "/" PACKAGE_VERSION,
00969             filename);
00970     cpl_free(filename);
00971 
00972     /* Save the positions table */
00973     pos_table = cpl_table_new(cpl_matrix_get_ncol(star_pos));
00974 
00975     /* star_pos is _not_ modified */
00976     cpl_table_wrap_double(pos_table, cpl_matrix_get_data((cpl_matrix*)star_pos),
00977                           "Star_positions");
00978     /* spec_pos is _not_ modified */
00979     cpl_table_wrap_double(pos_table, cpl_vector_get_data((cpl_vector*)spec_pos),
00980                           "Spec_positions");
00981 
00982     procat = isaac_spc_startrace_config.arm == 1
00983         ? ISAAC_SPC_STARTRACE_SW_POS : ISAAC_SPC_STARTRACE_LW_POS;
00984     filename = cpl_sprintf("isaac_spc_startrace_positions_%cR.fits", resol);
00985     irplib_dfs_save_table(set_tot,
00986             parlist,
00987             set,
00988             tab,
00989             NULL,
00990             "isaac_spc_startrace",
00991             procat,
00992             qclist,
00993             NULL,
00994             PACKAGE "/" PACKAGE_VERSION,
00995             filename);
00996     cpl_free(filename);
00997 
00998     (void)cpl_table_unwrap(pos_table, "Star_positions");
00999     (void)cpl_table_unwrap(pos_table, "Spec_positions");
01000     cpl_table_delete(pos_table);
01001 
01002     /* Save the shapes table */
01003     shapes_table = cpl_table_new(isaac_spc_startrace_config.degree + 1); 
01004     for (i=0; i<cpl_vector_get_size(spec_pos); i++) {
01005         sprintf(colname, "Spec_%d", i+1);
01006         cpl_table_new_column(shapes_table, colname, CPL_TYPE_DOUBLE);
01007     }
01008     for (i=0; i<cpl_vector_get_size(spec_pos); i++) {
01009         sprintf(colname, "Spec_%d", i+1);
01010         for (j=0; j<isaac_spc_startrace_config.degree + 1; j++) {
01011             cpl_table_set_double(shapes_table, colname, j, 
01012                     cpl_polynomial_get_coeff(shapes[i], &j));
01013         }
01014     }
01015     procat = isaac_spc_startrace_config.arm == 1 ?
01016         ISAAC_SPC_STARTRACE_SW_SHAPE : ISAAC_SPC_STARTRACE_LW_SHAPE;
01017     filename = cpl_sprintf("isaac_spc_startrace_shapes_%cR.fits", resol);
01018     irplib_dfs_save_table(set_tot,
01019             parlist,
01020             set,
01021             tab,
01022             NULL,
01023             "isaac_spc_startrace",
01024             procat,
01025             qclist,
01026             NULL,
01027             PACKAGE "/" PACKAGE_VERSION,
01028             filename);
01029     cpl_free(filename);
01030     cpl_table_delete(shapes_table);
01031 
01032     /* Get the reference frame */
01033     ref_frame = irplib_frameset_get_first_from_group(set, CPL_FRAME_GROUP_RAW);
01034 
01035     /* Get FITS header from reference file */
01036     if ((plist=cpl_propertylist_load(cpl_frame_get_filename(ref_frame),
01037                     0)) == NULL) {
01038         cpl_msg_error(cpl_func, "getting header from reference frame");
01039         cpl_propertylist_delete(qclist);
01040         return -1;
01041     }
01042    
01043     /* Get the keywords for the paf file */
01044     paflist = cpl_propertylist_new();
01045     cpl_propertylist_copy_property_regexp(paflist, plist, 
01046         "^(ARCFILE|MJD-OBS|INSTRUME|ESO TPL ID|ESO TPL NEXP|ESO DPR CATG|"
01047         "ESO DPR TECH|ESO DPR TYPE|DATE-OBS|ESO INS GRAT NAME|"
01048         "ESO OCS SELECT-ARM)$", 0);
01049     cpl_propertylist_delete(plist);
01050 
01051     /* Copy the QC in paflist */
01052     cpl_propertylist_copy_property_regexp(paflist, qclist, "", 0);
01053     cpl_propertylist_delete(qclist);
01054 
01055     /* PRO.CATG */
01056     cpl_propertylist_update_string(paflist, CPL_DFS_PRO_CATG, procatt);
01057 
01058     /* Save the PAF file */
01059     filename = cpl_sprintf("isaac_spc_startrace_%cR.paf", resol);
01060     cpl_dfs_save_paf("ISAAC",
01061             "isaac_spc_startrace",
01062             paflist,
01063             filename);
01064     cpl_free(filename);
01065     cpl_propertylist_delete(paflist);
01066     return  0;
01067 }
01068 

Generated on Wed Mar 9 15:43:10 2011 for ISAAC Pipeline Reference Manual by  doxygen 1.5.8