visir_utils.c

00001 /* $Id: visir_utils.c,v 1.145 2012/02/03 14:23:33 llundin Exp $
00002  *
00003  * This file is part of the VISIR 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: 2012/02/03 14:23:33 $
00024  * $Revision: 1.145 $
00025  * $Name: visir-3_5_0 $
00026  */
00027 
00028 #ifdef HAVE_CONFIG_H
00029 #include <config.h>
00030 #endif
00031 
00032 /*-----------------------------------------------------------------------------
00033                                    Includes
00034  -----------------------------------------------------------------------------*/
00035 
00036 #include <cpl.h>
00037 
00038 /* TEMPORARY SUPPORT OF CPL 5.x */
00039 #ifndef CPL_SIZE_FORMAT
00040 #define CPL_SIZE_FORMAT "d"
00041 #define cpl_size int
00042 #endif
00043 /* END TEMPORARY SUPPORT OF CPL 5.x */
00044 
00045 #include "visir_utils.h"
00046 
00047 #include "irplib_utils.h"
00048 
00049 #include "visir_inputs.h"
00050 #include "visir_pfits.h"
00051 #include "visir_spc_distortion.h"
00052 
00053 #include <string.h>
00054 #include <math.h>
00055 #include <assert.h>
00056 
00057 /*-----------------------------------------------------------------------------
00058                                    Define
00059  -----------------------------------------------------------------------------*/
00060 
00061 #define VISIR_BACKGD_START  76
00062 #define VISIR_BACKGD_STOP   172
00063 
00064 /*----------------------------------------------------------------------------*/
00070 /*----------------------------------------------------------------------------*/
00071 
00072 /*-----------------------------------------------------------------------------
00073                         Private function prototypes
00074  -----------------------------------------------------------------------------*/
00075 
00076 
00077 static double visir_great_circle_dist(double, double, double, double);
00078 static double ra_hms2deg(int, int, double);
00079 static double dec_hms2deg(int, int, double);
00080 
00081 static const char * visir_get_capa(const cpl_propertylist *);
00082 static double visir_hcycle_background(const irplib_framelist *, int, int);
00083 
00084 #ifdef VISIR_MASK_HAS
00085 static cpl_boolean visir_mask_has(const cpl_mask *, cpl_binary, int);
00086 #endif
00087 
00088 
00091 /*----------------------------------------------------------------------------*/
00100 /*----------------------------------------------------------------------------*/
00101 double * visir_utils_get_wls(const irplib_framelist * self)
00102 {
00103     /* Get the number of files */
00104     const int   size = irplib_framelist_get_size(self);
00105     double    * wls = NULL;
00106     int         i;
00107 
00108 
00109     skip_if (0);
00110 
00111     skip_if(irplib_framelist_contains(self, VISIR_PFITS_DOUBLE_MONOC_POS,
00112                                       CPL_TYPE_DOUBLE, CPL_FALSE, 0.0));
00113 
00114     /* Allocate the output array */
00115     wls = cpl_malloc(size * sizeof(double));
00116 
00117     /* Get the wavelengths */
00118     for (i=0; i < size; i++) {
00119         const cpl_propertylist * plist
00120             = irplib_framelist_get_propertylist_const(self, i);
00121 
00122         wls[i] = visir_pfits_get_monoc_pos(plist);
00123 
00124         skip_if (0);
00125     }
00126 
00127     end_skip;
00128 
00129     if (cpl_error_get_code()) {
00130         cpl_free(wls);
00131         wls = NULL;
00132     }
00133 
00134     return wls;
00135 }
00136 
00137 /*----------------------------------------------------------------------------*/
00147 /*----------------------------------------------------------------------------*/
00148 cpl_image * visir_create_disk_intimage(
00149         int     nx, 
00150         int     ny, 
00151         int     x_pos, 
00152         int     y_pos, 
00153         int     radius) 
00154 {
00155     cpl_image   *   intima;
00156     int         *   pintima;
00157     double          dist;
00158     int             i, j;
00159 
00160     /* Create the empty output image */
00161     intima = cpl_image_new(nx, ny, CPL_TYPE_INT);
00162     pintima = cpl_image_get_data_int(intima);
00163 
00164     /* Loop on the pixels */
00165     for (j=0;j<ny ; j++) {
00166         for (i=0;i<nx ; i++) {
00167             dist = (i+1-x_pos)*(i+1-x_pos)+(j+1-y_pos)*(j+1-y_pos);
00168             if (dist < radius*radius) {
00169                 pintima[i+j*nx] = 1;
00170             } else {
00171                 pintima[i+j*nx] = 0;
00172             }
00173         }
00174     }
00175     return intima;
00176 }
00177 
00178 /*----------------------------------------------------------------------------*/
00189 /*----------------------------------------------------------------------------*/
00190 cpl_image * visir_create_ring_intimage(
00191         int     nx, 
00192         int     ny, 
00193         int     x_pos, 
00194         int     y_pos, 
00195         int     radius1, 
00196         int     radius2)
00197 {
00198     cpl_image   *   intima;
00199     int         *   pintima;
00200     double          dist;
00201     int             i, j;
00202 
00203     /* Create the empty output image */
00204     intima = cpl_image_new(nx, ny, CPL_TYPE_INT);
00205     pintima = cpl_image_get_data_int(intima);
00206 
00207     /* Loop on the pixels */
00208     for (j=0;j<ny ; j++) {
00209         for (i=0;i<nx ; i++) {
00210             dist = (i+1-x_pos)*(i+1-x_pos)+(j+1-y_pos)*(j+1-y_pos);
00211             if ((dist < radius2*radius2) && (dist > radius1*radius1)) {
00212                 pintima[i+j*nx] = 1;
00213             } else {
00214                 pintima[i+j*nx] = 0;
00215             }
00216         }
00217     }
00218     return intima;
00219 }
00220 
00221 /*----------------------------------------------------------------------------*/
00232 /*----------------------------------------------------------------------------*/
00233 double visir_image_sigma_clip(const cpl_image * self, double * pstdev)
00234 {
00235     const int      dimx = cpl_image_get_size_x(self);
00236     const int      dimy = cpl_image_get_size_y(self);
00237     const cpl_type type = cpl_image_get_type(self);
00238     /* Apply a 3x3 median filter to the input image  */
00239     /* FIXME: A wrap (around float/double) would be sufficient */
00240     cpl_image    * noise = cpl_image_new(dimx, dimy, type);
00241     cpl_mask     * bpm = NULL;
00242     cpl_mask     * kernel = cpl_mask_new(3, 3);
00243     const int      niterations = 5;
00244     const double   sigma = 3.0;
00245     const double   median_corr = 0.94;
00246     double         bgnoise = -1;
00247     int            i = -1;
00248 
00249 
00250     bug_if (0);
00251 
00252     bug_if(cpl_mask_not(kernel));
00253     bug_if(cpl_image_filter_mask(noise, self, kernel, CPL_FILTER_MEDIAN,
00254                                  CPL_BORDER_FILTER));
00255 
00256     /* (Inverted) Noise image */
00257     bug_if (cpl_image_subtract(noise, self));
00258 
00259     for (i=0; i < niterations ; i++) {
00260         /* Compute mean and stdev */
00261         cpl_stats * stats =
00262             cpl_stats_new_from_image(noise, CPL_STATS_MEAN | CPL_STATS_STDEV);
00263 
00264         const double mean  = cpl_stats_get_mean(stats);
00265         const double stdev = cpl_stats_get_stdev(stats);
00266 
00267         /* Set the thresholds */
00268         const double low_thresh  = mean - sigma * stdev;
00269         const double high_thresh = mean + sigma * stdev;
00270 
00271 
00272         cpl_stats_delete(stats); /* :-( */
00273 
00274         /* The previous thresholding may have left too few good pixels */
00275         skip_if (0);
00276 
00277         /* Identify where mean-sigma*stdev < noise < mean+sigma*stdev */
00278         bpm = cpl_mask_threshold_image_create(noise, low_thresh, high_thresh);
00279 
00280         bug_if (0);
00281 
00282         bug_if (cpl_mask_not(bpm));
00283 
00284         bug_if (cpl_image_reject_from_mask(noise, bpm));
00285 
00286         cpl_mask_delete(bpm);  /* :-( */
00287         bpm = NULL;
00288 
00289     }
00290 
00291     if (pstdev != NULL) {
00292         /* Compute the stdev of the noise and the background */
00293 
00294         cpl_stats * stats =
00295             cpl_stats_new_from_image(noise, CPL_STATS_MEAN | CPL_STATS_STDEV);
00296 
00297         /* Compute mean and stdev */
00298         bgnoise = cpl_stats_get_stdev(stats);
00299         *pstdev = cpl_image_get_median(self) - cpl_stats_get_mean(stats);
00300 
00301         cpl_stats_delete(stats);
00302     } else {
00303         /* Compute the stdev */
00304         bgnoise = cpl_image_get_stdev(noise);
00305     }
00306 
00307     bug_if(0);
00308 
00309     bgnoise /= median_corr;
00310 
00311     end_skip;
00312 
00313     if (cpl_error_get_code()) 
00314         cpl_msg_error(cpl_func, "Computation of background noise using sigma=%g"
00315                       " failed in iteration %d of %d", sigma, i+1, niterations);
00316 
00317     cpl_mask_delete(kernel);
00318     cpl_mask_delete(bpm);
00319     cpl_image_delete(noise);
00320 
00321     return bgnoise;
00322 }
00323 
00324 /*----------------------------------------------------------------------------*/
00334 /*----------------------------------------------------------------------------*/
00335 double visir_img_phot_sigma_clip(const cpl_image * self)
00336 {
00337 
00338     const double noise = visir_image_sigma_clip(self, NULL);
00339 
00340     cpl_ensure(!cpl_error_get_code(), cpl_error_get_code(), noise);
00341 
00342     return noise;
00343 
00344 }
00345 
00346 /*----------------------------------------------------------------------------*/
00364 /*----------------------------------------------------------------------------*/
00365 int visir_star_find(const cpl_vector * v_ra, const cpl_vector * v_dec,
00366                     double ra, double dec, double maxdist, double * pdist)
00367 {
00368     const int    nra   = cpl_vector_get_size(v_ra);
00369     const int    ndec  = cpl_vector_get_size(v_dec);
00370     double       dmin = 0.0;  /* Avoid (false) uninit warning */
00371     int          minind = 0;
00372     int          i;
00373 
00374 
00375     /* Catch NULL input */
00376     cpl_ensure(nra  > 0,     cpl_error_get_code(), -2);
00377     cpl_ensure(ndec > 0,     cpl_error_get_code(), -3);
00378 
00379     /* It would be natural to use a cpl_bivector for the positions,
00380        but since CPL cannot ensure that a bivector comprises two vectors
00381        of the same length this would be pointless :-( */
00382     cpl_ensure(nra == ndec,  CPL_ERROR_INCOMPATIBLE_INPUT, -4);
00383 
00384     cpl_ensure(maxdist >= 0, CPL_ERROR_ILLEGAL_INPUT, -5);
00385 
00386     /* Find the index of the star closest to the given coordinate */
00387     for (i=0 ; i < nra ; i++) {
00388         const double rai  = cpl_vector_get(v_ra,  i);
00389         const double deci = cpl_vector_get(v_dec, i);
00390         const double gdist = visir_great_circle_dist(rai, deci, ra, dec);
00391 
00392         cpl_msg_debug(cpl_func, "DISTANCE (RAi,DECi)=(%g,%g) <=> "
00393                       "(RA,DEC)=(%g,%g): %g", rai, deci, ra, dec, gdist);
00394 
00395         if (i == 0 || gdist < dmin) {
00396             minind = i;
00397             dmin = gdist;
00398         }
00399     }
00400 
00401     if (pdist != NULL) *pdist = dmin;
00402 
00403     /* Check that it is close enough */
00404     if (dmin > maxdist) {
00405         cpl_msg_error(cpl_func, "Nearest standard star (%d of %d) at (RA,DEC)="
00406                       "(%g,%g) is too distant from (RA,DEC)=(%g, %g): %g > %g",
00407                       1+minind, nra, cpl_vector_get(v_ra,  minind),
00408                       cpl_vector_get(v_dec,  minind), ra, dec, dmin, maxdist);
00409         cpl_ensure(0, CPL_ERROR_DATA_NOT_FOUND, -1);
00410     }
00411 
00412     return minind;
00413 }
00414 
00415 /*----------------------------------------------------------------------------*/
00434 /*----------------------------------------------------------------------------*/
00435 cpl_error_code visir_star_convert(const char * line, int ra_hh, int ra_mm,
00436                                   double ra_ss, char isign, int dec_hh,
00437                                   int dec_mm, double dec_ss,
00438                                   const double * jys, int njys,
00439                                   double * pra, double * pdec)
00440 {
00441 
00442     double sign;
00443     int i;
00444 
00445     assert( line );
00446     assert( pra );
00447     assert( pdec );
00448     assert( jys );
00449     assert( njys > 0 );
00450 
00451 
00452     if (isign == '+')
00453       sign = 1.0;
00454     else if (isign == '-')
00455       sign = -1.0;
00456     else {
00457         cpl_msg_error(cpl_func, "Line has illegal declination-sign character "
00458                       "(%c): %s", isign, line);
00459         cpl_ensure_code(0, CPL_ERROR_BAD_FILE_FORMAT);
00460     }
00461 
00462     if (ra_hh < 0) {
00463         cpl_msg_error(cpl_func, "Line has negative RA hh (%d): %s",
00464                       ra_hh, line);
00465         cpl_ensure_code(0, CPL_ERROR_BAD_FILE_FORMAT);
00466     }
00467     if (ra_mm < 0) {
00468         cpl_msg_error(cpl_func, "Line has negative RA mm (%d): %s",
00469                       ra_hh, line);
00470         cpl_ensure_code(0, CPL_ERROR_BAD_FILE_FORMAT);
00471     }
00472     if (ra_mm >= 60) {
00473         cpl_msg_error(cpl_func, "Line has too large RA mm (%d): %s ",
00474                       ra_mm, line);
00475         cpl_ensure_code(0, CPL_ERROR_BAD_FILE_FORMAT);
00476     }
00477     if (ra_ss < 0) {
00478         cpl_msg_error(cpl_func, "Line has negative RA ss (%g): %s",
00479                       ra_ss, line);
00480         cpl_ensure_code(0, CPL_ERROR_BAD_FILE_FORMAT);
00481     }
00482     if (ra_ss >= 60) {
00483         cpl_msg_error(cpl_func, "Line has too large RA ss (%g): %s ",
00484                       ra_ss, line);
00485         cpl_ensure_code(0, CPL_ERROR_BAD_FILE_FORMAT);
00486     }
00487 
00488     if (dec_hh < 0) {
00489         cpl_msg_error(cpl_func, "Line has negative DEC hh (%d): %s",
00490                       dec_hh, line);
00491         cpl_ensure_code(0, CPL_ERROR_BAD_FILE_FORMAT);
00492     }
00493     if (dec_mm < 0) {
00494         cpl_msg_error(cpl_func, "Line has negative DEC mm (%d): %s",
00495                       dec_hh, line);
00496         cpl_ensure_code(0, CPL_ERROR_BAD_FILE_FORMAT);
00497     }
00498     if (dec_mm >= 60) {
00499         cpl_msg_error(cpl_func, "Line has too large DEC mm (%d): %s ",
00500                       dec_mm, line);
00501         cpl_ensure_code(0, CPL_ERROR_BAD_FILE_FORMAT);
00502     }
00503     if (dec_ss < 0) {
00504         cpl_msg_error(cpl_func, "Line has negative DEC ss (%g): %s",
00505                       dec_ss, line);
00506         cpl_ensure_code(0, CPL_ERROR_BAD_FILE_FORMAT);
00507     }
00508     if (dec_ss >= 60) {
00509         cpl_msg_error(cpl_func, "Line has too large DEC ss (%g): %s ",
00510                       dec_ss, line);
00511         cpl_ensure_code(0, CPL_ERROR_BAD_FILE_FORMAT);
00512     }
00513 
00514     *pra = ra_hms2deg(ra_hh, ra_mm, ra_ss);
00515     if (*pra >= 360.0) {
00516         cpl_msg_error(cpl_func, "Line has too large RA (%g): %s ",
00517                       *pra, line);
00518         cpl_ensure_code(0, CPL_ERROR_BAD_FILE_FORMAT);
00519     }
00520 
00521     *pdec = sign * dec_hms2deg(dec_hh, dec_mm, dec_ss);
00522     if (*pdec > 90.0) {
00523         cpl_msg_error(cpl_func, "Line has too large RA (%g): %s ",
00524                       *pdec, line);
00525         cpl_ensure_code(0, CPL_ERROR_BAD_FILE_FORMAT);
00526     }
00527     if (*pdec < -90.0) {
00528         cpl_msg_error(cpl_func, "Line has too small RA (%g): %s ",
00529                       *pdec, line);
00530         cpl_ensure_code(0, CPL_ERROR_BAD_FILE_FORMAT);
00531     }
00532 
00533     for (i=0; i < njys; i++) if (jys[i] <= 0.0) {
00534         cpl_msg_error(cpl_func,"Line has non-positive Jy value (%g) at %d: %s ",
00535                       jys[i], i+1, line);
00536         cpl_ensure_code(0, CPL_ERROR_BAD_FILE_FORMAT);
00537     }
00538 
00539     return CPL_ERROR_NONE;
00540 
00541 }
00542 
00543 /*----------------------------------------------------------------------------*/
00556 /*----------------------------------------------------------------------------*/
00557 cpl_table * visir_table_new_xypos(const cpl_imagelist * images,
00558                                   const char * label)
00559 {
00560     cpl_errorstate cleanstate = cpl_errorstate_get();
00561     const int    nsize = cpl_imagelist_get_size(images);
00562     double       psigmas[] = {5, 2, 1, 0.5}; /* Actually not modified */
00563     cpl_vector * sigmas = NULL;
00564     cpl_table  * self  = NULL;
00565     const int           nsigmas = sizeof(psigmas)/sizeof(double);
00566     int isflux = 0;
00567     int nfail, i;
00568 
00569     cpl_ensure(nsize > 0, cpl_error_get_code(), NULL);
00570     cpl_ensure(label,     CPL_ERROR_NULL_INPUT, NULL);
00571     cpl_ensure(!strcmp(label, "FLUX") || !strcmp(label, "FWHM"),
00572                CPL_ERROR_UNSUPPORTED_MODE, NULL);
00573 
00574     self = cpl_table_new(nsize);
00575 
00576     skip_if (cpl_table_new_column(self, "X_POS", CPL_TYPE_DOUBLE));
00577     skip_if (cpl_table_new_column(self, "Y_POS", CPL_TYPE_DOUBLE));
00578 
00579     if (!strcmp(label,"FLUX")) {
00580         isflux = 1;
00581         skip_if (cpl_table_new_column(self, label,    CPL_TYPE_DOUBLE));
00582     } else {
00583         skip_if (cpl_table_new_column(self, "X_FWHM", CPL_TYPE_DOUBLE));
00584         skip_if (cpl_table_new_column(self, "Y_FWHM", CPL_TYPE_DOUBLE));
00585     }
00586 
00587     sigmas = cpl_vector_wrap(4, psigmas);
00588     skip_if (sigmas == NULL);
00589 
00590     cpl_msg_info(cpl_func, "Detecting apertures using %d sigma-levels "
00591                  "ranging from %g down to %g", nsigmas, psigmas[0],
00592                  psigmas[nsigmas-1]);
00593 
00594     /* Object detection */
00595     nfail = 0;
00596     for (i=0 ; i < nsize ; i++) {
00597         const cpl_image * image = cpl_imagelist_get_const(images, i);
00598         cpl_apertures   * apert;
00599         cpl_size          isigma;
00600 
00601 
00602         double posx  = -1;
00603         double posy  = -1;
00604         double fwhmx = -1;
00605         double fwhmy = -1;
00606         double flux  = -1;
00607         int iflux;
00608 
00609         skip_if (0);
00610 
00611         /* Find any apertures in each image */
00612         apert = cpl_apertures_extract(image, sigmas, &isigma);
00613 
00614         if (apert != NULL && cpl_error_get_code()) {
00615             /* FIX for DFS 2616 */
00616             cpl_msg_error(cpl_func, "cpl_apertures_extract() returned non-NULL "
00617                           "while setting the CPL error-state to '%s' at '%s'",
00618                           cpl_error_get_message(), cpl_error_get_where());
00619             cpl_msg_debug(cpl_func, "Deleting the spurious aperture list at %p:",
00620                           (void*)apert);
00621             if (cpl_msg_get_level() <= CPL_MSG_DEBUG)
00622                 cpl_apertures_dump(apert, stdout);
00623             cpl_apertures_delete(apert);
00624             apert = NULL;
00625         }
00626 
00627         if (apert != NULL &&
00628             !irplib_apertures_find_max_flux(apert, &iflux, 1) &&
00629             cpl_apertures_get_flux(apert, iflux) > 0) {
00630 
00631             posx = cpl_apertures_get_centroid_x(apert, iflux);
00632             posy = cpl_apertures_get_centroid_y(apert, iflux);
00633             flux = cpl_apertures_get_flux(apert, iflux);
00634             if (!isflux)
00635                 cpl_image_get_fwhm(image, (int)posx, (int)posy, &fwhmx, &fwhmy);
00636 
00637             cpl_msg_info(cpl_func, "Detected an aperture with flux=%g at "
00638                          "sigma=%g, at position: %g %g", flux,
00639                          psigmas[isigma], posx, posy);
00640     
00641         }
00642 
00643         if (apert == NULL || cpl_error_get_code()) {
00644             visir_error_reset("Aperture detection in image %d of %d failed",
00645                              i+1, nsize);
00646             nfail++;
00647         } else if (flux <= 0) {
00648             cpl_msg_warning(cpl_func, "Ignoring %d-pixel aperture %d (out of "
00649                             "%d) in file %d of %d with non-positive flux: %g",
00650                             (int)cpl_apertures_get_npix(apert, iflux), iflux,
00651                             (int)cpl_apertures_get_size(apert), i+1, nsize,
00652                             flux);
00653             nfail++;
00654         }
00655 
00656         cpl_apertures_delete(apert);
00657         apert = NULL;
00658 
00659         skip_if (cpl_table_set_double(self, "X_POS", i, posx));
00660         skip_if (cpl_table_set_double(self, "Y_POS", i, posy));
00661 
00662         if (isflux)
00663             skip_if (cpl_table_set_double(self, "FLUX",  i, flux));
00664         else {
00665             skip_if (cpl_table_set_double(self, "X_FWHM", i, fwhmx));
00666             skip_if (cpl_table_set_double(self, "Y_FWHM", i, fwhmy));
00667         }
00668 
00669     }
00670 
00671     /* Check if some detections were successful */
00672     if (nfail == nsize) {
00673         cpl_msg_error(cpl_func, "Aperture detection failed in all %d images",
00674                       nsize);
00675         visir_error_set(CPL_ERROR_DATA_NOT_FOUND);
00676         skip_if(1);
00677     }
00678 
00679     end_skip;
00680 
00681     cpl_vector_unwrap(sigmas);
00682 
00683     if (self && cpl_error_get_code()) {
00684         cpl_table_delete(self);
00685         self = NULL;
00686     }
00687 
00688     return self;
00689 }
00690 
00691 /*----------------------------------------------------------------------------*/
00698 /*----------------------------------------------------------------------------*/
00699 int visir_vector_minpos(const cpl_vector * v)
00700 {
00701     const double * x     = cpl_vector_get_data_const(v);
00702     const int      n     = cpl_vector_get_size(v);
00703     int minpos = 0;
00704     int i;
00705 
00706     cpl_ensure(x, CPL_ERROR_NULL_INPUT, -1);
00707 
00708     for (i = 1; i < n; i++) if (x[i] < x[minpos]) minpos = i;
00709 
00710     return minpos;
00711 }
00712 
00713 /*----------------------------------------------------------------------------*/
00728 /*----------------------------------------------------------------------------*/
00729 cpl_error_code visir_bivector_load(cpl_bivector * self, FILE * stream)
00730 {
00731     cpl_vector * v1;
00732     cpl_vector * v2;
00733     int          np = 0;
00734     int          xsize, ysize;
00735     char         line[1024];
00736 
00737     cpl_ensure_code(self,   CPL_ERROR_NULL_INPUT);
00738     cpl_ensure_code(stream, CPL_ERROR_NULL_INPUT);
00739 
00740     /* Create and fill the vectors */
00741     v1 = cpl_bivector_get_x(self);
00742     v2 = cpl_bivector_get_y(self);
00743 
00744     xsize = cpl_vector_get_size(v1);
00745     ysize = cpl_vector_get_size(v2);
00746 
00747     while (fgets(line, 1024, stream) != NULL) {
00748         double x, y;
00749         if (line[0] != '#' && sscanf(line, "%lg %lg", &x, &y) == 2) {
00750             /* Found new element-pair
00751                - increase vector sizes if necessary,
00752                - insert element at end and
00753                - increment size counter */
00754             if (np == xsize) {
00755                 xsize *= 2;
00756                 cpl_vector_set_size(v1, xsize);
00757             }
00758             if (np == ysize) {
00759                 ysize *= 2;
00760                 cpl_vector_set_size(v2, ysize);
00761             }
00762             cpl_vector_set(v1, np, x);
00763             cpl_vector_set(v2, np, y);
00764             np++;
00765         }
00766     }
00767 
00768     /* Check that the loop ended due to eof and not an error */
00769     cpl_ensure_code(!ferror(stream), CPL_ERROR_FILE_IO);
00770 
00771     /* Check that the file was not empty and set the size to its true value */
00772     if (np == 0 || cpl_vector_set_size(v1, np) || cpl_vector_set_size(v2, np)) {
00773         cpl_ensure_code(0, CPL_ERROR_BAD_FILE_FORMAT);
00774     }
00775 
00776     return CPL_ERROR_NONE;
00777 
00778 }
00779 
00780 /*----------------------------------------------------------------------------*/
00793 /*----------------------------------------------------------------------------*/
00794 double visir_star_dist_min(const double * pras, const double * pdecs, int nloc,
00795                            int * piloc1, int * piloc2)
00796 {
00797 
00798     int i, j;
00799     double dmin = 180;
00800 
00801 
00802     assert( pras != NULL);
00803     assert( pdecs != NULL);
00804     assert( piloc1 != NULL);
00805     assert( piloc2 != NULL);
00806     assert( nloc > 0 );
00807 
00808     for (j = 0; j < nloc; j++) {
00809         for (i = 0; i < j; i++) {
00810             const double dist = visir_great_circle_dist(pras[i], pdecs[i],
00811                                                         pras[j], pdecs[j]);
00812             if (dist < dmin) {
00813                 dmin = dist;
00814                 *piloc1 = i;
00815                 *piloc2 = j;
00816             }
00817             if (dist < VISIR_STAR_MAX_RADIUS)
00818                 cpl_msg_warning(cpl_func,"The two stars (%d,%d) have a distance"
00819                                 ": %g < %g", i, j, dist, VISIR_STAR_MAX_RADIUS);
00820         }
00821     }
00822 
00823     return dmin;
00824 }
00825 
00826 
00827 /*----------------------------------------------------------------------------*/
00841 /*----------------------------------------------------------------------------*/
00842 const char ** visir_framelist_set_tag(irplib_framelist * self,
00843                                       char * (*pftag)(const cpl_frame *,
00844                                                       const cpl_propertylist *,
00845                                                       int),
00846                                       int *pntags)
00847 {
00848 
00849     /* FIXME: Copied from NACO - move to irplib */
00850 
00851     const char ** taglist = NULL; /* Must be initialized due to realloc call */
00852     int iframe, size;
00853 
00854     cpl_ensure(!cpl_error_get_code(), cpl_error_get_code(), NULL);
00855     cpl_ensure(self   != NULL, CPL_ERROR_NULL_INPUT, NULL);
00856     cpl_ensure(pftag  != NULL, CPL_ERROR_NULL_INPUT, NULL);
00857     cpl_ensure(pntags != NULL, CPL_ERROR_NULL_INPUT, NULL);
00858 
00859     size = irplib_framelist_get_size(self);
00860 
00861     cpl_ensure(size > 0, CPL_ERROR_DATA_NOT_FOUND, NULL);
00862 
00863     *pntags = 0;
00864 
00865     for (iframe = 0; iframe < size ; iframe++) {
00866         cpl_frame  * frame = irplib_framelist_get(self, iframe);
00867         const cpl_propertylist * plist
00868             = irplib_framelist_get_propertylist_const(self, iframe);
00869         char       * tag;
00870         const char * newtag;
00871         int          i;
00872 
00873 
00874         /* This should really be an assert() */
00875         cpl_ensure(frame != NULL, CPL_ERROR_ILLEGAL_INPUT, NULL);
00876         cpl_ensure(plist != NULL, CPL_ERROR_ILLEGAL_INPUT, NULL);
00877 
00878         tag = (*pftag)(frame, plist, iframe);
00879 
00880         cpl_ensure(tag != NULL, cpl_error_get_code(), NULL);
00881 
00882         /* From this point on failures should not really happen */
00883 
00884         (void)cpl_frame_set_tag(frame, tag);
00885         cpl_free(tag);
00886 
00887         newtag = cpl_frame_get_tag(frame);
00888 
00889         cpl_ensure(!cpl_error_get_code(), cpl_error_get_code(), NULL);
00890 
00891         /* Compare the new tags with those of previous frames */
00892         for (i=0; i < *pntags; i++)
00893             if (strcmp(newtag, taglist[i]) == 0) break;
00894 
00895         if (i == *pntags) {
00896             /* The new tag is different from the previous ones
00897                - add it to the list */
00898             (*pntags)++;
00899             taglist = (const char **)cpl_realloc(taglist, *pntags *
00900                                                  sizeof(const char *));
00901             taglist[i] = newtag;
00902         }
00903 
00904     }
00905 
00906     return taglist;
00907 
00908 }
00909 
00910 /*----------------------------------------------------------------------------*/
00920 /*----------------------------------------------------------------------------*/
00921 cpl_error_code visir_qc_append_background(cpl_propertylist * self,
00922                                           const irplib_framelist * rawframes,
00923                                           int icol1, int icol2)
00924 {
00925 
00926     /* Compute the background values of the HCYCLE frames */
00927     const double bg_mean = visir_hcycle_background(rawframes, icol1, icol2);
00928 
00929     skip_if (0);
00930 
00931     bug_if (cpl_propertylist_append_double(self, "ESO QC BACKGD MEAN",
00932                                            bg_mean));
00933 
00934     end_skip;
00935 
00936     return cpl_error_get_code();
00937 
00938 }
00939 
00940 
00941 /*----------------------------------------------------------------------------*/
00950 /*----------------------------------------------------------------------------*/
00951 cpl_error_code visir_qc_append_capa(cpl_propertylist * self,
00952                                     const irplib_framelist * rawframes)
00953 {
00954 
00955     cpl_errorstate cleanstate = cpl_errorstate_get();
00956     const cpl_propertylist * plist
00957         = irplib_framelist_get_propertylist_const(rawframes, 0);
00958     const char             * capa;
00959 
00960 
00961     bug_if (0);
00962 
00963     capa = visir_get_capa(plist);
00964 
00965     if (cpl_error_get_code()) {
00966         visir_error_reset("Could not determine capa");
00967     } else {
00968         bug_if (cpl_propertylist_append_string(self, "ESO QC CAPA", capa));
00969     }
00970 
00971     end_skip;
00972 
00973     return cpl_error_get_code();
00974 
00975 }
00976 
00977 /*----------------------------------------------------------------------------*/
00985 /*----------------------------------------------------------------------------*/
00986 cpl_error_code visir_qc_append_filter(cpl_propertylist * self,
00987                                       const irplib_framelist * rawframes)
00988 {
00989 
00990     const cpl_propertylist * plist
00991         = irplib_framelist_get_propertylist_const(rawframes, 0);
00992     const char             * value = visir_pfits_get_filter(plist);
00993 
00994 
00995     skip_if (0);
00996  
00997     bug_if (cpl_propertylist_append_string(self, "ESO QC FILTER", value));
00998 
00999     end_skip;
01000 
01001     return cpl_error_get_code();
01002 
01003 }
01004 
01005 /*----------------------------------------------------------------------------*/
01013 /*----------------------------------------------------------------------------*/
01014 cpl_error_code visir_qc_append_exptime(cpl_propertylist * self,
01015                                        const irplib_framelist * rawframes)
01016 {
01017 
01018     const cpl_propertylist * plist
01019         = irplib_framelist_get_propertylist_const(rawframes, 0);
01020 
01021     /* Get the total exposure time */
01022     /* DIT */
01023     const double dit = visir_pfits_get_dit(plist);
01024     /* NDIT */
01025     const int ndit = visir_pfits_get_ndit(plist);
01026     /* NNOD */
01027     const int nnod = irplib_framelist_get_size(rawframes);
01028     /* Number of chopping cycles */
01029     const int ncycles = visir_pfits_get_chop_ncycles(plist);
01030 
01031     /* Exptime * 2 because of chopping */
01032     const double value = 2 * dit * ndit * nnod * ncycles;
01033 
01034 
01035     skip_if (0);
01036     
01037     if (value <= 0) {
01038         cpl_msg_error(cpl_func, "Illegal exposure time "
01039                       "(dit=%g:ndit=%d:ncycles=%d:nnod=%d): %g",
01040                       dit, ndit, ncycles, nnod, value);
01041         skip_if(1);
01042     }
01043 
01044     bug_if (cpl_propertylist_append_double(self, "ESO QC EXPTIME", value));
01045 
01046     end_skip;
01047 
01048     return cpl_error_get_code();
01049 
01050 }
01051 
01054 /*----------------------------------------------------------------------------*/
01065 /*----------------------------------------------------------------------------*/
01066 static double visir_great_circle_dist(double ra1, double dec1,
01067                                       double ra2, double dec2)
01068 {
01069 
01070   /* Convert all input from degrees to radian - and back for the result */
01071   const double dra  = sin( CPL_MATH_RAD_DEG * (ra2  - ra1 )/2.0 );
01072   const double ddec = sin( CPL_MATH_RAD_DEG * (dec2 - dec1)/2.0 );
01073 
01074   dec1 *= CPL_MATH_RAD_DEG;
01075   dec2 *= CPL_MATH_RAD_DEG;
01076 
01077   return 2.0 * asin(sqrt( ddec*ddec + cos(dec1)*cos(dec2)*dra*dra))
01078       * CPL_MATH_DEG_RAD;
01079 
01080 }
01081 
01082 /*----------------------------------------------------------------------------*/
01095 /*----------------------------------------------------------------------------*/
01096 static double ra_hms2deg(int hh, int mm, double ss)
01097 {
01098     return 15.0 * dec_hms2deg(hh, mm, ss);
01099 }
01100 
01101 /*----------------------------------------------------------------------------*/
01113 /*----------------------------------------------------------------------------*/
01114 static double dec_hms2deg(int dd, int mm, double ss)
01115 {
01116     return ((double)ss/60.0 + (double)mm)/60.0 + dd;
01117 }
01118 
01119 /*----------------------------------------------------------------------------*/
01132 /*----------------------------------------------------------------------------*/
01133 static double visir_hcycle_background(const irplib_framelist * rawframes,
01134                                int icol1, int icol2)
01135 {
01136     cpl_imagelist * iset = NULL;
01137     /* Get the number of files */
01138     const int       nfiles = irplib_framelist_get_size(rawframes);
01139     double          bgsum  = 0;
01140     double          bgmean = -1;
01141     int             nsum  = 0;
01142     int             i, j;
01143 
01144     
01145     skip_if (nfiles < 1);
01146 
01147     if (icol1 == 0) icol1 = VISIR_BACKGD_START;
01148     if (icol2 == 0) icol2 = VISIR_BACKGD_STOP;
01149 
01150     cpl_msg_info(cpl_func, "Computing Half-cycle background level from column %d "
01151                  "through %d", icol1, icol2);
01152 
01153     /* Loop on the hcycles images */
01154     for (i=0; i < nfiles; i++) {
01155 
01156         iset = visir_load_hcycle(rawframes, i);
01157 
01158         skip_if (0);
01159 
01160         for (j = 0; j < cpl_imagelist_get_size(iset) ; j++) {
01161             const double median =
01162                 cpl_image_get_median_window(cpl_imagelist_get(iset, j),
01163                                             VISIR_BACKGD_START, icol1,
01164                                             VISIR_BACKGD_STOP, icol2);
01165 
01166             skip_if (0);
01167 
01168             if (median != median) {
01169                 const cpl_frame * frame = irplib_framelist_get_const(rawframes,
01170                                                                      i);
01171                 /* Some Comm. I data contains NaNs */
01172                 cpl_msg_error(cpl_func, "Image window (%d, %d, %d, %d) "
01173                               "(image %d of %d) in %s (frame %d of %d) "
01174                               "has NaN median",
01175                               VISIR_BACKGD_START, icol1,
01176                               VISIR_BACKGD_STOP, icol2,
01177                               j+1, (int)cpl_imagelist_get_size(iset),
01178                               cpl_frame_get_filename(frame), i+1, nfiles);
01179                 visir_error_set(CPL_ERROR_BAD_FILE_FORMAT);
01180                 skip_if(1);
01181             }
01182             bgsum += median;
01183         }
01184         nsum += j;
01185         cpl_imagelist_delete(iset);
01186         iset = NULL;
01187     }
01188 
01189     /* Test if there are some HCYCLE frames */
01190     skip_if (nsum < 1);
01191 
01192     bgmean = bgsum / nsum;
01193 
01194     end_skip;
01195 
01196     cpl_imagelist_delete(iset);
01197 
01198     /* The background was requested to not include the offset correction */
01199     return bgmean - VISIR_HCYCLE_OFFSET;
01200 }
01201 
01202 
01203 /*----------------------------------------------------------------------------*/
01214 /*----------------------------------------------------------------------------*/
01215 cpl_error_code
01216 visir_get_subpixel_maxpos(const cpl_image * img, cpl_size x, cpl_size y,
01217                           double * xsub, double * ysub)
01218 {
01219     int bad;
01220     const cpl_size nx = cpl_image_get_size_x(img);
01221     const cpl_size ny = cpl_image_get_size_y(img);
01222 
01223     *xsub = 0;
01224     *ysub = 0;
01225     if (x - 1 > 0 && x + 1 <= nx) {
01226         double sub[] = {
01227             cpl_image_get(img, x - 1, y, &bad),
01228             cpl_image_get(img, x - 0, y, &bad),
01229             cpl_image_get(img, x + 1, y, &bad),
01230         };
01231         if (!bad)
01232             *xsub = 0.5 * (sub[0] - sub[2])/(sub[0] - 2*sub[1] + sub[2]);
01233     }
01234     if (y - 1 > 0 && y + 1 <= ny) {
01235         double sub[] = {
01236             cpl_image_get(img, x, y - 1, &bad),
01237             cpl_image_get(img, x, y - 0, &bad),
01238             cpl_image_get(img, x, y + 1, &bad),
01239         };
01240         if (!bad)
01241             *ysub = 0.5 * (sub[0] - sub[2])/(sub[0] - 2*sub[1] + sub[2]);
01242     }
01243 
01244     return cpl_error_get_code();
01245 }
01246 
01247 
01248 /*----------------------------------------------------------------------------*/
01259 /*----------------------------------------------------------------------------*/
01260 cpl_error_code
01261 visir_fftxcorrelate(const cpl_image * atemplate, const cpl_image * aimg,
01262                     cpl_boolean normalize, double * xshift, double * yshift)
01263 {
01264     cpl_size Nx = cpl_image_get_size_x(aimg);
01265     cpl_size Ny = cpl_image_get_size_y(aimg);
01266     const cpl_size nsquare = abs(Nx-Ny);
01267     cpl_size Nxe = 2 * (Nx + (Ny > Nx ? nsquare : 0)) - 1;
01268     cpl_size Nye = 2 * (Ny + (Nx > Ny ? nsquare : 0)) - 1;
01269     cpl_size txshift, tyshift;
01270     double subx = 0, suby = 0;
01271     double * bzimg = cpl_calloc(Nxe * Nye, sizeof(double));
01272     double * bztemp = cpl_calloc(Nxe * Nye, sizeof(double));
01273     cpl_image * template = cpl_image_cast(atemplate, CPL_TYPE_DOUBLE);
01274     cpl_image * img = NULL;
01275     cpl_image * zimg = NULL;
01276     cpl_image * ztemp = NULL;
01277     cpl_image * fft1 = NULL;
01278     cpl_image * fft2 = NULL;
01279     cpl_image * res = NULL;
01280 
01281     zimg = cpl_image_wrap(Nxe, Nye, CPL_TYPE_DOUBLE, bzimg);
01282     ztemp = cpl_image_wrap(Nxe, Nye, CPL_TYPE_DOUBLE, bztemp);
01283 
01284     if (Nx > Ny)
01285         Ny += nsquare;
01286     else
01287         Nx += nsquare;
01288     /* FIXME: zero pads to square images due to DFS10988 */
01289     cpl_ensure_code(Nx == Ny, CPL_ERROR_ILLEGAL_INPUT);
01290 
01291     if (cpl_image_get_type(aimg) != CPL_TYPE_DOUBLE)
01292         img = cpl_image_cast(aimg, CPL_TYPE_DOUBLE);
01293     else
01294         img = cpl_image_duplicate(aimg);
01295 
01296     skip_if(img == NULL);
01297 
01298     cpl_image_fill_rejected(img, 0);
01299     cpl_image_fill_rejected(template, 0);
01300 
01301     /* normalize */
01302     if (normalize) {
01303         skip_if(cpl_image_subtract_scalar(img, cpl_image_get_mean(img)));
01304         skip_if(cpl_image_divide_scalar(img, cpl_image_get_stdev(img)));
01305         skip_if(cpl_image_subtract_scalar(template, cpl_image_get_mean(template)));
01306         skip_if(cpl_image_divide_scalar(template, cpl_image_get_stdev(template)));
01307     }
01308 
01309     /* zero pad */
01310     skip_if(cpl_image_copy(zimg, img, 1, 1));
01311     skip_if(cpl_image_copy(ztemp, template, Nx, Ny));
01312 
01313     fft1 = cpl_image_new(Nxe, Nye, CPL_TYPE_DOUBLE_COMPLEX);
01314     fft2 = cpl_image_new(Nxe, Nye, CPL_TYPE_DOUBLE_COMPLEX);
01315     res = cpl_image_new(Nxe, Nye, CPL_TYPE_DOUBLE);
01316 
01317     /* flip first image to row major
01318      * second image is already flipped as it is column major
01319      * so we have a fft correlation instead of a convolution */
01320     skip_if(cpl_image_flip(zimg, 1));
01321     skip_if(cpl_image_flip(zimg, 3));
01322 
01323     skip_if(cpl_fft_image(fft1, zimg, CPL_FFT_FORWARD));
01324     skip_if(cpl_fft_image(fft2, ztemp, CPL_FFT_FORWARD));
01325 
01326     /* correlate, no conjugation necessary due to flipping */
01327     skip_if(cpl_image_multiply(fft1, fft2));
01328 
01329     skip_if(cpl_fft_image(res, fft1, CPL_FFT_BACKWARD));
01330 
01331     skip_if(cpl_image_get_maxpos(res, &txshift, &tyshift));
01332     skip_if(visir_get_subpixel_maxpos(res, txshift, tyshift, &subx, &suby));
01333     *xshift = txshift - (Nx - 1) + subx;
01334     *xshift *= -1;
01335     *yshift = tyshift - (Ny - 1) + suby;
01336     *yshift *= -1;
01337 
01338     end_skip;
01339 
01340     cpl_image_delete(fft1);
01341     cpl_image_delete(fft2);
01342     cpl_image_delete(img);
01343     cpl_image_delete(template);
01344     cpl_image_delete(zimg);
01345     cpl_image_delete(ztemp);
01346     cpl_image_delete(res);
01347 
01348     return cpl_error_get_code();
01349 }
01350 
01351 
01352 /*----------------------------------------------------------------------------*/
01358 /*----------------------------------------------------------------------------*/
01359 static const char * visir_get_capa(const cpl_propertylist * plist)
01360 {
01361     const char  * capa = "Pb with Capa";
01362     const char  * sval;
01363     double        mean;
01364 
01365 
01366     skip_if (0);
01367 
01368 
01369     /* Get the instrument mode */
01370     sval = visir_pfits_get_insmode(plist);
01371     skip_if (0);
01372 
01373     /* Identify the mode */
01374     if (!strcmp(sval, "IMG")) {
01375         /* Imaging mode */
01376         mean  = visir_pfits_get_volt1dcta9(plist);
01377         mean += visir_pfits_get_volt1dctb9(plist);
01378     } else if (!strcmp(sval, "SPC") || !strcmp(sval, "SPCIMG")) {
01379         /* Spectro mode */
01380         mean  = visir_pfits_get_volt2dcta9(plist);
01381         mean += visir_pfits_get_volt2dctb9(plist);
01382     } else
01383         skip_if (1);
01384 
01385     skip_if (0);
01386 
01387     mean *= 0.5;
01388 
01389     /* Compute Capa value */
01390     if (mean < 1.0) {
01391         capa = "Large Capa";
01392     } else if (mean > 4.5) {
01393         capa = "Small Capa";
01394     }
01395 
01396     end_skip;    
01397 
01398     return capa;
01399 }
01400 
01401 #ifdef VISIR_MASK_HAS
01402 /*----------------------------------------------------------------------------*/
01422 /*----------------------------------------------------------------------------*/
01423 static cpl_boolean visir_mask_has(const cpl_mask * self, cpl_binary value,
01424                                   int ngood)
01425 {
01426     const cpl_binary * pself = cpl_mask_get_data_const(self);
01427     int                size  = cpl_mask_get_size_x(self)
01428                              * cpl_mask_get_size_y(self);
01429     int i;
01430 
01431     cpl_ensure(self,          CPL_ERROR_NULL_INPUT,          CPL_FALSE);
01432     cpl_ensure(ngood >= 0,    CPL_ERROR_ILLEGAL_INPUT,       CPL_FALSE);
01433     cpl_ensure(ngood <= size, CPL_ERROR_ACCESS_OUT_OF_RANGE, CPL_FALSE);
01434     cpl_ensure(value == CPL_BINARY_0 || value == CPL_BINARY_1,
01435                CPL_ERROR_INCOMPATIBLE_INPUT, CPL_FALSE);
01436 
01437     for (i = 0; i < ngood; i++) {
01438         /* Assume NULL is returned if size == 0 */
01439         const cpl_binary * ppos = memchr(pself, value, (size_t)size);
01440         if (ppos == NULL) break;
01441 
01442         size -= 1 + (int)(ppos - pself);
01443         pself = 1 + ppos;
01444     }
01445 
01446     return i == ngood ? CPL_TRUE : CPL_FALSE;
01447 }
01448 #endif

Generated on Mon Feb 6 15:23:49 2012 for VISIR Pipeline Reference Manual by  doxygen 1.5.8