visir_util_repack.c

00001 /* $Id: visir_util_repack.c,v 1.72 2012/01/13 12:02:03 jtaylor 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: jtaylor $
00023  * $Date: 2012/01/13 12:02:03 $
00024  * $Revision: 1.72 $
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 "visir_recipe.h"
00037 
00038 /* Verify self-sufficiency of CPL header files by including system files last */
00039 #include <string.h>
00040 
00041 /*-----------------------------------------------------------------------------
00042                                 Defines
00043  -----------------------------------------------------------------------------*/
00044 
00045 #ifndef VISIR_UTIL_REPACK_CONAD
00046 #define VISIR_UTIL_REPACK_CONAD 1.1
00047 #endif
00048 
00049 #define RECIPE_STRING   "visir_util_repack"
00050 
00051 #define VISIR_DRS_CUMOFFSETX "ESO DRS CUMOFFSETX"
00052 #define VISIR_DRS_CUMOFFSETY "ESO DRS CUMOFFSETY"
00053 /* FIXME: Change to ESO DRS OUT1 CONAD when that is supported by mime */
00054 #define VISIR_DRS_CONAD      "ESO DET OUT1 CONAD"
00055 
00056 /*
00057   FIXME: Manual replacement of the keys needed by the Austrian mime code:
00058     perl -pi -e 's/\bESO DRS CUMOFFSET\B/ESO SEQ CUMOFFSET/g'
00059              -e 's/\bESO DRS OUT1 CONAD\b/ESO DET OUT1 CONAD/g'
00060             visir_util_repack_*.fits
00061 */
00062 
00063 
00064 /*-----------------------------------------------------------------------------
00065                             Private Functions prototypes
00066  -----------------------------------------------------------------------------*/
00067 
00068 static cpl_error_code visir_util_repack_one(cpl_frameset *,
00069                                             irplib_framelist *, int,
00070                                             const cpl_parameterlist *,
00071                                             const cpl_image *);
00072 
00073 static cpl_error_code visir_util_repack_one_(cpl_frameset *,
00074                                              irplib_framelist *, int,
00075                                              const cpl_parameterlist *,
00076                                              const char * tag,
00077                                              const cpl_image *);
00078 
00079 static cpl_error_code visir_util_repack_check(const cpl_image *,
00080                                               const cpl_imagelist *,
00081                                               const cpl_imagelist *);
00082 
00083 cpl_recipe_define(visir_util_repack, VISIR_BINARY_VERSION,
00084                   "Lars Lundin", PACKAGE_BUGREPORT, "2011", 
00085                   "Conversion of raw CUBE2 or BURST images to on- and off-cubes",
00086                   "The files listed in the Set Of Frames (sof-file) "
00087                   "must be tagged:\n"
00088                   "VISIR-CUBE2-raw-file.fits " VISIR_UTIL_REPACK_RAW
00089                   "\nor\n"
00090                   "VISIR-BURST-raw-file.fits " VISIR_IMG_BURST"\n"
00091                   "VISIR-BURST-bpm-file.fits " VISIR_CALIB_STATIC_MASK
00092                   "\nFor BURST data it will remove planes where the chopper "
00093                   "switched from on <-> off based on the "
00094                   "timestamps in the header."
00095                   "\nThe product(s) will have a FITS card\n"
00096                   "'HIERARCH ESO PRO CATG' with a value of one of:\n"
00097                   VISIR_UTIL_REPACK_A_ON_PROCATG  " (NodPos: A, ChopPos: on)\n"
00098                   VISIR_UTIL_REPACK_A_OFF_PROCATG " (NodPos: A, ChopPos: off)\n"
00099                   VISIR_UTIL_REPACK_B_ON_PROCATG  " (NodPos: B, ChopPos: on)\n"
00100                   VISIR_UTIL_REPACK_B_OFF_PROCATG " (NodPos: B, ChopPos: off)\n"
00101                   /* FIXME: reimplement
00102                   "Additionally, the recipe collapses the on- and off-cubes, "
00103                   "these product(s) will have a FITS card\n"
00104                   "'HIERARCH ESO PRO CATG' with a value of one of:\n"
00105                   VISIR_UTIL_REPACK_MEAN_A_ON_PROCATG
00106                   " (NodPos: A, ChopPos: on)\n"
00107                   VISIR_UTIL_REPACK_MEAN_A_OFF_PROCATG
00108                   " (NodPos: A, ChopPos: off)\n"
00109                   VISIR_UTIL_REPACK_MEAN_B_ON_PROCATG
00110                   " (NodPos: B, ChopPos: on)\n"
00111                   VISIR_UTIL_REPACK_MEAN_B_OFF_PROCATG
00112                   " (NodPos: B, ChopPos: off)\n" */
00113                   "For CUBE2, the recipe will produce a static "
00114                   "bad-pixel map, it will have a FITS card\n"
00115                   "'HIERARCH ESO PRO CATG' with a value of:\n"
00116                   VISIR_CALIB_STATIC_MASK"\n"
00117                   );
00118 
00119 /*----------------------------------------------------------------------------*/
00123 /*----------------------------------------------------------------------------*/
00124 
00125 /*-----------------------------------------------------------------------------
00126                                 Functions code
00127  -----------------------------------------------------------------------------*/
00128 
00129 
00130 /*----------------------------------------------------------------------------*/
00137 /*----------------------------------------------------------------------------*/
00138 static cpl_image *
00139 cpl_imagelist_pop(cpl_imagelist * list)
00140 {
00141     if (cpl_imagelist_get_size(list) == 0)
00142         return NULL;
00143     return cpl_imagelist_unset(list, cpl_imagelist_get_size(list) - 1);
00144 }
00145 
00146 
00147 /*----------------------------------------------------------------------------*/
00155 /*----------------------------------------------------------------------------*/
00156 static cpl_error_code
00157 visir_util_repack_fill_parameterlist(cpl_parameterlist * self)
00158 {
00159     const char * context = PACKAGE "." RECIPE_STRING;
00160     cpl_error_code err;
00161 
00162     cpl_ensure_code(self, CPL_ERROR_NULL_INPUT);
00163 
00164     /* Fill the parameters list */
00165 
00166     /* --planestart */
00167     err = irplib_parameterlist_set_int(self, PACKAGE, RECIPE_STRING, "planestart",
00168                                        0, NULL, context, "Plane range startpoint.");
00169     cpl_ensure_code(!err, err);
00170 
00171     /* --ncycles */
00172     err = irplib_parameterlist_set_int(self, PACKAGE, RECIPE_STRING, "ncycles",
00173                                        -1, NULL, context, "Number of full "
00174                                        "on-off cycles to repack. <= 0 for all.");
00175     /* --trimlow */
00176     err = irplib_parameterlist_set_int(self, PACKAGE, RECIPE_STRING, "trimlow",
00177                                        0, NULL, context, "Burst data only. "
00178                                        "Number of additional planes to cut "
00179                                        "from before each plane with chopper "
00180                                        "movement.");
00181     cpl_ensure_code(!err, err);
00182 
00183     /* --trimhigh */
00184     err = irplib_parameterlist_set_int(self, PACKAGE, RECIPE_STRING, "trimhigh",
00185                                        0, NULL, context, "Burst data only. "
00186                                        "Number of additional planes to cut "
00187                                        "from after each plane with chopper "
00188                                        "movement.\n A value of -1 does not "
00189                                        "skip the plane of the movement.");
00190     cpl_ensure_code(!err, err);
00191 
00192     /* --bkgcorrect */
00193     err =
00194         irplib_parameterlist_set_bool(self, PACKAGE, RECIPE_STRING, "bkgcorrect",
00195                                       CPL_FALSE, NULL, context, "Output "
00196                                       " background corrected planes by "
00197                                       " subtracting chop planes instead of "
00198                                       " outputting each plane");
00199     cpl_ensure_code(!err, err);
00200 
00201     /* --bkgcorrect */
00202     err =
00203         irplib_parameterlist_set_bool(self, PACKAGE, RECIPE_STRING, "error",
00204                                       CPL_FALSE, NULL, context, "Output error map"
00205                                       " by assuming  poisson distributed photon "
00206                                       "counts. Error will be sqrt(2*|on - off|)."
00207                                       " Implies --bkgcorrect.");
00208     cpl_ensure_code(!err, err);
00209 
00210     return CPL_ERROR_NONE;
00211 }
00212 
00213 
00214 /*----------------------------------------------------------------------------*/
00221 /*----------------------------------------------------------------------------*/
00222 static int visir_util_repack(cpl_frameset            * framelist,
00223                              const cpl_parameterlist * parlist)
00224 {
00225     cpl_errorstate     cleanstate = cpl_errorstate_get();
00226     cpl_error_code     errori = CPL_ERROR_NONE;
00227     irplib_framelist * allframes = NULL;
00228     irplib_framelist * rawframes = NULL;
00229     int                i, n;
00230     cpl_image *        bpm = NULL;
00231 
00232     /* Identify the RAW and CALIB frames in the input frameset */
00233     skip_if (visir_dfs_set_groups(framelist));
00234 
00235     /* Objects observation */
00236     allframes = irplib_framelist_cast(framelist);
00237     skip_if(allframes == NULL);
00238     rawframes = irplib_framelist_extract_regexp(allframes, "^(" VISIR_IMG_BURST
00239                                                 "|" VISIR_UTIL_REPACK_RAW
00240                                                 "|" VISIR_CALIB_STATIC_MASK ")$",
00241                                                 CPL_FALSE);
00242     skip_if (rawframes == NULL);
00243     
00244     n = irplib_framelist_get_size(rawframes);
00245 
00246     for (i = 0; i < n; i++) {
00247         if (visir_util_repack_one(framelist, rawframes, i, parlist, bpm)) {
00248             errori = cpl_error_set_where(cpl_func);
00249             if (errori != CPL_ERROR_NONE)
00250                 break;
00251         }
00252     }
00253     cpl_errorstate_dump(cleanstate, CPL_FALSE, NULL);
00254     cpl_errorstate_set(cleanstate);
00255 
00256     error_if(errori, errori, "Failed to repack cubes in %d frame(s)", n);
00257 
00258     end_skip;
00259 
00260     irplib_framelist_delete(allframes);
00261     irplib_framelist_delete(rawframes);
00262     cpl_image_delete(bpm);
00263 
00264     return cpl_error_get_code();
00265 }
00266 
00267 
00268 /*----------------------------------------------------------------------------*/
00277 /*----------------------------------------------------------------------------*/
00278 static cpl_error_code visir_util_repack_one(cpl_frameset * framelist,
00279                                             irplib_framelist * rawframes, int i,
00280                                             const cpl_parameterlist * parlist,
00281                                             const cpl_image * bpm)
00282 {
00283 
00284     const cpl_frame * rawframe = irplib_framelist_get_const(rawframes, i);
00285     const char * tag = cpl_frame_get_tag(rawframe);
00286 
00287     if (strcmp(tag, VISIR_CALIB_STATIC_MASK) == 0)
00288         return cpl_error_get_code();
00289 
00290     skip_if(irplib_framelist_load_propertylist(rawframes, i, 0, "^(NAXIS3|BITPIX|"
00291                                                VISIR_PFITS_DOUBLE_DIT "|"
00292                                                VISIR_PFITS_INT_NDITSKIP "|"
00293                                                VISIR_PFITS_INT_NDIT "|"
00294                                                IRPLIB_PFITS_WCS_REGEXP "|"
00295                                                VISIR_PFITS_INT_CHOP_NCYCLES "|"
00296                                                VISIR_PFITS_STRING_CHOP_START "|"
00297                                                VISIR_PFITS_DOUBLE_CHOP_FREQ "|"
00298                                                VISIR_PFITS_STRING_CHOP_START "|"
00299                                                VISIR_PFITS_STRING_OBS_START "|"
00300                                                VISIR_PFITS_DOUBLE_CHOP_THROW "|"
00301                                                VISIR_PFITS_STRING_PIXSCALE "|"
00302                                                VISIR_PFITS_STRING_FRAME_TYPE "|"
00303                                                VISIR_PFITS_DOUBLE_CUMOFFSETX "|"
00304                                                VISIR_PFITS_DOUBLE_CUMOFFSETY "|"
00305                                                VISIR_PFITS_STRING_NODPOS ")$",
00306                                                CPL_FALSE));
00307 
00308     bug_if(tag == NULL); /* Already extracted CUBE2 or BURST */
00309 
00310     skip_if(visir_util_repack_one_(framelist, rawframes, i, parlist, tag, bpm));
00311 
00312     end_skip;
00313 
00314     return cpl_error_get_code();
00315 }
00316 
00317 
00318 typedef enum {
00319     VISIR_DATA_CUBE2,
00320     VISIR_DATA_BURST
00321 } visir_data_type;
00322 
00323 /* convinience data structure to hold common data needed
00324  * to process one frame */
00325 typedef struct {
00326     int planestart;
00327     int planeend;
00328     int trimlow;
00329     int trimhigh;
00330     cpl_boolean bkgcorrect;
00331     cpl_boolean esterror;
00332     double conad;
00333     int nframes;
00334     const irplib_framelist * rawframes;
00335     int iframe;
00336     const cpl_propertylist * plist;
00337     visir_data_type datatype;
00338     cpl_type_bpp save_type;
00339 
00340     char * onname;
00341     char * offname;
00342     const char * remregexp;
00343 
00344     double pthrow;
00345     const char * comoffx;
00346     const char * comoffy;
00347     double offsetx;
00348     double offsety;
00349 
00350     const cpl_image * bpm;
00351     double bpmthresh;
00352 
00353     int naxis3;
00354     const char * procatgon;
00355     const char * procatgoff;
00356 } repack_frame_state;
00357 
00358 
00359 /*----------------------------------------------------------------------------*/
00371 /*----------------------------------------------------------------------------*/
00372 static repack_frame_state *
00373 init_frame_state(const irplib_framelist * rawframes, int iframe,
00374                  const cpl_parameterlist * parlist, const char * tag)
00375 {
00376     repack_frame_state * state = cpl_malloc(sizeof(repack_frame_state));
00377     int ndit, ncycles, planes_per_cycle;
00378 
00379     state->rawframes = rawframes;
00380 
00381     state->iframe = iframe;
00382 
00383     state->plist = irplib_framelist_get_propertylist_const(rawframes, iframe);
00384 
00385     state->naxis3     = visir_pfits_get_naxis3(state->plist);
00386 
00387     state->datatype =
00388         !strcmp(tag, "CUBE2") ? VISIR_DATA_CUBE2 : VISIR_DATA_BURST;
00389 
00390     state->bkgcorrect = irplib_parameterlist_get_bool(parlist, PACKAGE,
00391                                                       RECIPE_STRING,
00392                                                       "bkgcorrect");
00393 
00394     state->esterror = irplib_parameterlist_get_bool(parlist, PACKAGE,
00395                                                     RECIPE_STRING,
00396                                                     "error");
00397     state->bkgcorrect |= state->esterror;
00398 
00399     state->planestart = irplib_parameterlist_get_int(parlist, PACKAGE,
00400                                                      RECIPE_STRING,
00401                                                      "planestart");
00402 
00403     ndit = visir_pfits_get_ndit(state->plist);
00404     if (state->datatype == VISIR_DATA_CUBE2)
00405         planes_per_cycle = 2;
00406     else if (state->datatype == VISIR_DATA_BURST)
00407         planes_per_cycle = ndit * 2;
00408     else
00409         bug_if(1);
00410 
00411     ncycles = irplib_parameterlist_get_int(parlist, PACKAGE,
00412                                               RECIPE_STRING, "ncycles");
00413 
00414     state->planeend = state->planestart + ncycles * planes_per_cycle;
00415     /* ensure we always repack a multiple of a full cycle to get equal number
00416      * of on and off planes */
00417     if (state->planeend >= state->naxis3 || state->planeend <= 0) {
00418         if (state->planestart % planes_per_cycle == 0)
00419             state->planeend = state->naxis3;
00420         else
00421             state->planeend = state->naxis3 -
00422                 (planes_per_cycle - (state->planestart % planes_per_cycle));
00423     }
00424 
00425 #ifdef CPL_BPP_IEEE_FLOAT
00426 /* FIXME: Use just CPL_TYPE_UNSPECIFIED once CPL 5.3.1 is no longer supported */
00427     state->save_type = CPL_TYPE_UNSPECIFIED;
00428 #else
00429     state->save_type = cpl_propertylist_get_int(state->plist, "BITPIX");
00430 #endif
00431 
00432 
00433     state->trimlow = irplib_parameterlist_get_int(parlist, PACKAGE,
00434                                                   RECIPE_STRING,
00435                                                   "trimlow");
00436     state->trimhigh = irplib_parameterlist_get_int(parlist, PACKAGE,
00437                                                    RECIPE_STRING,
00438                                                    "trimhigh");
00439     state->conad = VISIR_UTIL_REPACK_CONAD;
00440 
00441     state->nframes = irplib_framelist_get_size(rawframes);
00442     state->remregexp  = "^(" VISIR_PFITS_DOUBLE_CUMOFFSETX
00443                         "|" VISIR_PFITS_DOUBLE_CUMOFFSETY ")$";
00444 
00445     /* Get the chopping throw in pixels */
00446     {
00447         const char * sscale       = visir_pfits_get_pixscale(state->plist);
00448         double pscale       = sscale ? atof(sscale) : 0.0;
00449         state->pthrow       = pscale > 0.0 ?
00450                               visir_pfits_get_chop_throw(state->plist) / pscale : 0.0;
00451     }
00452     /* Copy comments from CUMOFFSET[XY] */
00453     state->comoffx      = cpl_propertylist_get_comment
00454         (state->plist, VISIR_PFITS_DOUBLE_CUMOFFSETX);
00455     state->comoffy      = cpl_propertylist_get_comment
00456         (state->plist, VISIR_PFITS_DOUBLE_CUMOFFSETY);
00457     state->offsetx      = visir_pfits_get_cumoffsetx(state->plist);
00458     state->offsety      = visir_pfits_get_cumoffsety(state->plist);
00459 
00460     state->bpm = NULL; /* set and freed elsewhere */
00461     state->bpmthresh = VISIR_HCYCLE_BPM_THRESHOLD - VISIR_HCYCLE_OFFSET;
00462 
00463     if (state->bkgcorrect == CPL_FALSE) {
00464         const char * nodpos     = visir_pfits_get_nodpos(state->plist);
00465         const cpl_boolean is_a     = nodpos != NULL &&
00466             (strstr(nodpos, "A") || strstr(nodpos, "a")) ? CPL_TRUE : CPL_FALSE;
00467         state->procatgon = is_a ? VISIR_UTIL_REPACK_A_ON_PROCATG
00468             : VISIR_UTIL_REPACK_B_ON_PROCATG;
00469         state->procatgoff = is_a ? VISIR_UTIL_REPACK_A_OFF_PROCATG
00470             : VISIR_UTIL_REPACK_B_OFF_PROCATG;
00471         state->onname     = cpl_sprintf(RECIPE_STRING "_%s_on_%d"
00472                                         CPL_DFS_FITS, nodpos, 1+iframe);
00473         state->offname    = cpl_sprintf(RECIPE_STRING "_%s_off_%d"
00474                                         CPL_DFS_FITS, nodpos, 1+iframe);
00475 
00476         if (!is_a) {
00477             /* Verify that the NODPOS is either A or B */
00478             skip_if (nodpos == NULL);
00479             skip_if (strstr(nodpos, "B") == NULL && strstr(nodpos, "b") == NULL);
00480         }
00481     } else  {
00482         const char * nodpos     = visir_pfits_get_nodpos(state->plist);
00483         const cpl_boolean is_a     = nodpos != NULL &&
00484             (strstr(nodpos, "A") || strstr(nodpos, "a")) ? CPL_TRUE : CPL_FALSE;
00485         state->procatgon = is_a ? "BKG_CORRECTED_A" : "BKG_CORRECTED_B";
00486         state->onname    = cpl_sprintf(RECIPE_STRING "_%s_bkgcor_%d"
00487                                        CPL_DFS_FITS, nodpos, 1+iframe);
00488         if (state->esterror) {
00489             state->procatgoff = is_a ?
00490                 "BKG_CORRECTED_ERROR_A" : "BKG_CORRECTED_ERROR_B";
00491             state->offname    = cpl_sprintf(RECIPE_STRING "_%s_bkgcor_err_%d"
00492                                             CPL_DFS_FITS, nodpos, 1+iframe);
00493         } else {
00494             state->procatgoff = NULL;
00495             state->offname = NULL;
00496         }
00497 
00498     }
00499 
00500     if (state->offsety != 0.0)
00501         cpl_msg_warning(cpl_func, "Frame %d/%d has '%s' = %g != 0.0",
00502                         1+iframe, state->nframes,
00503                         VISIR_PFITS_DOUBLE_CUMOFFSETY, state->offsety);
00504 
00505     end_skip;
00506 
00507     return state;
00508 }
00509 
00510 
00511 static cpl_error_code
00512 subtract_images(const repack_frame_state * state,
00513                 cpl_imagelist * on, cpl_imagelist * off,
00514                 const cpl_propertylist * plist)
00515 {
00516     const int non = cpl_imagelist_get_size(on);
00517     cpl_image * errmap = NULL;
00518     cpl_image * imgabs = NULL;
00519     bug_if(cpl_imagelist_get_size(off) != non);
00520 
00521     for (int j = 0; j < non; j++) {
00522         cpl_image * onimg  = cpl_imagelist_get(on,  j);
00523         cpl_image * offimg  = cpl_imagelist_get(off,  j);
00524         cpl_image * minuend = onimg;
00525         cpl_image * subtrahend = offimg;
00526         cpl_image * errmap;
00527 
00528         /* burst data is not preprocessed so it negative */
00529         if (state->datatype == VISIR_DATA_BURST) {
00530             minuend = offimg;
00531             subtrahend = onimg;
00532         }
00533         cpl_image_subtract(minuend, subtrahend);
00534         /* FIXME: gain */
00535         if (state->esterror) {
00536             cpl_image_delete(errmap);
00537             cpl_image_delete(imgabs);
00538             imgabs = cpl_image_cast(minuend, CPL_TYPE_FLOAT);
00539             cpl_image_abs(imgabs);
00540             errmap = cpl_image_power_create(imgabs, 0.5);
00541             cpl_image_multiply_scalar(errmap, sqrt(2));
00542             skip_if(cpl_image_save(errmap, state->offname, CPL_BPP_IEEE_FLOAT,
00543                                    plist, CPL_IO_EXTEND));
00544         }
00545 
00546 
00547         /* Pending closure of DFS 10468:
00548            Duplicate on/off lists in all extension headers
00549            */
00550         skip_if(cpl_image_save(minuend, state->onname, state->save_type,
00551                                plist, CPL_IO_EXTEND));
00552     }
00553 
00554     end_skip;
00555 
00556     cpl_image_delete(errmap);
00557     cpl_image_delete(imgabs);
00558     return cpl_error_get_code();
00559 }
00560 
00561 
00562 /*----------------------------------------------------------------------------*/
00575 /*----------------------------------------------------------------------------*/
00576 static cpl_error_code
00577 append_images(const repack_frame_state * state,
00578               cpl_imagelist * images,
00579               const cpl_propertylist * plist, const cpl_boolean on)
00580 {
00581     const char * name = on ? state->onname : state->offname;
00582     const int n = cpl_imagelist_get_size(images);
00583 
00584     for (int j = 0; j < n; j++) {
00585         cpl_image * img  = cpl_imagelist_get(images,  j);
00586         /* burst data is not preprocessed so it needs flipping */
00587         if (state->datatype == VISIR_DATA_BURST) {
00588             cpl_image_multiply_scalar(img, -1);
00589             /* we want to save it in 16 bit, so decrease the offset by one
00590              * we don't really care about the offset as the images are
00591              * subtracted later anyway */
00592             cpl_image_add_scalar(img, -1);
00593         }
00594 
00595         /* Pending closure of DFS 10468:
00596            Duplicate on/off lists in all extension headers
00597            */
00598         skip_if(cpl_image_save(img,  name, state->save_type,
00599                                plist, CPL_IO_EXTEND));
00600     }
00601 
00602     end_skip;
00603 
00604     return cpl_error_get_code();
00605 }
00606 
00607 
00608 /*----------------------------------------------------------------------------*/
00621 /*----------------------------------------------------------------------------*/
00622 static cpl_error_code
00623 process_data(repack_frame_state * state, cpl_frameset * products,
00624              cpl_frameset * usedframes, const cpl_parameterlist * parlist,
00625              cpl_propertylist * onlist, cpl_propertylist * offlist)
00626 {
00627     int to_off = 0, halfcycle = 0;
00628     int nton = 0, ntoff = 0;
00629     int chunksize = 200;
00630     cpl_imagelist * on  = NULL;
00631     cpl_imagelist * off = NULL;
00632 
00633     /* chunksize must be a multiple of the period to avoid having a
00634      * #on-#off difference larger than chunksize */
00635     if (state->datatype == VISIR_DATA_BURST) {
00636         skip_if(visir_img_burst_find_delta_chop(state->plist,
00637                                                 &to_off, &halfcycle));
00638         chunksize = 2 * halfcycle;
00639         /* parameter sanity check, ensures equal length A and B lists */
00640         error_if(state->planeend - state->planestart < 2 * halfcycle,
00641                  CPL_ERROR_ILLEGAL_INPUT,
00642                  "Number of planes to be repacked must be larger than "
00643                  "a full cycle of %d planes.", halfcycle * 2);
00644     }
00645 
00646     for (int c = state->planestart;
00647          c < state->planeend + chunksize - 1;
00648          c += chunksize) {
00649         const int pend = c + chunksize > state->planeend ? state->planeend :
00650             c + chunksize;
00651         if (c >= pend)
00652             break;
00653 
00654         cpl_imagelist_delete(on);
00655         cpl_imagelist_delete(off);
00656         on  = cpl_imagelist_new();
00657         off = cpl_imagelist_new();
00658 
00659         /* sort a chunk of data */
00660         if (state->datatype == VISIR_DATA_CUBE2) {
00661             skip_if(visir_load_cube2_split(on, off, state->rawframes, state->iframe, c, pend));
00662 
00663             /* extract bpm from preprocessed burst data */
00664             if (state->iframe == 0 && c == state->planestart) {
00665                 cpl_image * bpm;
00666                 error_if(state->bpm, CPL_ERROR_ILLEGAL_INPUT, "CUBE2 data has "
00667                          "the badpixel map encoded. No extra STATIC_MASK "
00668                          "allowed");
00669                 bpm = cpl_image_duplicate(cpl_imagelist_get(off, 0));
00670                 bug_if(cpl_image_threshold(bpm, state->bpmthresh,
00671                                            state->bpmthresh, 0.0, 1.0));
00672                 state->bpm = bpm;
00673                 /* mime_estimate_error (DFS 10470) not needed
00674                  * as we create error maps in this recipe directly so only create
00675                  * one bpm */
00676                 skip_if(irplib_dfs_save_image(products, parlist,
00677                                               usedframes, state->bpm,
00678                                               CPL_BPP_8_UNSIGNED, RECIPE_STRING,
00679                                               VISIR_CALIB_STATIC_MASK, NULL,
00680                                               state->remregexp, visir_pipe_id,
00681                                               RECIPE_STRING "_bpm"
00682                                               CPL_DFS_FITS));
00683             }
00684         }
00685         else if (state->datatype == VISIR_DATA_BURST)
00686             skip_if(visir_load_burst(on, off,
00687                                      irplib_framelist_get_const(state->rawframes, state->iframe),
00688                                      state->plist, to_off, halfcycle, c, pend,
00689                                      state->trimlow, state->trimhigh));
00690         else
00691             error_if(1, CPL_ERROR_ILLEGAL_INPUT, "invalid data tag");
00692 
00693         nton += cpl_imagelist_get_size(on);
00694         ntoff += cpl_imagelist_get_size(off);
00695 
00696         /* if on last chunk, try to equalize on and off lists
00697          * as chunksize is a multiple of the period this should work
00698          * within a single chunk*/
00699         if (c + chunksize >= state->planeend) {
00700             int diff = nton - ntoff;
00701             if (diff != 0)
00702                 cpl_msg_warning(cpl_func, "Unequal number of planes in on "
00703                                 "and off list: #on %d, #off %d. Skipping %d"
00704                                 " planes.", nton, ntoff, abs(diff));
00705             if (diff > 0) {
00706                 for (int i = 0; i < diff; i++)
00707                     cpl_image_delete(cpl_imagelist_pop(on));
00708                 nton -= diff;
00709             }
00710             else {
00711                 for (int i = 0; i < -diff; i++)
00712                     cpl_image_delete(cpl_imagelist_pop(off));
00713                 ntoff += diff;
00714             }
00715         }
00716 
00717         if (state->bkgcorrect)
00718             skip_if(subtract_images(state, on, off, onlist));
00719         else {
00720             skip_if(append_images(state, on, onlist, CPL_TRUE));
00721             skip_if(append_images(state, off, offlist, CPL_FALSE));
00722         }
00723     }
00724     /* sanity check */
00725     error_if(nton != ntoff, CPL_ERROR_ILLEGAL_OUTPUT, "Unequal number of "
00726              "planes in on and offlist: #on %d, #off %d. Correct the"
00727              "recipe parameters to the period of the data.", nton, ntoff);
00728 
00729     end_skip;
00730 
00731     cpl_imagelist_delete(on);
00732     cpl_imagelist_delete(off);
00733 
00734     return cpl_error_get_code();
00735 }
00736 
00737 
00738 /*----------------------------------------------------------------------------*/
00748 /*----------------------------------------------------------------------------*/
00749 static
00750 cpl_error_code visir_util_repack_one_(cpl_frameset * framelist,
00751                                       irplib_framelist * rawframes, int iframe,
00752                                       const cpl_parameterlist * parlist,
00753                                       const char * tag,
00754                                       const cpl_image * bpm)
00755 {
00756     cpl_frameset  * products   = cpl_frameset_new();
00757     cpl_frameset  * usedframes = cpl_frameset_new();
00758     cpl_propertylist * onlist  = cpl_propertylist_new();
00759     cpl_propertylist * offlist = cpl_propertylist_new();
00760 
00761     repack_frame_state * state = init_frame_state(rawframes, iframe,
00762                                                   parlist, tag);
00763     state->bpm = bpm;
00764 
00765     cpl_msg_info(cpl_func, "Repacking frame %d/%d ('%s'=%g)",
00766                  1 + iframe, state->nframes, VISIR_DRS_CUMOFFSETY, state->pthrow);
00767 
00768     /* Need a copy of the WCS cards for subsequent beam stacking */
00769     bug_if(cpl_propertylist_copy_property_regexp(onlist, state->plist, "^("
00770                                                  IRPLIB_PFITS_WCS_REGEXP ")$",
00771                                                  CPL_FALSE));
00772 
00773     bug_if(cpl_propertylist_append_double(onlist, VISIR_DRS_CONAD, state->conad));
00774     bug_if(cpl_propertylist_set_comment(onlist, VISIR_DRS_CONAD, "Default "
00775                                         "single frame value: " IRPLIB_STRINGIFY
00776                                         (VISIR_UTIL_REPACK_CONAD)));
00777 
00778     bug_if(cpl_propertylist_append_double(onlist, VISIR_DRS_CUMOFFSETX,
00779                                           state->offsetx));
00780     bug_if(cpl_propertylist_append_double(onlist, VISIR_DRS_CUMOFFSETY,
00781                                           state->offsety));
00782     bug_if(cpl_propertylist_set_comment(onlist, VISIR_DRS_CUMOFFSETX,
00783                                         state->comoffx));
00784     bug_if(cpl_propertylist_set_comment(onlist, VISIR_DRS_CUMOFFSETY,
00785                                         state->comoffy));
00786     bug_if(cpl_propertylist_append(offlist, onlist));
00787     bug_if(cpl_propertylist_update_double(offlist, VISIR_DRS_CUMOFFSETY,
00788                                           state->offsety + state->pthrow));
00789 
00790     bug_if(cpl_frameset_insert(usedframes, cpl_frame_duplicate
00791                                (irplib_framelist_get_const(rawframes, iframe))));
00792 
00793 #ifdef VISIR_MIME_MULTI_MASK_SUPPORT
00794 #error VISIR_MIME_MULTI_MASK_SUPPORT not implemented
00795 #endif
00796 
00797     if (state->bkgcorrect) {
00798         skip_if(irplib_dfs_save_propertylist(products, parlist, usedframes,
00799                                              RECIPE_STRING, state->procatgon,
00800                                              offlist, state->remregexp,
00801                                              visir_pipe_id,
00802                                              state->onname));
00803         if (state->esterror)
00804             skip_if(irplib_dfs_save_propertylist(products, parlist, usedframes,
00805                                                  RECIPE_STRING, state->procatgoff,
00806                                                  offlist, state->remregexp,
00807                                                  visir_pipe_id,
00808                                                  state->offname));
00809     } else {
00810         /* Save each image in a separate extension */
00811         /* Do not save data in the primary data unit (DFS10475) */
00812         skip_if(irplib_dfs_save_propertylist(products, parlist, usedframes,
00813                                              RECIPE_STRING, state->procatgon,
00814                                              onlist, state->remregexp,
00815                                              visir_pipe_id, state->onname));
00816         skip_if(irplib_dfs_save_propertylist(products, parlist, usedframes,
00817                                              RECIPE_STRING, state->procatgoff,
00818                                              offlist, state->remregexp,
00819                                              visir_pipe_id, state->offname));
00820     }
00821 
00822     /* process the data */
00823     skip_if(process_data(state, products, usedframes, parlist, onlist, offlist));
00824 
00825     for (const cpl_frame * frame = cpl_frameset_get_first_const(products);
00826          frame != NULL;
00827          frame = cpl_frameset_get_next_const(products)) {
00828         cpl_frame * copy = cpl_frame_duplicate(frame);
00829         cpl_error_code error;
00830 
00831         error = cpl_frameset_insert(framelist, copy);
00832 
00833         if (error) break;
00834     }
00835 
00836     end_skip;
00837     cpl_propertylist_delete(onlist);
00838     cpl_propertylist_delete(offlist);
00839     cpl_free(state->onname);
00840     cpl_free(state->offname);
00841     cpl_frameset_delete(usedframes);
00842     cpl_frameset_delete(products);
00843     cpl_free(state);
00844     return 0;
00845 }
00846 
00847 
00848 /*----------------------------------------------------------------------------*/
00856 /*----------------------------------------------------------------------------*/
00857 static cpl_error_code visir_util_repack_check(const cpl_image     * self,
00858                                               const cpl_imagelist * on,
00859                                               const cpl_imagelist * off)
00860 {
00861     /* UNUSED due to chunking */
00862     cpl_image          * meanon  = cpl_imagelist_collapse_create(on);
00863     cpl_image          * meanoff = cpl_imagelist_collapse_create(off);
00864     const cpl_error_code err1  = cpl_image_subtract(meanon, meanoff);
00865     const cpl_error_code err2  = cpl_image_subtract(meanon, self);
00866     const unsigned bitmask = CPL_STATS_MIN | CPL_STATS_MAX | CPL_STATS_MEAN
00867         | CPL_STATS_MEDIAN | CPL_STATS_MEDIAN_DEV | CPL_STATS_STDEV;
00868 
00869     cpl_stats * stats = cpl_stats_new_from_image(meanon, bitmask);
00870 
00871     bug_if(err1 + err2);
00872 
00873     bug_if(cpl_stats_dump(stats, bitmask, stderr));
00874 
00875     end_skip;
00876 
00877     cpl_image_delete(meanon);
00878     cpl_image_delete(meanoff);
00879     cpl_stats_delete(stats);
00880 
00881     return cpl_error_get_code();
00882 
00883 }

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