naco_spc.c

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

Generated on Tue Mar 12 15:19:53 2013 for NACO Pipeline Reference Manual by  doxygen 1.4.7