KMOS Pipeline Reference Manual  1.3.11
kmo_fits_strip.c
00001 /*
00002  * This file is part of the KMOS Pipeline
00003  * Copyright (C) 2002,2003 European Southern Observatory
00004  *
00005  * This program is free software; you can redistribute it and/or modify
00006  * it under the terms of the GNU General Public License as published by
00007  * the Free Software Foundation; either version 2 of the License, or
00008  * (at your option) any later version.
00009  *
00010  * This program is distributed in the hope that it will be useful,
00011  * but WITHOUT ANY WARRANTY; without even the implied warranty of
00012  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
00013  * GNU General Public License for more details.
00014  *
00015  * You should have received a copy of the GNU General Public License
00016  * along with this program; if not, write to the Free Software
00017  * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
00018  */
00019 
00020 #ifdef HAVE_CONFIG_H
00021 #include <config.h>
00022 #endif
00023 
00024 #include <math.h>
00025 #include <string.h>
00026 
00027 #include <cpl.h>
00028 
00029 #include "kmclipm_constants.h"
00030 #include "kmclipm_functions.h"
00031 
00032 #include "kmo_dfs.h"
00033 #include "kmo_error.h"
00034 #include "kmo_debug.h"
00035 
00036 static int kmo_fits_strip_create(cpl_plugin *);
00037 static int kmo_fits_strip_exec(cpl_plugin *);
00038 static int kmo_fits_strip_destroy(cpl_plugin *);
00039 static int kmo_fits_strip(cpl_parameterlist *, cpl_frameset *);
00040 
00041 static char kmo_fits_strip_description[] =
00042 "With this recipe KMOS fits frames can be stripped in following way:\n"
00043 "\n"
00044 "--noise\n"
00045 "All noise extensions will be removed. Only the data extensions remain.\n"
00046 "\n"
00047 "--angle\n"
00048 "Applies only to calibration products from kmo_flat and kmo_wave_cal.\n"
00049 "All extensions matching provided angle are kept, the others are removed.\n"
00050 "Supply a single integer value.\n"
00051 "\n"
00052 "--empty\n"
00053 "All empty extensions will be removed.\n"
00054 "\n"
00055 "--extension\n"
00056 "Supply a comma-separated string with integer values indicating the extensions\n"
00057 "to keep. The other extensions are removed (any data or noise information is\n"
00058 "disregarded, the values are interpreted absolutely)\n"
00059 "\n"
00060 "The parameters --noise, --angle and --empty can be combined.\n"
00061 "When --extension is specified, all other parameters are ignored.\n"
00062 "When no parameter is provided, no output will be generated.\n"
00063 "\n"
00064 "-------------------------------------------------------------------------------\n"
00065 "  Input files:\n"
00066 "\n"
00067 "   DO                    KMOS                                                  \n"
00068 "   category              Type   Explanation                    Required #Frames\n"
00069 "   --------              -----  -----------                    -------- -------\n"
00070 "   <none or any>         F2D or frame to strip                     Y       1   \n"
00071 "                         F3I or\n"
00072 "                         F2I or\n"
00073 "                         F1I or\n"
00074 "\n"
00075 "  Output files:\n"
00076 "\n"
00077 "   DO                    KMOS\n"
00078 "   category              Type   Explanation\n"
00079 "   --------              -----  -----------\n"
00080 "   STRIP                 F2D or Stripped frame\n"
00081 "                         F3I or \n"
00082 "                         F2I or \n"
00083 "                         F1I    \n"
00084 "-------------------------------------------------------------------------------\n"
00085 "\n";
00086 
00103 int cpl_plugin_get_info(cpl_pluginlist *list)
00104 {
00105     cpl_recipe *recipe = cpl_calloc(1, sizeof *recipe);
00106     cpl_plugin *plugin = &recipe->interface;
00107 
00108     cpl_plugin_init(plugin,
00109                         CPL_PLUGIN_API,
00110                         KMOS_BINARY_VERSION,
00111                         CPL_PLUGIN_TYPE_RECIPE,
00112                         "kmo_fits_strip",
00113                         "Strip noise, rotator and/or empty extensions from a "
00114                         "processed KMOS fits frame",
00115                         kmo_fits_strip_description,
00116                         "Alex Agudo Berbel",
00117                         "usd-help@eso.org",
00118                         kmos_get_license(),
00119                         kmo_fits_strip_create,
00120                         kmo_fits_strip_exec,
00121                         kmo_fits_strip_destroy);
00122 
00123     cpl_pluginlist_append(list, plugin);
00124 
00125     return 0;
00126 }
00127 
00135 static int kmo_fits_strip_create(cpl_plugin *plugin)
00136 {
00137     cpl_recipe *recipe = NULL;
00138     cpl_parameter *p = NULL;
00139 
00140     /* Check that the plugin is part of a valid recipe */
00141     if (cpl_plugin_get_type(plugin) == CPL_PLUGIN_TYPE_RECIPE) 
00142         recipe = (cpl_recipe *)plugin;
00143     else
00144         return -1;
00145 
00146     /* Create the parameters list in the cpl_recipe object */
00147     recipe->parameters = cpl_parameterlist_new();
00148 
00149     /* Fill the parameters list */
00150     /* --empty */
00151     p = cpl_parameter_new_value("kmos.kmo_fits_strip.empty",
00152                                 CPL_TYPE_BOOL,
00153                                 "TRUE: if empty extensions shall be removed,"
00154                                 " FALSE: otherwise",
00155                                 "kmos.kmo_fits_strip",
00156                                 FALSE);
00157     cpl_parameter_set_alias(p, CPL_PARAMETER_MODE_CLI, "empty");
00158     cpl_parameter_disable(p, CPL_PARAMETER_MODE_ENV);
00159     cpl_parameterlist_append(recipe->parameters, p);
00160 
00161     /* --noise */
00162     p = cpl_parameter_new_value("kmos.kmo_fits_strip.noise",
00163                                 CPL_TYPE_BOOL,
00164                                 "TRUE: if noise extensions shall be removed,"
00165                                 " FALSE: otherwise",
00166                                 "kmos.kmo_fits_strip",
00167                                 FALSE);
00168     cpl_parameter_set_alias(p, CPL_PARAMETER_MODE_CLI, "noise");
00169     cpl_parameter_disable(p, CPL_PARAMETER_MODE_ENV);
00170     cpl_parameterlist_append(recipe->parameters, p);
00171 
00172     /* --angle */
00173     p = cpl_parameter_new_value("kmos.kmo_fits_strip.angle",
00174                                 CPL_TYPE_INT,
00175                                 "All extensions not matching provided angle "
00176                                 "are stripped.",
00177                                 "kmos.kmo_fits_strip",
00178                                 -1);
00179     cpl_parameter_set_alias(p, CPL_PARAMETER_MODE_CLI, "angle");
00180     cpl_parameter_disable(p, CPL_PARAMETER_MODE_ENV);
00181     cpl_parameterlist_append(recipe->parameters, p);
00182 
00183     /* --extension */
00184     p = cpl_parameter_new_value("kmos.kmo_fits_strip.extension",
00185                                 CPL_TYPE_STRING,
00186                                 "Comma-separated string with integers. "
00187                                 "All extensions matching these values are stripped.",
00188                                 "kmos.kmo_fits_strip",
00189                                 NULL);
00190     cpl_parameter_set_alias(p, CPL_PARAMETER_MODE_CLI, "extension");
00191     cpl_parameter_disable(p, CPL_PARAMETER_MODE_ENV);
00192     cpl_parameterlist_append(recipe->parameters, p);
00193 
00194     return 0;
00195 }
00196 
00202 static int kmo_fits_strip_exec(cpl_plugin *plugin)
00203 {
00204     cpl_recipe  *recipe;
00205 
00206     /* Get the recipe out of the plugin */
00207     if (cpl_plugin_get_type(plugin) == CPL_PLUGIN_TYPE_RECIPE) 
00208         recipe = (cpl_recipe *)plugin;
00209     else return -1 ;
00210 
00211     return kmo_fits_strip(recipe->parameters, recipe->frames);
00212 }
00213 
00219 static int kmo_fits_strip_destroy(cpl_plugin *plugin)
00220 {
00221     cpl_recipe *recipe;
00222 
00223     /* Get the recipe out of the plugin */
00224     if (cpl_plugin_get_type(plugin) == CPL_PLUGIN_TYPE_RECIPE) 
00225         recipe = (cpl_recipe *)plugin;
00226     else return -1 ;
00227 
00228     cpl_parameterlist_delete(recipe->parameters);
00229     return 0 ;
00230 }
00231 
00232 static const char * kmos_get_base_name(const char * self)
00233 {
00234     const char * p = self ? strrchr(self, '/') : NULL;
00235 
00236     return p ? p + 1 : self;
00237 }
00238 
00239 // kmo_dfs_save_main_header() doesn't allow to change ESO OCS ROT NAANGLE
00240 cpl_error_code kmo_save_header_fits_strip(cpl_propertylist *header,
00241                                           cpl_parameterlist *parlist,
00242                                           cpl_frameset *frameset,
00243                                           const char *filename)
00244 {
00245 #define PRO_REC_PARAMi_NAME         "ESO PRO REC1 PARAM%d NAME"
00246 #define PRO_REC_PARAMi_VALUE        "ESO PRO REC1 PARAM%d VALUE"
00247 
00248     cpl_error_code      err                 = CPL_ERROR_NONE;
00249     char                *ggg                = NULL,
00250                         cval[1024];
00251     const char          *kname              = NULL;
00252     const cpl_parameter *param              = NULL;
00253     cpl_frame           *product_frame      = NULL;
00254     int                 npar                = 0;
00255 
00256     KMO_TRY
00257     {
00258         // setup DFS manually (no MD5 calculated...)
00259         KMO_TRY_EXIT_IF_ERROR(
00260             cpl_propertylist_update_string(header, "PIPEFILE", "strip.fits"));
00261         KMO_TRY_EXIT_IF_ERROR(
00262             cpl_propertylist_update_string(header, CPL_DFS_PRO_CATG, STRIP));
00263         KMO_TRY_EXIT_IF_ERROR(
00264             cpl_propertylist_update_string(header, "ESO PRO REC1 ID", cpl_func));
00265         ggg = cpl_sprintf("cpl-%d.%d.%d", cpl_version_get_major(), cpl_version_get_minor(), cpl_version_get_micro());
00266         KMO_TRY_EXIT_IF_ERROR(
00267             cpl_propertylist_update_string(header, "ESO PRO REC1 DRS ID", ggg));
00268         cpl_free(ggg); ggg = NULL;
00269         KMO_TRY_EXIT_IF_ERROR(
00270             cpl_propertylist_update_string(header, "ESO PRO REC1 PIPE ID", VERSION));
00271         KMO_TRY_EXIT_IF_ERROR(
00272             cpl_propertylist_update_string(header, "ESO PRO REC1 CAL1 NAME", kmos_get_base_name(filename)));
00273         KMO_TRY_EXIT_IF_ERROR(
00274             cpl_propertylist_update_string(header, "ESO PRO REC1 CAL1 CATG", COMMANDLINE));
00275         KMO_TRY_EXIT_IF_ERROR(
00276             cpl_propertylist_update_string(header, "ESO PRO REC1 CAL1 DATAMD5", cpl_propertylist_get_string(header, "DATAMD5")));
00277         KMO_TRY_CHECK_ERROR_STATE();
00278 
00279         while (param != NULL) {
00280             char *pval, *dval;
00281             ++npar;
00282 
00283             kname = cpl_parameter_get_alias(param, CPL_PARAMETER_MODE_CLI);
00284             const char * comment = cpl_parameter_get_help(param);
00285             switch (cpl_parameter_get_type(param)) {
00286             case CPL_TYPE_BOOL:
00287                 pval = cpl_strdup(cpl_parameter_get_bool(param) == 1 ? "true" : "false");
00288                 dval = cpl_sprintf("Default: %s", cpl_parameter_get_default_bool(param) == 1 ? "true" : "false");
00289                 break;
00290             case CPL_TYPE_INT:
00291                 pval = cpl_sprintf("%d", cpl_parameter_get_int(param));
00292                 dval = cpl_sprintf("Default: %d", cpl_parameter_get_default_int(param));
00293                 break;
00294             case CPL_TYPE_DOUBLE:
00295                 pval = cpl_sprintf("%g", cpl_parameter_get_double(param));
00296                 dval = cpl_sprintf("Default: %g", cpl_parameter_get_default_double(param));
00297                 break;
00298             case CPL_TYPE_STRING:
00299                 pval = cpl_strdup(cpl_parameter_get_string(param));
00300                 dval = cpl_sprintf("Default: '%s'", cpl_parameter_get_default_string(param));
00301                 break;
00302             default:
00303                 /* Theoretically impossible to get here */
00304                 KMO_TRY_ASSURE(1==0,
00305                                CPL_ERROR_UNSPECIFIED,
00306                                "what?");
00307             }
00308             snprintf(cval, 1024, PRO_REC_PARAMi_NAME, npar);
00309             cpl_propertylist_update_string(header, cval, kname);
00310             cpl_propertylist_set_comment(header, cval, comment);
00311 
00312             snprintf(cval, 1024, PRO_REC_PARAMi_VALUE, npar);
00313             cpl_propertylist_update_string(header, cval, pval);
00314             cpl_propertylist_set_comment(header, cval, dval);
00315 
00316             cpl_free((void*)pval);
00317             cpl_free((void*)dval);
00318 
00319             param = cpl_parameterlist_get_next_const(parlist);
00320         }
00321         KMO_TRY_CHECK_ERROR_STATE();
00322 
00323         cpl_msg_info(cpl_func, "Writing FITS %s product(%s): %s", "propertylist", "STRIP", "strip.fits");
00324         KMO_TRY_EXIT_IF_NULL(
00325             product_frame = cpl_frame_new());
00326         KMO_TRY_EXIT_IF_ERROR(
00327             cpl_frame_set_filename(product_frame, "strip.fits"));
00328         KMO_TRY_EXIT_IF_ERROR(
00329             cpl_frame_set_tag(product_frame, "STRIP"));
00330         KMO_TRY_EXIT_IF_ERROR(
00331             cpl_frame_set_type(product_frame, CPL_FRAME_TYPE_ANY));
00332         KMO_TRY_EXIT_IF_ERROR(
00333             cpl_frame_set_group(product_frame, CPL_FRAME_GROUP_PRODUCT));
00334         KMO_TRY_EXIT_IF_ERROR(
00335             cpl_frame_set_level(product_frame, CPL_FRAME_LEVEL_FINAL));
00336         KMO_TRY_EXIT_IF_ERROR(
00337             cpl_frameset_insert(frameset, product_frame));
00338 
00339         KMO_TRY_EXIT_IF_ERROR(
00340             cpl_propertylist_save(header, "strip.fits", CPL_IO_CREATE));
00341     }
00342     KMO_CATCH
00343     {
00344         KMO_CATCH_MSG();
00345         err = cpl_error_get_code();
00346     }
00347 
00348     return err;
00349 }
00350 
00369 static int kmo_fits_strip(cpl_parameterlist *parlist, cpl_frameset *frameset)
00370 {
00371     int                 ret_val             = 0,
00372                         nr_devices          = 0,
00373                         remove_noise        = FALSE,
00374                         remove_empty        = FALSE,
00375                         remove_angle        = FALSE,
00376                         found_angle         = FALSE,
00377                         isCalFrame          = 0,
00378                         isMasterFlat        = 0,
00379                         actDetNr            = 0,
00380                         cal_device_nr       = 0,
00381                         dummy               = 0,
00382                         index               = 0,
00383                         i                   = 0;
00384     double              angle               = 0.,
00385                         tmp_angle           = 0.,
00386                         ret_angle           = 0.,
00387                         secClosestAng       = 0.,
00388                         ocsRotAngle         = 0.,
00389                         proRotAngle         = 0.,
00390                         *pextension         = NULL;
00391     cpl_propertylist    *header             = NULL,
00392                         *sub_header         = NULL;
00393     cpl_imagelist       *cube               = NULL;
00394     cpl_image           *img                = NULL;
00395     cpl_vector          *vec                = NULL,
00396                         *extension          = NULL;
00397     main_fits_desc      desc;
00398     cpl_frame           *frame              = NULL;
00399     const char          *filename           = NULL,
00400                         *extension_txt      = NULL;
00401     char                **split             = NULL;
00402     kmclipm_vector      *kv                 = NULL;
00403 
00404     KMO_TRY
00405     {
00406         kmo_init_fits_desc(&desc);
00407 
00408         /* --- check input --- */
00409         KMO_TRY_ASSURE((parlist != NULL) &&
00410                        (frameset != NULL),
00411                        CPL_ERROR_NULL_INPUT,
00412                        "Not all input data is provided!");
00413 
00414         KMO_TRY_ASSURE(cpl_frameset_get_size(frameset) == 1,
00415                        CPL_ERROR_NULL_INPUT,
00416                        "A fits-file must be provided!");
00417 
00418         KMO_TRY_EXIT_IF_NULL(
00419             frame = kmo_dfs_get_frame(frameset, "0"));
00420 
00421         KMO_TRY_EXIT_IF_NULL(
00422             filename = cpl_frame_get_filename(frame));
00423 
00424         desc = kmo_identify_fits_header(filename);
00425         KMO_TRY_CHECK_ERROR_STATE_MSG("Provided fits file doesn't seem to be "
00426                                       "in KMOS-format!");
00427 
00428         KMO_TRY_ASSURE((desc.fits_type == f2d_fits) ||
00429                        (desc.fits_type == f3i_fits) ||
00430                        (desc.fits_type == f2i_fits) ||
00431                        (desc.fits_type == f1i_fits),
00432                        CPL_ERROR_ILLEGAL_INPUT,
00433                        "Input data hasn't correct data type "
00434                        "(KMOSTYPE must be F2D, F3I, F2I or F1I)!");
00435 
00436         KMO_TRY_ASSURE(kmo_dfs_set_groups(frameset, "kmo_fits_strip") == 1,
00437                        CPL_ERROR_ILLEGAL_INPUT,
00438                        "Cannot identify RAW and CALIB frames!");
00439 
00440         cpl_msg_info("", "--- Parameter setup for kmo_fits_strip ----");
00441         remove_empty = kmo_dfs_get_parameter_bool(parlist,
00442                                                   "kmos.kmo_fits_strip.empty");
00443         KMO_TRY_CHECK_ERROR_STATE();
00444         KMO_TRY_ASSURE((remove_empty == TRUE) ||
00445                        (remove_empty == FALSE),
00446                        CPL_ERROR_ILLEGAL_INPUT,
00447                        "empty must be TRUE or FALSE!");
00448         KMO_TRY_EXIT_IF_ERROR(
00449             kmo_dfs_print_parameter_help(parlist, "kmos.kmo_fits_strip.empty"));
00450 
00451         remove_noise = kmo_dfs_get_parameter_bool(parlist,
00452                                                   "kmos.kmo_fits_strip.noise");
00453         KMO_TRY_CHECK_ERROR_STATE();
00454         KMO_TRY_ASSURE((remove_noise == TRUE) ||
00455                        (remove_noise == FALSE),
00456                        CPL_ERROR_ILLEGAL_INPUT,
00457                        "noise must be TRUE or FALSE!");
00458         KMO_TRY_EXIT_IF_ERROR(
00459             kmo_dfs_print_parameter_help(parlist, "kmos.kmo_fits_strip.noise"));
00460 
00461         angle = kmo_dfs_get_parameter_int(parlist,
00462                                           "kmos.kmo_fits_strip.angle");
00463         KMO_TRY_CHECK_ERROR_STATE();
00464         KMO_TRY_EXIT_IF_ERROR(
00465             kmo_dfs_print_parameter_help(parlist, "kmos.kmo_fits_strip.angle"));
00466 
00467         if (angle >= 0) {
00468             remove_angle = TRUE;
00469         }
00470 
00471         KMO_TRY_ASSURE(!remove_angle || ((angle >=0) && (angle < 360)),
00472                        CPL_ERROR_ILLEGAL_INPUT,
00473                        "angle must be between 0 and 360 degrees!");
00474 
00475         extension_txt = kmo_dfs_get_parameter_string(parlist,
00476                                                      "kmos.kmo_fits_strip.extension");
00477         KMO_TRY_CHECK_ERROR_STATE();
00478         KMO_TRY_EXIT_IF_ERROR(
00479             kmo_dfs_print_parameter_help(parlist, "kmos.kmo_fits_strip.extension"));
00480 
00481         if (strcmp(extension_txt, "") != 0) {
00482             // extract values from string
00483             KMO_TRY_EXIT_IF_NULL(
00484                 split = kmo_strsplit(extension_txt, ",", NULL));
00485 
00486             i = 0;
00487             while (split[i] != NULL) {
00488                 i++;
00489             }
00490 
00491             KMO_TRY_EXIT_IF_NULL(
00492                 extension = cpl_vector_new(i));
00493             KMO_TRY_EXIT_IF_NULL(
00494                 pextension = cpl_vector_get_data(extension));
00495             i = 0;
00496             while (split[i] != NULL) {
00497                 pextension[i] = atof(split[i]);
00498                 i++;
00499             }
00500             KMO_TRY_CHECK_ERROR_STATE();
00501 
00502             kmo_strfreev(split); split = NULL;
00503 
00504             // sort vector and remove double entries
00505             KMO_TRY_EXIT_IF_ERROR(
00506                 cpl_vector_sort(extension, CPL_SORT_ASCENDING));
00507 
00508             kv = kmclipm_vector_create(extension);
00509 
00510             for (i = 0; i < kmclipm_vector_get_size(kv)-1; i++) {
00511                 if (kmclipm_vector_get(kv, i, NULL) == kmclipm_vector_get(kv, i+1, NULL)) {
00512                     kmclipm_vector_reject(kv, i+1);
00513                 }
00514             }
00515             extension = kmclipm_vector_create_non_rejected(kv);
00516             kmclipm_vector_delete(kv); kv = NULL;
00517 
00518             KMO_TRY_ASSURE(cpl_vector_get_max(extension) <= desc.nr_ext,
00519                            CPL_ERROR_ILLEGAL_INPUT,
00520                            "The input frame has less extensions than specified in 'extensions'-parameter!");
00521             KMO_TRY_ASSURE(cpl_vector_get_max(extension) >= 1,
00522                            CPL_ERROR_ILLEGAL_INPUT,
00523                            "All values in 'extensions'-parameter must be > 1 !");
00524         }
00525 
00526         cpl_msg_info("", "-------------------------------------------");
00527 
00528         if ((!remove_empty) && (!remove_noise) && (!remove_angle) && (extension == NULL)) {
00529             // do nothing
00530             cpl_msg_info("","No action has been specified (angle-, noise- or empty-parameter),"
00531                             " therefore no output is generated");
00532         } else if (extension != NULL) {
00533             //
00534             // --- save primary extension ---
00535             //
00536             // load data and save it away again
00537             KMO_TRY_EXIT_IF_NULL(
00538                 header = kmo_dfs_load_primary_header(frameset, "0"));
00539             KMO_TRY_EXIT_IF_ERROR(
00540                 kmo_save_header_fits_strip(header, parlist, frameset, filename));
00541             cpl_propertylist_delete(header); header = NULL;
00542 
00543             //
00544             // loop extensions
00545             //
00546             KMO_TRY_EXIT_IF_NULL(
00547                 pextension = cpl_vector_get_data(extension));
00548             for (i = 0; i < cpl_vector_get_size(extension); i++) {
00549                 KMO_TRY_EXIT_IF_NULL(
00550                     sub_header = cpl_propertylist_load(filename, pextension[i]));
00551                 if ((desc.fits_type == f2d_fits) ||
00552                     (desc.fits_type == f2i_fits))
00553                 {
00554                     img = cpl_image_load(filename,CPL_TYPE_FLOAT, 0, pextension[i]);
00555                     if (CPL_ERROR_NONE != cpl_error_get_code()) {
00556                         cpl_error_reset();
00557                     }
00558                     KMO_TRY_EXIT_IF_ERROR(
00559                         kmo_dfs_save_image(img, STRIP, "", sub_header, 0./0.));
00560                     cpl_image_delete(img); img = NULL;
00561                 } else if (desc.fits_type == f3i_fits) {
00562                     cube = cpl_imagelist_load(filename,CPL_TYPE_FLOAT, pextension[i]);
00563                     if (CPL_ERROR_NONE != cpl_error_get_code()) {
00564                         cpl_error_reset();
00565                     }
00566                     KMO_TRY_EXIT_IF_ERROR(
00567                         kmo_dfs_save_cube(cube, STRIP, "", sub_header, 0./0.));
00568                     cpl_imagelist_delete(cube); cube = NULL;
00569                 } else if (desc.fits_type == f1i_fits) {
00570                     vec = cpl_vector_load(filename, pextension[i]);
00571                     if (CPL_ERROR_NONE != cpl_error_get_code()) {
00572                         cpl_error_reset();
00573                     }
00574                     KMO_TRY_EXIT_IF_NULL(
00575                         kv = kmclipm_vector_create(vec));
00576                     KMO_TRY_EXIT_IF_ERROR(
00577                         kmo_dfs_save_vector(kv, STRIP, "", sub_header, 0./0.));
00578                     kmclipm_vector_delete(kv); kv = NULL;
00579                 }
00580                 cpl_propertylist_delete(sub_header); sub_header = NULL;
00581             }
00582         } else {
00583             // check if it is a multi-angle-calibration file
00584             isCalFrame = FALSE;
00585             KMO_TRY_EXIT_IF_NULL(
00586                 sub_header = kmo_dfs_load_sub_header(frameset, "0", 1, FALSE));
00587             if (cpl_propertylist_has(sub_header, CAL_ROTANGLE)) {
00588                 isCalFrame = TRUE;
00589             }
00590             cpl_propertylist_delete(sub_header); sub_header = NULL;
00591 
00592             //
00593             // --- save primary extension ---
00594             //
00595             // load data and save it away again
00596             KMO_TRY_EXIT_IF_NULL(
00597                 header = kmo_dfs_load_primary_header(frameset, "0"));
00598 
00599             if (strcmp(MASTER_FLAT, cpl_propertylist_get_string(header, CPL_DFS_PRO_CATG))==0) {
00600                 isMasterFlat = TRUE;
00601             }
00602 
00603             if (remove_angle && isCalFrame) {
00604                 // update OCS.ROT.NAANGLE if it differs
00605                 ocsRotAngle = cpl_propertylist_get_double(header, ROTANGLE);
00606                 ocsRotAngle = kmclipm_strip_angle(&ocsRotAngle);
00607                 proRotAngle = kmclipm_cal_propertylist_find_angle(filename, 1, FALSE, angle,
00608                         &dummy, &secClosestAng);
00609                 KMO_TRY_CHECK_ERROR_STATE();
00610                 if (fabs(ocsRotAngle-proRotAngle) > 0.1) {
00611                     cpl_msg_warning("", "In the product the original ESO OCS ROT NAANGLE keyword "
00612                                         "has been updated with the chosen "
00613                                         "ESO PRO ROT NAANGLE (was: %g, is: %g)!", ocsRotAngle, proRotAngle);
00614                     KMO_TRY_EXIT_IF_ERROR(
00615                         cpl_propertylist_update_double(header, ROTANGLE, proRotAngle));
00616                 }
00617             }
00618 
00619             KMO_TRY_EXIT_IF_ERROR(
00620                 kmo_save_header_fits_strip(header, parlist, frameset, filename));
00621             cpl_propertylist_delete(header); header = NULL;
00622 
00623             if (!isCalFrame) {
00624                 if (!desc.ex_noise) {
00625                     nr_devices = desc.nr_ext;
00626                 } else {
00627                     nr_devices = desc.nr_ext / 2;
00628                 }
00629             } else {
00630                 nr_devices = 3;
00631             }
00632 
00633             if (isCalFrame) {
00634                 if (isMasterFlat) {
00635                     remove_noise = !remove_noise;
00636                 }
00637             } else {
00638                 if (desc.ex_noise) {
00639                     remove_noise = !remove_noise;
00640                 }
00641             }
00642 
00643             actDetNr = 1;
00644             int i = 0, n = 0;
00645             for (i = 0; i < nr_devices; i++)
00646             {
00647                 // either loop noise or not
00648                 for (n = FALSE; n <= remove_noise; n++) {
00649                     if (isCalFrame) {
00650                         KMO_TRY_EXIT_IF_NULL(
00651                             header = kmclipm_cal_propertylist_load(filename, i+1, n, angle, &ret_angle));
00652                     } else {
00653                         KMO_TRY_EXIT_IF_NULL(
00654                             header = kmo_dfs_load_sub_header(frameset, "0", i + 1, n));
00655                     }
00656 
00657                     if (remove_angle) {
00658                         // examine angle
00659                         if (cpl_propertylist_has(header, CAL_ROTANGLE)) {
00660                             tmp_angle = cpl_propertylist_get_double(header, CAL_ROTANGLE);
00661                             KMO_TRY_CHECK_ERROR_STATE();
00662 
00663                             if (fabs(angle - tmp_angle) < 0.01) {
00664                                 found_angle = TRUE;
00665                                 isCalFrame = TRUE;
00666                             } else {
00667                                 found_angle = FALSE;
00668                             }
00669                         } else {
00670                             // frame doesn't seem to have the CAL_ROTANGLE keyword
00671                             // process all extensions
00672                             found_angle = TRUE;
00673                         }
00674                     } else {
00675                         found_angle = TRUE;
00676                     }
00677 
00678                     index = kmo_identify_index(filename, i+1, n);
00679                     if (found_angle) {
00680                         if ((desc.fits_type == f2d_fits) ||
00681                             (desc.fits_type == f2i_fits))
00682                         {
00683                             if (isCalFrame) {
00684                                 cal_device_nr = cpl_propertylist_get_int(header, CHIPINDEX);
00685                                 KMO_TRY_CHECK_ERROR_STATE();
00686                                 if (cal_device_nr == actDetNr) {
00687                                     KMO_TRY_EXIT_IF_ERROR(
00688                                         kmo_update_sub_keywords(header,
00689                                                                 n,
00690                                                                 FALSE,
00691                                                                 desc.frame_type,
00692                                                                 actDetNr));
00693                                     print_cal_angle_msg_once = FALSE;
00694                                     print_xcal_angle_msg_once = FALSE;
00695                                     KMO_TRY_EXIT_IF_NULL(
00696                                         img = kmo_dfs_load_cal_image(frameset, "0",
00697                                                                      i+1, n, angle,
00698                                                                      FALSE, NULL,
00699                                                                      &ret_angle, -1, 0, 0));
00700 
00701                                     if (fabs(angle-ret_angle) > 0.01) {
00702                                         cpl_msg_warning("","Angle provided: %g, angle found: %g", angle, ret_angle);
00703                                     }
00704                                     if (n == remove_noise) {
00705                                         actDetNr++;
00706                                     }
00707                                 }
00708                                 if (img != NULL) {
00709                                     KMO_TRY_EXIT_IF_ERROR(
00710                                         kmo_dfs_save_image(img, STRIP, "", header, 0./0.));
00711                                 }
00712                             } else {
00713                                 img = cpl_image_load(filename,CPL_TYPE_FLOAT, 0, index);
00714                                 if (CPL_ERROR_NONE != cpl_error_get_code()) {
00715                                     cpl_error_reset();
00716                                     if (!remove_empty) {
00717                                         KMO_TRY_EXIT_IF_ERROR(
00718                                             kmo_dfs_save_image(img, STRIP, "", header, 0./0.));
00719                                     }
00720                                 } else {
00721                                     KMO_TRY_EXIT_IF_ERROR(
00722                                         kmo_dfs_save_image(img, STRIP, "", header, 0./0.));
00723                                 }
00724                             }
00725                             cpl_image_delete(img); img = NULL;
00726                         } else if (desc.fits_type == f3i_fits) {
00727                             cube = cpl_imagelist_load(filename,CPL_TYPE_FLOAT, index);
00728                             if (CPL_ERROR_NONE != cpl_error_get_code()) {
00729                                 cpl_error_reset();
00730                                 if (!remove_empty) {
00731                                     KMO_TRY_EXIT_IF_ERROR(
00732                                         kmo_dfs_save_cube(cube, STRIP, "", header, 0./0.));
00733                                 }
00734                             } else {
00735                                 KMO_TRY_EXIT_IF_ERROR(
00736                                     kmo_dfs_save_cube(cube, STRIP, "", header, 0./0.));
00737                             }
00738                             cpl_imagelist_delete(cube); cube = NULL;
00739                         } else if (desc.fits_type == f1i_fits) {
00740                             vec = cpl_vector_load(filename, index);
00741                             if (CPL_ERROR_NONE != cpl_error_get_code()) {
00742                                 cpl_error_reset();
00743                                 if (!remove_empty) {
00744                                     KMO_TRY_EXIT_IF_ERROR(
00745                                         kmo_dfs_save_vector(NULL, STRIP, "", header, 0./0.));
00746                                 }
00747                             } else {
00748                                 KMO_TRY_EXIT_IF_NULL(
00749                                     kv = kmclipm_vector_create(vec));
00750                                 KMO_TRY_EXIT_IF_ERROR(
00751                                     kmo_dfs_save_vector(kv, STRIP, "", header, 0./0.));
00752                             }
00753                             kmclipm_vector_delete(kv); kv = NULL;
00754                         }
00755                     } // if (found_angle)
00756                     cpl_propertylist_delete(header); header = NULL;
00757                 } // for (n)
00758             } // for (i = nr_devices)
00759         } // if ((!remove_empty) && (!remove_noise) && (!remove_angle))
00760     }
00761     KMO_CATCH
00762     {
00763         KMO_CATCH_MSG();
00764 
00765         ret_val = -1;
00766     }
00767 
00768     cpl_propertylist_delete(header); header = NULL;
00769     cpl_imagelist_delete(cube); cube = NULL;
00770     cpl_image_delete(img); img = NULL;
00771     kmclipm_vector_delete(kv); kv = NULL;
00772     kmo_free_fits_desc(&desc);
00773     cpl_vector_delete(extension); extension = NULL;
00774 
00775     return ret_val;
00776 }
00777