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