naco_spc.c

00001 /* $Id: naco_spc.c,v 1.41 2008/09/12 09:17:51 llundin Exp $
00002  *
00003  * This file is part of the NACO 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., 51 Franklin St, Fifth Floor, Boston, MA  02111-1307  USA
00019  */
00020 
00021 /*
00022  * $Author: llundin $
00023  * $Date: 2008/09/12 09:17:51 $
00024  * $Revision: 1.41 $
00025  * $Name: naco-4_1_2 $
00026  */
00027 
00028 #ifdef HAVE_CONFIG_H
00029 #include <config.h>
00030 #endif
00031 
00032 /*-----------------------------------------------------------------------------
00033                                    Includes
00034  -----------------------------------------------------------------------------*/
00035 
00036 #include <string.h>
00037 #include <math.h>
00038 #include <cpl.h>
00039 
00040 #ifdef HAVE_GSL
00041 #include <gsl/gsl_multimin.h>
00042 #endif
00043 
00044 #include "naco_spc.h"
00045 #include "naco_pfits.h"
00046 
00047 #include "irplib_plot.h"
00048 
00049 
00050 /*-----------------------------------------------------------------------------
00051                                Private types
00052  -----------------------------------------------------------------------------*/
00053 typedef struct {
00054     double x;
00055     int    index;
00056 } vector_index;
00057 
00058 
00059 /*-----------------------------------------------------------------------------
00060                                    Private functions
00061  -----------------------------------------------------------------------------*/
00062 
00063 static int naco_vector_get_maxpos_window(const cpl_vector *, int, int);
00064 
00065 #if 0
00066 static int vector_index_compare(const void *, const void *);
00067 #endif
00068 
00069 static cpl_error_code naco_framelist_get_state(const irplib_framelist *,
00070                                                     int, cpl_boolean,
00071                                                     cpl_boolean *,
00072                                                     const cpl_propertylist *);
00073 
00074 /*----------------------------------------------------------------------------*/
00078 /*----------------------------------------------------------------------------*/
00079 
00082 /*----------------------------------------------------------------------------*/
00098 /*----------------------------------------------------------------------------*/
00099 cpl_error_code naco_vector_correlate_imagelist_1d(cpl_vector * offset,
00100                                                   const cpl_vector * goffset,
00101                                                   cpl_boolean do_wave,
00102                                                   const cpl_imagelist * self)
00103 {
00104 
00105     cpl_image  * d2d      = NULL;
00106     cpl_image  * dspat1d  = NULL;
00107     cpl_vector * vspat1dp = NULL;
00108     cpl_vector * vspat1di = NULL;
00109     cpl_vector * vxc      = NULL;
00110     const int    nsize    = cpl_imagelist_get_size(self);
00111     const int    maxerr   = 20;
00112     int          gleni, glenprev = 0; /* Avoid (false) uninit warning */
00113 
00114     /* Wavelenth/Spatial resolution */
00115     const int    nz = (do_wave ? cpl_image_get_size_y : cpl_image_get_size_x)
00116         (cpl_imagelist_get_const(self, 0));
00117     const char   dirch = do_wave ? 'Y' : 'X';
00118     const int    direc = do_wave ? 1 : 0;
00119     int          ii, i, iprev = 0; /* Avoid (false) uninit warning */
00120     double       xcmin    = 1.0;
00121 
00122 
00123     bug_if(self     == NULL);
00124 
00125     bug_if(offset  == NULL);
00126     bug_if(goffset == NULL);
00127     bug_if(cpl_vector_get_size(offset)  != nsize);
00128     bug_if(cpl_vector_get_size(goffset) != nsize);
00129 
00130     /* Process frames in order of offset */
00131     for (ii = 0; ii < nsize; ii++) {
00132         i = ii;
00133 
00134         cpl_msg_info(cpl_func, "%c-offset(%d:%d): %g", dirch, ii, i,
00135                      cpl_vector_get(goffset, i));
00136 
00137     }
00138 
00139     vxc = cpl_vector_new(maxerr);
00140 
00141     /* Process frames in order of offset */
00142     for (ii = 0; ii < nsize; ii++) {
00143 
00144         int maxoff, halfoff;
00145         int ixc, ixc0;
00146         int irealfirst, ireallast;
00147         int ioff;
00148         double xci;
00149         double doff, dnewoff;
00150 
00151         i = ii;
00152 
00153         gleni = (int)round(cpl_vector_get(goffset, i));
00154 
00155         /* Need double for the cpl_vector */
00156         d2d = cpl_image_cast(cpl_imagelist_get_const(self, i), CPL_TYPE_DOUBLE);
00157 
00158         /* Sum over the spatial dimension */
00159         dspat1d = cpl_image_collapse_create(d2d, direc);
00160         /* A skip before vspat1di has wrapped will leak the pixel buffer */
00161         cpl_image_delete(d2d);
00162         d2d = NULL;
00163 
00164         cpl_vector_delete(vspat1di);
00165         vspat1di = cpl_vector_wrap(nz, cpl_image_get_data_double(dspat1d));
00166         (void)cpl_image_unwrap(dspat1d);
00167         dspat1d = NULL;
00168         bug_if(0);
00169 
00170 #if 0
00171         irplib_vector_plot("set grid;", "t '1D-Profile i' w linespoints", "",
00172                           vspat1di);
00173 #endif
00174         if (ii == 0) {
00175             vspat1dp = vspat1di;
00176             vspat1di = NULL;
00177             glenprev = gleni;
00178             iprev = i;
00179             continue;
00180         }
00181 
00182         halfoff = maxerr + abs(gleni - glenprev);
00183         if (halfoff > nz-1) halfoff = nz - 1;
00184         maxoff = 2 * halfoff + 1;
00185 
00186         bug_if(cpl_vector_set_size(vxc, maxoff));
00187 
00188         ixc0 = cpl_vector_correlate(vxc, vspat1di, vspat1dp);
00189         bug_if(0);
00190 
00191         /* Limit the search range to 1+2*maxerr to reduce risk of false max */
00192         irealfirst = halfoff - (glenprev - gleni) - maxerr;
00193         ireallast  = halfoff - (glenprev - gleni) + maxerr;
00194 
00195         ixc = naco_vector_get_maxpos_window(vxc, irealfirst, ireallast);
00196         bug_if(0);
00197 
00198         if (ixc != ixc0) {
00199             cpl_msg_warning(cpl_func, "%c-False maximum(%d:%d): %d <+. %d. "
00200                             "0 <= %d => %d < %d", dirch, ii, i, ixc0, ixc,
00201                             irealfirst, ireallast, maxoff);
00202         }
00203 
00204         ioff = ixc - halfoff;
00205         doff = cpl_vector_get(goffset, i) - cpl_vector_get(goffset, iprev);
00206 
00207         xci = cpl_vector_get(vxc, ixc);
00208 
00209         if (xci < xcmin) xcmin = xci;
00210 
00211         if (ioff != (int)round(doff)) {
00212             cpl_msg_warning(cpl_func, "%c-XC(%d)=%g changes offset: %g - %g = "
00213                             "%g => %d = %d - %d", dirch, i, xci,
00214                             cpl_vector_get(goffset, i),
00215                             cpl_vector_get(goffset, iprev), doff, ioff,
00216                             gleni, glenprev);
00217             dnewoff = (double)-ioff;
00218         } else {
00219             cpl_msg_info(cpl_func, "%c-XC(%d)=%g confirms offset: %g - %g = %g "
00220                          "<=> %d = %d - %d", dirch, i, xci,
00221                          cpl_vector_get(goffset, i),
00222                          cpl_vector_get(goffset, iprev), doff, ioff,
00223                          gleni, glenprev);
00224             dnewoff = -doff;
00225         }
00226         bug_if(0);
00227         bug_if(cpl_vector_set(offset, i, dnewoff));
00228 
00229 #if 0
00230         irplib_vector_plot("set grid;", "t 'Cross-correlation' w linespoints",
00231                            "", vxc);
00232 
00233 #endif
00234     }
00235 
00236     cpl_msg_info(cpl_func, "Minimum 1D-spatial XC for %d sets: %g",
00237                  nsize, xcmin);
00238 
00239     end_skip;
00240 
00241     cpl_image_delete(d2d);
00242     (void)cpl_image_unwrap(dspat1d);
00243     cpl_vector_delete(vspat1dp);
00244     cpl_vector_delete(vspat1di);
00245     cpl_vector_delete(vxc);
00246 
00247     return cpl_error_get_code();
00248 }
00249 
00250 /*----------------------------------------------------------------------------*/
00258 /*----------------------------------------------------------------------------*/
00259 cpl_error_code naco_imagelist_add_split(cpl_imagelist * self)
00260 {
00261 
00262     cpl_image     * copy  = NULL;
00263     int             n     = cpl_imagelist_get_size(self);
00264     int             i;
00265 
00266     bug_if(self == NULL);
00267 
00268     bug_if(n&1);
00269 
00270 
00271     for (i=0; i < n; i += 2) {
00272         cpl_image * first  = cpl_imagelist_get(self, i);
00273         cpl_image * second = cpl_imagelist_get(self, i+1);
00274 
00275         bug_if(cpl_image_subtract(first, second));
00276 
00277         copy = cpl_image_multiply_scalar_create(first, -1.0);
00278 
00279         bug_if(cpl_imagelist_set(self, copy, i+1));
00280         copy = NULL;
00281 
00282     }
00283 
00284     end_skip;
00285 
00286     cpl_image_delete(copy);
00287 
00288     return cpl_error_get_code();
00289 
00290 }
00291 
00292 
00293 
00294 /*----------------------------------------------------------------------------*/
00302 /*----------------------------------------------------------------------------*/
00303 cpl_error_code naco_imagelist_append_invert(cpl_imagelist * self)
00304 {
00305 
00306     cpl_image     * BA = NULL;
00307     const int       n      = cpl_imagelist_get_size(self);
00308     int             i;
00309 
00310 
00311     bug_if(self == NULL);
00312 
00313     for (i=0; i < n; i++) {
00314         const cpl_image * AB  = cpl_imagelist_get(self, i);
00315 
00316         BA = cpl_image_multiply_scalar_create(AB, -1.0);
00317 
00318         bug_if(cpl_imagelist_set(self, BA, n+i));
00319         BA = NULL;
00320 
00321     }
00322 
00323     end_skip;
00324 
00325     cpl_image_delete(BA);
00326 
00327     return cpl_error_get_code();
00328 
00329 }
00330 
00331 
00332 /*----------------------------------------------------------------------------*/
00342 /*----------------------------------------------------------------------------*/
00343 cpl_error_code naco_imagelist_split(cpl_imagelist * self)
00344 {
00345 
00346     cpl_imagelist * copy   = cpl_imagelist_new();
00347     cpl_image     * image  = NULL;
00348     cpl_image     * im_neg = NULL;
00349     int             j      = cpl_imagelist_get_size(self);
00350     int             i      = 0;
00351 
00352 
00353     skip_if(self == NULL);
00354 
00355     /* Move all images to the copy - and revert their order */
00356     j--;
00357     for (; j >= 0; j--, i++) {
00358         bug_if(cpl_imagelist_set(copy, cpl_imagelist_unset(self, j), i));
00359     }
00360 
00361     j++;
00362     i--;
00363 
00364     bug_if(j != 0);
00365 
00366     /* Move all images back to self, revert their order again while splitting */
00367     for (; i >= 0; i--, j += 2) {
00368         image = cpl_imagelist_unset(copy, i);
00369 
00370         /* The negative flux */
00371         im_neg = cpl_image_duplicate(image);
00372         bug_if(cpl_image_threshold(im_neg, -FLT_MAX, 0.0, 0.0, 0.0));
00373         bug_if(cpl_image_multiply_scalar(im_neg, -1.0));
00374 
00375 
00376         /* The positive flux */
00377         bug_if(cpl_image_threshold(image, 0.0, FLT_MAX, 0.0, 0.0));
00378 
00379         bug_if(cpl_imagelist_set(self, image, j));
00380         image = NULL;
00381 
00382         bug_if(cpl_imagelist_set(self, im_neg, j+1));
00383         im_neg = NULL;
00384 
00385     }
00386 
00387     end_skip;
00388 
00389     cpl_image_delete(image);
00390     cpl_image_delete(im_neg);
00391     cpl_imagelist_delete(copy);
00392 
00393     return CPL_ERROR_NONE;
00394 
00395 }
00396 
00397 /*----------------------------------------------------------------------------*/
00409 /*----------------------------------------------------------------------------*/
00410 char * naco_spc_make_tag(const cpl_frame* self, const cpl_propertylist * plist,
00411              int dummy)
00412 {
00413 
00414     char       * tag = NULL;
00415     double       wlen, dit;
00416     const char * specmode; 
00417     const char * slitname; 
00418 
00419 
00420     bug_if (0);
00421 
00422     bug_if(self  == NULL);
00423     bug_if(plist == NULL);
00424     bug_if(dummy < 0); /* Avoid warning of unused variable */
00425 
00426     specmode = irplib_pfits_get_string(plist, NACO_PFITS_STRING_SPECMODE);
00427     skip_if(cpl_error_get_code());
00428 
00429     slitname = irplib_pfits_get_string(plist, NACO_PFITS_STRING_SLITNAME);
00430     skip_if(cpl_error_get_code());
00431 
00432     dit  = irplib_pfits_get_double(plist, NACO_PFITS_DOUBLE_DIT);
00433     skip_if(cpl_error_get_code());
00434 
00435     wlen = irplib_pfits_get_double(plist, NACO_PFITS_DOUBLE_CWLEN);
00436     skip_if(cpl_error_get_code());
00437 
00438     tag = cpl_sprintf("%s:%s:%.5f:%.5f", specmode, slitname, wlen, dit);
00439     bug_if(tag == NULL);
00440 
00441     end_skip;
00442 
00443     if (cpl_error_get_code()) {
00444         cpl_free(tag);
00445         tag = NULL;
00446     }
00447 
00448     return tag;
00449 
00450 }
00451 
00452 
00453 /*----------------------------------------------------------------------------*/
00484 /*----------------------------------------------------------------------------*/
00485 cpl_error_code naco_imagelist_load_diff(cpl_imagelist * self,
00486                                         const irplib_framelist * onofflist,
00487                                         const cpl_propertylist * onoffkeys)
00488 {
00489     cpl_image     * img_off = NULL;
00490     cpl_image     * diff = NULL;
00491     int             nfiles, ndiff;
00492     int             ion, ioff;
00493 
00494     skip_if (0);
00495     skip_if (self      == NULL);
00496     skip_if (onofflist == NULL);
00497 
00498     skip_if(cpl_imagelist_get_size(self) != 0);
00499 
00500     skip_if (irplib_framelist_contains(onofflist, "NAXIS1", CPL_TYPE_INT,
00501                                        CPL_TRUE, 0.0));
00502     skip_if (irplib_framelist_contains(onofflist, "NAXIS2", CPL_TYPE_INT,
00503                                        CPL_TRUE, 0.0));
00504 
00505     skip_if (irplib_framelist_contains(onofflist, NACO_PFITS_DOUBLE_DIT,
00506                                        CPL_TYPE_DOUBLE, CPL_TRUE, 1e-5));
00507    
00508     nfiles = irplib_framelist_get_size(onofflist);
00509 
00510     for (ioff = 0, ion = 0, ndiff = 0; ioff < nfiles && ion < nfiles;
00511          ioff++, ion++) {
00512         /* Each completed iteration produces one on-off image */
00513         cpl_boolean need_on = CPL_TRUE;
00514 
00515         const cpl_frame * frame;
00516         const char * name;
00517 
00518 
00519         /* Find next off-frame - and perhaps also the next on-frame */
00520         for (; ioff < nfiles; ioff++) {
00521             cpl_boolean is_off;
00522 
00523             skip_if(naco_framelist_get_state(onofflist, ioff, CPL_FALSE,
00524                                                   &is_off, onoffkeys));
00525 
00526             if (is_off) {
00527                 break;
00528             } else if (need_on && ioff >= ion) {
00529                 ion = ioff;
00530                 need_on = CPL_FALSE;
00531             }
00532         }
00533 
00534         bug_if(0);
00535 
00536         if (ioff == nfiles) break;
00537 
00538         if (need_on) {
00539             /* Find next on-frame */
00540             if (ion == ioff) ion++; /* No need to check an off-frame */
00541             for (; ion < nfiles; ion++) {
00542 
00543                 cpl_boolean is_on;
00544 
00545                 skip_if(naco_framelist_get_state(onofflist, ion, CPL_TRUE,
00546                                                       &is_on, onoffkeys));
00547 
00548                 if (is_on) break;
00549 
00550             }
00551 
00552             bug_if(0);
00553 
00554             if (ion == nfiles) break;
00555         }
00556 
00557         frame = irplib_framelist_get_const(onofflist, ion);
00558         name = cpl_frame_get_filename(frame);
00559 
00560         bug_if(0);
00561 
00562         diff = cpl_image_load(name, CPL_TYPE_FLOAT, 0, 0);
00563         error_if(diff == NULL, cpl_error_get_code(),
00564                  "Could not load on-image from %s", name);
00565 
00566         frame = irplib_framelist_get_const(onofflist, ioff);
00567         name = cpl_frame_get_filename(frame);
00568 
00569         bug_if(0);
00570 
00571         img_off = cpl_image_load(name, CPL_TYPE_FLOAT, 0, 0);
00572         error_if(img_off == NULL, cpl_error_get_code(),
00573                  "Could not load off-image from %s", name);
00574 
00575         error_if(cpl_image_subtract(diff, img_off), cpl_error_get_code(),
00576                  "Could not subtract frame %d from %d", ioff, ion);
00577 
00578         cpl_image_delete(img_off);
00579         img_off = NULL;
00580 
00581         bug_if(cpl_imagelist_set(self, diff, ndiff));
00582         diff = NULL;
00583 
00584         ndiff++;
00585     }
00586 
00587     bug_if(cpl_imagelist_get_size(self) != ndiff);
00588 
00589     error_if(ndiff == 0 && ion == nfiles, CPL_ERROR_DATA_NOT_FOUND,
00590              "The %d frame(s) contain(s) no on-frames", nfiles);
00591     error_if(ndiff == 0 && ioff == nfiles, CPL_ERROR_DATA_NOT_FOUND,
00592              "The %d frame(s) contain(s) no off-frames", nfiles);
00593 
00594     if (2 * ndiff < nfiles) {
00595         cpl_msg_warning(cpl_func, "The %d frames contains only %d pairs of "
00596                         "on/off-frames, ignoring the rest", nfiles, ndiff);
00597     }
00598 
00599     bug_if(cpl_imagelist_get_size(self) < 1);
00600 
00601     end_skip;
00602 
00603     cpl_image_delete(img_off);
00604     cpl_image_delete(diff);
00605 
00606     return cpl_error_get_code();
00607 }
00608 
00609 
00614 /*----------------------------------------------------------------------------*/
00628 /*----------------------------------------------------------------------------*/
00629 static
00630 cpl_error_code naco_framelist_get_state(const irplib_framelist * self,
00631                                         int iframe,
00632                                         cpl_boolean is_on,
00633                                         cpl_boolean * pis_ok,
00634                                         const cpl_propertylist * onoffkeys)
00635 {
00636 
00637     cpl_boolean state = CPL_FALSE;
00638     const cpl_propertylist * plist
00639         = irplib_framelist_get_propertylist_const(self, iframe);
00640     const int nonoffkeys = cpl_propertylist_get_size(onoffkeys);
00641     int i;
00642     cpl_boolean onoffkeys_has_one_on = CPL_FALSE;
00643 
00644     bug_if (0);
00645     bug_if (self     == NULL);
00646     bug_if (iframe   <  0);
00647     bug_if (iframe   >= irplib_framelist_get_size(self));
00648     bug_if (pis_ok   == NULL);
00649     bug_if (onoffkeys == NULL);
00650     bug_if (plist    == NULL);
00651 
00652     for (i=0; i < nonoffkeys; i++) {
00653         const cpl_property * prop = cpl_propertylist_get_const(onoffkeys, i);
00654         const char         * name = cpl_property_get_name(prop);
00655         const int            ireq = cpl_property_get_int(prop);
00656         const cpl_type  statetype = cpl_propertylist_get_type(plist, name);
00657         cpl_boolean state_is_on;
00658 
00659         error_if(0, cpl_error_get_code(), "On/off property number %d, %s",
00660                  1+i, name ? name : "<NULL>");
00661 
00662         switch (statetype) {
00663         case CPL_TYPE_CHAR:
00664             state_is_on = cpl_propertylist_get_char(plist, name) > 0
00665                 ? CPL_TRUE : CPL_FALSE;
00666             break;
00667         case CPL_TYPE_BOOL:
00668             state_is_on = cpl_propertylist_get_bool(plist, name);
00669             break;
00670         case CPL_TYPE_INT:
00671             state_is_on = cpl_propertylist_get_int(plist, name) > 0
00672                 ? CPL_TRUE : CPL_FALSE;
00673             break;
00674         case CPL_TYPE_LONG:
00675             state_is_on = cpl_propertylist_get_long(plist, name) > 0
00676                 ? CPL_TRUE : CPL_FALSE;
00677             break;
00678         case CPL_TYPE_FLOAT:
00679             state_is_on = cpl_propertylist_get_float(plist, name) > 0.0
00680                 ? CPL_TRUE : CPL_FALSE;
00681             break;
00682         case CPL_TYPE_DOUBLE:
00683             state_is_on = cpl_propertylist_get_double(plist, name) > 0.0
00684                 ? CPL_TRUE : CPL_FALSE;
00685             break;
00686         default:
00687             cpl_ensure_code(0, CPL_ERROR_UNSUPPORTED_MODE);
00688         }
00689 
00690         if (is_on) {
00691             if (state_is_on) {
00692                 if (ireq == 0) break; /* This state is on, but shouldn't be */
00693                 onoffkeys_has_one_on = CPL_TRUE; /* A state is corrrectly on */
00694             } else if (ireq >  0) {
00695                 break; /* This state is off, but shouldn't be */
00696             }
00697         } else if (state_is_on) {
00698             break; /* This state is on, but all states should be off */
00699         }
00700     }
00701 
00702     if (i == nonoffkeys) {
00703         if (is_on) {
00704             /* All states were on or off, as specified by onoffkeys */
00705             state = onoffkeys_has_one_on; /* At least one state must be on */
00706         } else {
00707             /* All states were off, as they should be */
00708             state = CPL_TRUE;
00709         }
00710     }
00711 
00712     *pis_ok = state;
00713 
00714     end_skip;
00715 
00716     return cpl_error_get_code();
00717 }
00718 
00719 #if 0
00720 /*----------------------------------------------------------------------------*/
00730 /*----------------------------------------------------------------------------*/
00731 static int vector_index_compare(const void * a, const void * b)
00732 {
00733     return
00734         ( (const vector_index*)a)->x < ((const vector_index*)b)->x ? -1 :
00735         (((const vector_index*)a)->x > ((const vector_index*)b)->x ?  1 : 0);  
00736 }
00737 
00738 #endif
00739 /*----------------------------------------------------------------------------*/
00748 /*----------------------------------------------------------------------------*/
00749 static int naco_vector_get_maxpos_window(const cpl_vector * v, int i0, int i1)
00750 {
00751     int    i    = i0;
00752     int    imax = i0;
00753     double vmax = cpl_vector_get(v, imax);
00754 
00755     cpl_ensure(v != NULL, CPL_ERROR_NULL_INPUT,    -1);
00756     cpl_ensure(0  <= i0,  CPL_ERROR_ILLEGAL_INPUT, -2);
00757     cpl_ensure(i0 <= i1,  CPL_ERROR_ILLEGAL_INPUT, -3);
00758     cpl_ensure(i1 < cpl_vector_get_size(v), CPL_ERROR_ILLEGAL_INPUT, -4);
00759 
00760     for (i = i0; i <= i1; i++) if (cpl_vector_get(v, i) > vmax) {
00761         imax = i;
00762         vmax = cpl_vector_get(v, imax);
00763     }
00764 
00765     return imax;
00766 }
00767 

Generated on Fri Jul 3 11:23:58 2009 for NACO Pipeline Reference Manual by  doxygen 1.5.8